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