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 : }
|