LCOV - code coverage report
Current view: top level - image/decoders - iccjpeg.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 61 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 3 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* This Source Code Form is subject to the terms of the Mozilla Public
       2             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       3             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       4             : 
       5             : /*
       6             :  * iccjpeg.c
       7             :  *
       8             :  * This file provides code to read and write International Color Consortium
       9             :  * (ICC) device profiles embedded in JFIF JPEG image files.  The ICC has
      10             :  * defined a standard format for including such data in JPEG "APP2" markers.
      11             :  * The code given here does not know anything about the internal structure
      12             :  * of the ICC profile data; it just knows how to put the profile data into
      13             :  * a JPEG file being written, or get it back out when reading.
      14             :  *
      15             :  * This code depends on new features added to the IJG JPEG library as of
      16             :  * IJG release 6b; it will not compile or work with older IJG versions.
      17             :  *
      18             :  * NOTE: this code would need surgery to work on 16-bit-int machines
      19             :  * with ICC profiles exceeding 64K bytes in size.  If you need to do that,
      20             :  * change all the "unsigned int" variables to "INT32".  You'll also need
      21             :  * to find a malloc() replacement that can allocate more than 64K.
      22             :  */
      23             : 
      24             : #include "iccjpeg.h"
      25             : #include <stdlib.h>  /* define malloc() */
      26             : 
      27             : 
      28             : /*
      29             :  * Since an ICC profile can be larger than the maximum size of a JPEG marker
      30             :  * (64K), we need provisions to split it into multiple markers.  The format
      31             :  * defined by the ICC specifies one or more APP2 markers containing the
      32             :  * following data:
      33             :  *      Identifying string      ASCII "ICC_PROFILE\0"  (12 bytes)
      34             :  *      Marker sequence number  1 for first APP2, 2 for next, etc (1 byte)
      35             :  *      Number of markers       Total number of APP2's used (1 byte)
      36             :  *      Profile data            (remainder of APP2 data)
      37             :  * Decoders should use the marker sequence numbers to reassemble the profile,
      38             :  * rather than assuming that the APP2 markers appear in the correct sequence.
      39             :  */
      40             : 
      41             : #define ICC_MARKER  (JPEG_APP0 + 2)      /* JPEG marker code for ICC */
      42             : #define ICC_OVERHEAD_LEN  14             /* size of non-profile data in APP2 */
      43             : #define MAX_BYTES_IN_MARKER  65533       /* maximum data len of a JPEG marker */
      44             : #define MAX_DATA_BYTES_IN_MARKER  (MAX_BYTES_IN_MARKER - ICC_OVERHEAD_LEN)
      45             : 
      46             : /*
      47             :  * Prepare for reading an ICC profile
      48             :  */
      49             : 
      50             : void
      51           0 : setup_read_icc_profile (j_decompress_ptr cinfo)
      52             : {
      53             :   /* Tell the library to keep any APP2 data it may find */
      54           0 :   jpeg_save_markers(cinfo, ICC_MARKER, 0xFFFF);
      55           0 : }
      56             : 
      57             : 
      58             : /*
      59             :  * Handy subroutine to test whether a saved marker is an ICC profile marker.
      60             :  */
      61             : 
      62             : static boolean
      63           0 : marker_is_icc (jpeg_saved_marker_ptr marker)
      64             : {
      65             :   return
      66           0 :     marker->marker == ICC_MARKER &&
      67           0 :     marker->data_length >= ICC_OVERHEAD_LEN &&
      68             :     /* verify the identifying string */
      69           0 :     GETJOCTET(marker->data[0]) == 0x49 &&
      70           0 :     GETJOCTET(marker->data[1]) == 0x43 &&
      71           0 :     GETJOCTET(marker->data[2]) == 0x43 &&
      72           0 :     GETJOCTET(marker->data[3]) == 0x5F &&
      73           0 :     GETJOCTET(marker->data[4]) == 0x50 &&
      74           0 :     GETJOCTET(marker->data[5]) == 0x52 &&
      75           0 :     GETJOCTET(marker->data[6]) == 0x4F &&
      76           0 :     GETJOCTET(marker->data[7]) == 0x46 &&
      77           0 :     GETJOCTET(marker->data[8]) == 0x49 &&
      78           0 :     GETJOCTET(marker->data[9]) == 0x4C &&
      79           0 :     GETJOCTET(marker->data[10]) == 0x45 &&
      80           0 :     GETJOCTET(marker->data[11]) == 0x0;
      81             : }
      82             : 
      83             : 
      84             : /*
      85             :  * See if there was an ICC profile in the JPEG file being read;
      86             :  * if so, reassemble and return the profile data.
      87             :  *
      88             :  * TRUE is returned if an ICC profile was found, FALSE if not.
      89             :  * If TRUE is returned, *icc_data_ptr is set to point to the
      90             :  * returned data, and *icc_data_len is set to its length.
      91             :  *
      92             :  * IMPORTANT: the data at **icc_data_ptr has been allocated with malloc()
      93             :  * and must be freed by the caller with free() when the caller no longer
      94             :  * needs it.  (Alternatively, we could write this routine to use the
      95             :  * IJG library's memory allocator, so that the data would be freed implicitly
      96             :  * at jpeg_finish_decompress() time.  But it seems likely that many apps
      97             :  * will prefer to have the data stick around after decompression finishes.)
      98             :  *
      99             :  * NOTE: if the file contains invalid ICC APP2 markers, we just silently
     100             :  * return FALSE.  You might want to issue an error message instead.
     101             :  */
     102             : 
     103             : boolean
     104           0 : read_icc_profile (j_decompress_ptr cinfo,
     105             :   JOCTET** icc_data_ptr,
     106             :   unsigned int* icc_data_len)
     107             : {
     108             :   jpeg_saved_marker_ptr marker;
     109           0 :   int num_markers = 0;
     110             :   int seq_no;
     111             :   JOCTET* icc_data;
     112             :   unsigned int total_length;
     113             : #define MAX_SEQ_NO  255        /* sufficient since marker numbers are bytes */
     114             :   char marker_present[MAX_SEQ_NO+1];      /* 1 if marker found */
     115             :   unsigned int data_length[MAX_SEQ_NO+1]; /* size of profile data in marker */
     116             :   unsigned int data_offset[MAX_SEQ_NO+1]; /* offset for data in marker */
     117             : 
     118           0 :   *icc_data_ptr = NULL;                   /* avoid confusion if FALSE return */
     119           0 :   *icc_data_len = 0;
     120             : 
     121             :   /* This first pass over the saved markers discovers whether there are
     122             :    * any ICC markers and verifies the consistency of the marker numbering.
     123             :    */
     124             : 
     125           0 :   for (seq_no = 1; seq_no <= MAX_SEQ_NO; seq_no++) {
     126           0 :     marker_present[seq_no] = 0;
     127             :   }
     128             : 
     129           0 :   for (marker = cinfo->marker_list; marker != NULL; marker = marker->next) {
     130           0 :     if (marker_is_icc(marker)) {
     131           0 :       if (num_markers == 0) {
     132           0 :         num_markers = GETJOCTET(marker->data[13]);
     133           0 :       } else if (num_markers != GETJOCTET(marker->data[13])) {
     134           0 :         return FALSE;  /* inconsistent num_markers fields */
     135             :       }
     136           0 :       seq_no = GETJOCTET(marker->data[12]);
     137           0 :       if (seq_no <= 0 || seq_no > num_markers) {
     138           0 :         return FALSE;   /* bogus sequence number */
     139             :       }
     140           0 :       if (marker_present[seq_no]) {
     141           0 :         return FALSE;   /* duplicate sequence numbers */
     142             :       }
     143           0 :       marker_present[seq_no] = 1;
     144           0 :       data_length[seq_no] = marker->data_length - ICC_OVERHEAD_LEN;
     145             :     }
     146             :   }
     147             : 
     148           0 :   if (num_markers == 0) {
     149           0 :     return FALSE;
     150             :   }
     151             : 
     152             :   /* Check for missing markers, count total space needed,
     153             :    * compute offset of each marker's part of the data.
     154             :    */
     155             : 
     156           0 :   total_length = 0;
     157           0 :   for (seq_no = 1; seq_no <= num_markers; seq_no++) {
     158           0 :     if (marker_present[seq_no] == 0) {
     159           0 :       return FALSE;  /* missing sequence number */
     160             :     }
     161           0 :     data_offset[seq_no] = total_length;
     162           0 :     total_length += data_length[seq_no];
     163             :   }
     164             : 
     165           0 :   if (total_length <= 0) {
     166           0 :     return FALSE;  /* found only empty markers? */
     167             :   }
     168             : 
     169             :   /* Allocate space for assembled data */
     170           0 :   icc_data = (JOCTET*) malloc(total_length * sizeof(JOCTET));
     171           0 :   if (icc_data == NULL) {
     172           0 :     return FALSE;   /* oops, out of memory */
     173             :   }
     174             : 
     175             :   /* and fill it in */
     176           0 :   for (marker = cinfo->marker_list; marker != NULL; marker = marker->next) {
     177           0 :     if (marker_is_icc(marker)) {
     178             :       JOCTET FAR* src_ptr;
     179             :       JOCTET* dst_ptr;
     180             :       unsigned int length;
     181           0 :       seq_no = GETJOCTET(marker->data[12]);
     182           0 :       dst_ptr = icc_data + data_offset[seq_no];
     183           0 :       src_ptr = marker->data + ICC_OVERHEAD_LEN;
     184           0 :       length = data_length[seq_no];
     185           0 :       while (length--) {
     186           0 :         *dst_ptr++ = *src_ptr++;
     187             :       }
     188             :     }
     189             :   }
     190             : 
     191           0 :   *icc_data_ptr = icc_data;
     192           0 :   *icc_data_len = total_length;
     193             : 
     194           0 :   return TRUE;
     195             : }

Generated by: LCOV version 1.13