1 // Copyright 2012 Google Inc. All Rights Reserved.
2 //
3 // Use of this source code is governed by a BSD-style license
4 // that can be found in the COPYING file in the root of the source
5 // tree. An additional intellectual property rights grant can be found
6 // in the file PATENTS. All contributing project authors may
7 // be found in the AUTHORS file in the root of the source tree.
8 // -----------------------------------------------------------------------------
9 //
10 // JPEG decode.
11
12 #include "./jpegdec.h"
13
14 #ifdef HAVE_CONFIG_H
15 #include "webp/config.h"
16 #endif
17
18 #include <stdio.h>
19
20 #ifdef WEBP_HAVE_JPEG
21 #include <jpeglib.h>
22 #include <jerror.h>
23 #include <setjmp.h>
24 #include <stdlib.h>
25 #include <string.h>
26
27 #include "webp/encode.h"
28 #include "./imageio_util.h"
29 #include "./metadata.h"
30
31 // -----------------------------------------------------------------------------
32 // Metadata processing
33
34 #ifndef JPEG_APP1
35 # define JPEG_APP1 (JPEG_APP0 + 1)
36 #endif
37 #ifndef JPEG_APP2
38 # define JPEG_APP2 (JPEG_APP0 + 2)
39 #endif
40
41 typedef struct {
42 const uint8_t* data;
43 size_t data_length;
44 int seq; // this segment's sequence number [1, 255] for use in reassembly.
45 } ICCPSegment;
46
SaveMetadataMarkers(j_decompress_ptr dinfo)47 static void SaveMetadataMarkers(j_decompress_ptr dinfo) {
48 const unsigned int max_marker_length = 0xffff;
49 jpeg_save_markers(dinfo, JPEG_APP1, max_marker_length); // Exif/XMP
50 jpeg_save_markers(dinfo, JPEG_APP2, max_marker_length); // ICC profile
51 }
52
CompareICCPSegments(const void * a,const void * b)53 static int CompareICCPSegments(const void* a, const void* b) {
54 const ICCPSegment* s1 = (const ICCPSegment*)a;
55 const ICCPSegment* s2 = (const ICCPSegment*)b;
56 return s1->seq - s2->seq;
57 }
58
59 // Extract ICC profile segments from the marker list in 'dinfo', reassembling
60 // and storing them in 'iccp'.
61 // Returns true on success and false for memory errors and corrupt profiles.
StoreICCP(j_decompress_ptr dinfo,MetadataPayload * const iccp)62 static int StoreICCP(j_decompress_ptr dinfo, MetadataPayload* const iccp) {
63 // ICC.1:2010-12 (4.3.0.0) Annex B.4 Embedding ICC Profiles in JPEG files
64 static const char kICCPSignature[] = "ICC_PROFILE";
65 static const size_t kICCPSignatureLength = 12; // signature includes '\0'
66 static const size_t kICCPSkipLength = 14; // signature + seq & count
67 int expected_count = 0;
68 int actual_count = 0;
69 int seq_max = 0;
70 size_t total_size = 0;
71 ICCPSegment iccp_segments[255];
72 jpeg_saved_marker_ptr marker;
73
74 memset(iccp_segments, 0, sizeof(iccp_segments));
75 for (marker = dinfo->marker_list; marker != NULL; marker = marker->next) {
76 if (marker->marker == JPEG_APP2 &&
77 marker->data_length > kICCPSkipLength &&
78 !memcmp(marker->data, kICCPSignature, kICCPSignatureLength)) {
79 // ICC_PROFILE\0<seq><count>; 'seq' starts at 1.
80 const int seq = marker->data[kICCPSignatureLength];
81 const int count = marker->data[kICCPSignatureLength + 1];
82 const size_t segment_size = marker->data_length - kICCPSkipLength;
83 ICCPSegment* segment;
84
85 if (segment_size == 0 || count == 0 || seq == 0) {
86 fprintf(stderr, "[ICCP] size (%d) / count (%d) / sequence number (%d)"
87 " cannot be 0!\n",
88 (int)segment_size, seq, count);
89 return 0;
90 }
91
92 if (expected_count == 0) {
93 expected_count = count;
94 } else if (expected_count != count) {
95 fprintf(stderr, "[ICCP] Inconsistent segment count (%d / %d)!\n",
96 expected_count, count);
97 return 0;
98 }
99
100 segment = iccp_segments + seq - 1;
101 if (segment->data_length != 0) {
102 fprintf(stderr, "[ICCP] Duplicate segment number (%d)!\n" , seq);
103 return 0;
104 }
105
106 segment->data = marker->data + kICCPSkipLength;
107 segment->data_length = segment_size;
108 segment->seq = seq;
109 total_size += segment_size;
110 if (seq > seq_max) seq_max = seq;
111 ++actual_count;
112 }
113 }
114
115 if (actual_count == 0) return 1;
116 if (seq_max != actual_count) {
117 fprintf(stderr, "[ICCP] Discontinuous segments, expected: %d actual: %d!\n",
118 actual_count, seq_max);
119 return 0;
120 }
121 if (expected_count != actual_count) {
122 fprintf(stderr, "[ICCP] Segment count: %d does not match expected: %d!\n",
123 actual_count, expected_count);
124 return 0;
125 }
126
127 // The segments may appear out of order in the file, sort them based on
128 // sequence number before assembling the payload.
129 qsort(iccp_segments, actual_count, sizeof(*iccp_segments),
130 CompareICCPSegments);
131
132 iccp->bytes = (uint8_t*)malloc(total_size);
133 if (iccp->bytes == NULL) return 0;
134 iccp->size = total_size;
135
136 {
137 int i;
138 size_t offset = 0;
139 for (i = 0; i < seq_max; ++i) {
140 memcpy(iccp->bytes + offset,
141 iccp_segments[i].data, iccp_segments[i].data_length);
142 offset += iccp_segments[i].data_length;
143 }
144 }
145 return 1;
146 }
147
148 // Returns true on success and false for memory errors and corrupt profiles.
149 // The caller must use MetadataFree() on 'metadata' in all cases.
ExtractMetadataFromJPEG(j_decompress_ptr dinfo,Metadata * const metadata)150 static int ExtractMetadataFromJPEG(j_decompress_ptr dinfo,
151 Metadata* const metadata) {
152 static const struct {
153 int marker;
154 const char* signature;
155 size_t signature_length;
156 size_t storage_offset;
157 } kJPEGMetadataMap[] = {
158 // Exif 2.2 Section 4.7.2 Interoperability Structure of APP1 ...
159 { JPEG_APP1, "Exif\0", 6, METADATA_OFFSET(exif) },
160 // XMP Specification Part 3 Section 3 Embedding XMP Metadata ... #JPEG
161 // TODO(jzern) Add support for 'ExtendedXMP'
162 { JPEG_APP1, "http://ns.adobe.com/xap/1.0/", 29, METADATA_OFFSET(xmp) },
163 { 0, NULL, 0, 0 },
164 };
165 jpeg_saved_marker_ptr marker;
166 // Treat ICC profiles separately as they may be segmented and out of order.
167 if (!StoreICCP(dinfo, &metadata->iccp)) return 0;
168
169 for (marker = dinfo->marker_list; marker != NULL; marker = marker->next) {
170 int i;
171 for (i = 0; kJPEGMetadataMap[i].marker != 0; ++i) {
172 if (marker->marker == kJPEGMetadataMap[i].marker &&
173 marker->data_length > kJPEGMetadataMap[i].signature_length &&
174 !memcmp(marker->data, kJPEGMetadataMap[i].signature,
175 kJPEGMetadataMap[i].signature_length)) {
176 MetadataPayload* const payload =
177 (MetadataPayload*)((uint8_t*)metadata +
178 kJPEGMetadataMap[i].storage_offset);
179
180 if (payload->bytes == NULL) {
181 const char* marker_data = (const char*)marker->data +
182 kJPEGMetadataMap[i].signature_length;
183 const size_t marker_data_length =
184 marker->data_length - kJPEGMetadataMap[i].signature_length;
185 if (!MetadataCopy(marker_data, marker_data_length, payload)) return 0;
186 } else {
187 fprintf(stderr, "Ignoring additional '%s' marker\n",
188 kJPEGMetadataMap[i].signature);
189 }
190 }
191 }
192 }
193 return 1;
194 }
195
196 #undef JPEG_APP1
197 #undef JPEG_APP2
198
199 // -----------------------------------------------------------------------------
200 // JPEG decoding
201
202 struct my_error_mgr {
203 struct jpeg_error_mgr pub;
204 jmp_buf setjmp_buffer;
205 };
206
my_error_exit(j_common_ptr dinfo)207 static void my_error_exit(j_common_ptr dinfo) {
208 struct my_error_mgr* myerr = (struct my_error_mgr*)dinfo->err;
209 fprintf(stderr, "libjpeg error: ");
210 dinfo->err->output_message(dinfo);
211 longjmp(myerr->setjmp_buffer, 1);
212 }
213
214 typedef struct {
215 struct jpeg_source_mgr pub;
216 const uint8_t* data;
217 size_t data_size;
218 } JPEGReadContext;
219
ContextInit(j_decompress_ptr cinfo)220 static void ContextInit(j_decompress_ptr cinfo) {
221 JPEGReadContext* const ctx = (JPEGReadContext*)cinfo->src;
222 ctx->pub.next_input_byte = ctx->data;
223 ctx->pub.bytes_in_buffer = ctx->data_size;
224 }
225
ContextFill(j_decompress_ptr cinfo)226 static boolean ContextFill(j_decompress_ptr cinfo) {
227 // we shouldn't get here.
228 ERREXIT(cinfo, JERR_FILE_READ);
229 return FALSE;
230 }
231
ContextSkip(j_decompress_ptr cinfo,long jump_size)232 static void ContextSkip(j_decompress_ptr cinfo, long jump_size) {
233 JPEGReadContext* const ctx = (JPEGReadContext*)cinfo->src;
234 size_t jump = (size_t)jump_size;
235 if (jump > ctx->pub.bytes_in_buffer) { // Don't overflow the buffer.
236 jump = ctx->pub.bytes_in_buffer;
237 }
238 ctx->pub.bytes_in_buffer -= jump;
239 ctx->pub.next_input_byte += jump;
240 }
241
ContextTerm(j_decompress_ptr cinfo)242 static void ContextTerm(j_decompress_ptr cinfo) {
243 (void)cinfo;
244 }
245
ContextSetup(volatile struct jpeg_decompress_struct * const cinfo,JPEGReadContext * const ctx)246 static void ContextSetup(volatile struct jpeg_decompress_struct* const cinfo,
247 JPEGReadContext* const ctx) {
248 cinfo->src = (struct jpeg_source_mgr*)ctx;
249 ctx->pub.init_source = ContextInit;
250 ctx->pub.fill_input_buffer = ContextFill;
251 ctx->pub.skip_input_data = ContextSkip;
252 ctx->pub.resync_to_restart = jpeg_resync_to_restart;
253 ctx->pub.term_source = ContextTerm;
254 ctx->pub.bytes_in_buffer = 0;
255 ctx->pub.next_input_byte = NULL;
256 }
257
ReadJPEG(const uint8_t * const data,size_t data_size,WebPPicture * const pic,int keep_alpha,Metadata * const metadata)258 int ReadJPEG(const uint8_t* const data, size_t data_size,
259 WebPPicture* const pic, int keep_alpha,
260 Metadata* const metadata) {
261 volatile int ok = 0;
262 int width, height;
263 int64_t stride;
264 volatile struct jpeg_decompress_struct dinfo;
265 struct my_error_mgr jerr;
266 uint8_t* volatile rgb = NULL;
267 JSAMPROW buffer[1];
268 JPEGReadContext ctx;
269
270 if (data == NULL || data_size == 0 || pic == NULL) return 0;
271
272 (void)keep_alpha;
273 memset(&ctx, 0, sizeof(ctx));
274 ctx.data = data;
275 ctx.data_size = data_size;
276
277 memset((j_decompress_ptr)&dinfo, 0, sizeof(dinfo)); // for setjmp sanity
278 dinfo.err = jpeg_std_error(&jerr.pub);
279 jerr.pub.error_exit = my_error_exit;
280
281 if (setjmp(jerr.setjmp_buffer)) {
282 Error:
283 MetadataFree(metadata);
284 jpeg_destroy_decompress((j_decompress_ptr)&dinfo);
285 goto End;
286 }
287
288 jpeg_create_decompress((j_decompress_ptr)&dinfo);
289 ContextSetup(&dinfo, &ctx);
290 if (metadata != NULL) SaveMetadataMarkers((j_decompress_ptr)&dinfo);
291 jpeg_read_header((j_decompress_ptr)&dinfo, TRUE);
292
293 dinfo.out_color_space = JCS_RGB;
294 dinfo.do_fancy_upsampling = TRUE;
295
296 jpeg_start_decompress((j_decompress_ptr)&dinfo);
297
298 if (dinfo.output_components != 3) {
299 goto Error;
300 }
301
302 width = dinfo.output_width;
303 height = dinfo.output_height;
304 stride = (int64_t)dinfo.output_width * dinfo.output_components * sizeof(*rgb);
305
306 if (stride != (int)stride ||
307 !ImgIoUtilCheckSizeArgumentsOverflow(stride, height)) {
308 goto Error;
309 }
310
311 rgb = (uint8_t*)malloc((size_t)stride * height);
312 if (rgb == NULL) {
313 goto Error;
314 }
315 buffer[0] = (JSAMPLE*)rgb;
316
317 while (dinfo.output_scanline < dinfo.output_height) {
318 if (jpeg_read_scanlines((j_decompress_ptr)&dinfo, buffer, 1) != 1) {
319 goto Error;
320 }
321 buffer[0] += stride;
322 }
323
324 if (metadata != NULL) {
325 ok = ExtractMetadataFromJPEG((j_decompress_ptr)&dinfo, metadata);
326 if (!ok) {
327 fprintf(stderr, "Error extracting JPEG metadata!\n");
328 goto Error;
329 }
330 }
331
332 jpeg_finish_decompress((j_decompress_ptr)&dinfo);
333 jpeg_destroy_decompress((j_decompress_ptr)&dinfo);
334
335 // WebP conversion.
336 pic->width = width;
337 pic->height = height;
338 ok = WebPPictureImportRGB(pic, rgb, (int)stride);
339 if (!ok) goto Error;
340
341 End:
342 free(rgb);
343 return ok;
344 }
345 #else // !WEBP_HAVE_JPEG
ReadJPEG(const uint8_t * const data,size_t data_size,struct WebPPicture * const pic,int keep_alpha,struct Metadata * const metadata)346 int ReadJPEG(const uint8_t* const data, size_t data_size,
347 struct WebPPicture* const pic, int keep_alpha,
348 struct Metadata* const metadata) {
349 (void)data;
350 (void)data_size;
351 (void)pic;
352 (void)keep_alpha;
353 (void)metadata;
354 fprintf(stderr, "JPEG support not compiled. Please install the libjpeg "
355 "development package before building.\n");
356 return 0;
357 }
358 #endif // WEBP_HAVE_JPEG
359
360 // -----------------------------------------------------------------------------
361