1 // ==========================================================
2 // JPEG Loader and writer
3 // Based on code developed by The Independent JPEG Group
4 //
5 // Design and implementation by
6 // - Floris van den Berg (flvdberg@wxs.nl)
7 // - Jan L. Nauta (jln@magentammt.com)
8 // - Markus Loibl (markus.loibl@epost.de)
9 // - Karl-Heinz Bussian (khbussian@moss.de)
10 // - Herv� Drolon (drolon@infonie.fr)
11 // - Jascha Wetzel (jascha@mainia.de)
12 // - Mihail Naydenov (mnaydenov@users.sourceforge.net)
13 //
14 // This file is part of FreeImage 3
15 //
16 // COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
17 // OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
18 // THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
19 // OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
20 // CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
21 // THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
22 // SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
23 // PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
24 // THIS DISCLAIMER.
25 //
26 // Use at your own risk!
27 // ==========================================================
28
29 #ifdef _MSC_VER
30 #pragma warning (disable : 4786) // identifier was truncated to 'number' characters
31 #endif
32
33 extern "C" {
34 #define XMD_H
35 #undef FAR
36 #include <setjmp.h>
37
38 #include "../LibJPEG/jinclude.h"
39 #include "../LibJPEG/jpeglib.h"
40 #include "../LibJPEG/jerror.h"
41 }
42
43 #include "FreeImage.h"
44 #include "Utilities.h"
45
46 #include "../Metadata/FreeImageTag.h"
47
48
49 // ==========================================================
50 // Plugin Interface
51 // ==========================================================
52
53 static int s_format_id;
54
55 // ----------------------------------------------------------
56 // Constant declarations
57 // ----------------------------------------------------------
58
59 #define INPUT_BUF_SIZE 4096 // choose an efficiently fread'able size
60 #define OUTPUT_BUF_SIZE 4096 // choose an efficiently fwrite'able size
61
62 #define EXIF_MARKER (JPEG_APP0+1) // EXIF marker / Adobe XMP marker
63 #define ICC_MARKER (JPEG_APP0+2) // ICC profile marker
64 #define IPTC_MARKER (JPEG_APP0+13) // IPTC marker / BIM marker
65
66 #define ICC_HEADER_SIZE 14 // size of non-profile data in APP2
67 #define MAX_BYTES_IN_MARKER 65533L // maximum data length of a JPEG marker
68 #define MAX_DATA_BYTES_IN_MARKER 65519L // maximum data length of a JPEG APP2 marker
69
70 #define MAX_JFXX_THUMB_SIZE (MAX_BYTES_IN_MARKER - 5 - 1)
71
72 #define JFXX_TYPE_JPEG 0x10 // JFIF extension marker: JPEG-compressed thumbnail image
73 #define JFXX_TYPE_8bit 0x11 // JFIF extension marker: palette thumbnail image
74 #define JFXX_TYPE_24bit 0x13 // JFIF extension marker: RGB thumbnail image
75
76 // ----------------------------------------------------------
77 // Typedef declarations
78 // ----------------------------------------------------------
79
80 typedef struct tagErrorManager {
81 /// "public" fields
82 struct jpeg_error_mgr pub;
83 /// for return to caller
84 jmp_buf setjmp_buffer;
85 } ErrorManager;
86
87 typedef struct tagSourceManager {
88 /// public fields
89 struct jpeg_source_mgr pub;
90 /// source stream
91 fi_handle infile;
92 FreeImageIO *m_io;
93 /// start of buffer
94 JOCTET * buffer;
95 /// have we gotten any data yet ?
96 boolean start_of_file;
97 } SourceManager;
98
99 typedef struct tagDestinationManager {
100 /// public fields
101 struct jpeg_destination_mgr pub;
102 /// destination stream
103 fi_handle outfile;
104 FreeImageIO *m_io;
105 /// start of buffer
106 JOCTET * buffer;
107 } DestinationManager;
108
109 typedef SourceManager* freeimage_src_ptr;
110 typedef DestinationManager* freeimage_dst_ptr;
111 typedef ErrorManager* freeimage_error_ptr;
112
113 // ----------------------------------------------------------
114 // Error handling
115 // ----------------------------------------------------------
116
117 /** Fatal errors (print message and exit) */
118 static inline void
JPEG_EXIT(j_common_ptr cinfo,int code)119 JPEG_EXIT(j_common_ptr cinfo, int code) {
120 freeimage_error_ptr error_ptr = (freeimage_error_ptr)cinfo->err;
121 error_ptr->pub.msg_code = code;
122 error_ptr->pub.error_exit(cinfo);
123 }
124
125 /** Nonfatal errors (we can keep going, but the data is probably corrupt) */
126 static inline void
JPEG_WARNING(j_common_ptr cinfo,int code)127 JPEG_WARNING(j_common_ptr cinfo, int code) {
128 freeimage_error_ptr error_ptr = (freeimage_error_ptr)cinfo->err;
129 error_ptr->pub.msg_code = code;
130 error_ptr->pub.emit_message(cinfo, -1);
131 }
132
133 /**
134 Receives control for a fatal error. Information sufficient to
135 generate the error message has been stored in cinfo->err; call
136 output_message to display it. Control must NOT return to the caller;
137 generally this routine will exit() or longjmp() somewhere.
138 */
139 METHODDEF(void)
jpeg_error_exit(j_common_ptr cinfo)140 jpeg_error_exit (j_common_ptr cinfo) {
141 freeimage_error_ptr error_ptr = (freeimage_error_ptr)cinfo->err;
142
143 // always display the message
144 error_ptr->pub.output_message(cinfo);
145
146 // allow JPEG with unknown markers
147 if(error_ptr->pub.msg_code != JERR_UNKNOWN_MARKER) {
148
149 // let the memory manager delete any temp files before we die
150 jpeg_destroy(cinfo);
151
152 // return control to the setjmp point
153 longjmp(error_ptr->setjmp_buffer, 1);
154 }
155 }
156
157 /**
158 Actual output of any JPEG message. Note that this method does not know
159 how to generate a message, only where to send it.
160 */
161 METHODDEF(void)
jpeg_output_message(j_common_ptr cinfo)162 jpeg_output_message (j_common_ptr cinfo) {
163 char buffer[JMSG_LENGTH_MAX];
164 freeimage_error_ptr error_ptr = (freeimage_error_ptr)cinfo->err;
165
166 // create the message
167 error_ptr->pub.format_message(cinfo, buffer);
168 // send it to user's message proc
169 FreeImage_OutputMessageProc(s_format_id, buffer);
170 }
171
172 // ----------------------------------------------------------
173 // Destination manager
174 // ----------------------------------------------------------
175
176 /**
177 Initialize destination. This is called by jpeg_start_compress()
178 before any data is actually written. It must initialize
179 next_output_byte and free_in_buffer. free_in_buffer must be
180 initialized to a positive value.
181 */
182 METHODDEF(void)
init_destination(j_compress_ptr cinfo)183 init_destination (j_compress_ptr cinfo) {
184 freeimage_dst_ptr dest = (freeimage_dst_ptr) cinfo->dest;
185
186 dest->buffer = (JOCTET *)
187 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
188 OUTPUT_BUF_SIZE * sizeof(JOCTET));
189
190 dest->pub.next_output_byte = dest->buffer;
191 dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
192 }
193
194 /**
195 This is called whenever the buffer has filled (free_in_buffer
196 reaches zero). In typical applications, it should write out the
197 *entire* buffer (use the saved start address and buffer length;
198 ignore the current state of next_output_byte and free_in_buffer).
199 Then reset the pointer & count to the start of the buffer, and
200 return TRUE indicating that the buffer has been dumped.
201 free_in_buffer must be set to a positive value when TRUE is
202 returned. A FALSE return should only be used when I/O suspension is
203 desired.
204 */
205 METHODDEF(boolean)
empty_output_buffer(j_compress_ptr cinfo)206 empty_output_buffer (j_compress_ptr cinfo) {
207 freeimage_dst_ptr dest = (freeimage_dst_ptr) cinfo->dest;
208
209 if (dest->m_io->write_proc(dest->buffer, 1, OUTPUT_BUF_SIZE, dest->outfile) != OUTPUT_BUF_SIZE) {
210 // let the memory manager delete any temp files before we die
211 jpeg_destroy((j_common_ptr)cinfo);
212
213 JPEG_EXIT((j_common_ptr)cinfo, JERR_FILE_WRITE);
214 }
215
216 dest->pub.next_output_byte = dest->buffer;
217 dest->pub.free_in_buffer = OUTPUT_BUF_SIZE;
218
219 return TRUE;
220 }
221
222 /**
223 Terminate destination --- called by jpeg_finish_compress() after all
224 data has been written. In most applications, this must flush any
225 data remaining in the buffer. Use either next_output_byte or
226 free_in_buffer to determine how much data is in the buffer.
227 */
228 METHODDEF(void)
term_destination(j_compress_ptr cinfo)229 term_destination (j_compress_ptr cinfo) {
230 freeimage_dst_ptr dest = (freeimage_dst_ptr) cinfo->dest;
231
232 size_t datacount = OUTPUT_BUF_SIZE - dest->pub.free_in_buffer;
233
234 // write any data remaining in the buffer
235
236 if (datacount > 0) {
237 if (dest->m_io->write_proc(dest->buffer, 1, (unsigned int)datacount, dest->outfile) != datacount) {
238 // let the memory manager delete any temp files before we die
239 jpeg_destroy((j_common_ptr)cinfo);
240
241 JPEG_EXIT((j_common_ptr)cinfo, JERR_FILE_WRITE);
242 }
243 }
244 }
245
246 // ----------------------------------------------------------
247 // Source manager
248 // ----------------------------------------------------------
249
250 /**
251 Initialize source. This is called by jpeg_read_header() before any
252 data is actually read. Unlike init_destination(), it may leave
253 bytes_in_buffer set to 0 (in which case a fill_input_buffer() call
254 will occur immediately).
255 */
256 METHODDEF(void)
init_source(j_decompress_ptr cinfo)257 init_source (j_decompress_ptr cinfo) {
258 freeimage_src_ptr src = (freeimage_src_ptr) cinfo->src;
259
260 /* We reset the empty-input-file flag for each image,
261 * but we don't clear the input buffer.
262 * This is correct behavior for reading a series of images from one source.
263 */
264
265 src->start_of_file = TRUE;
266 }
267
268 /**
269 This is called whenever bytes_in_buffer has reached zero and more
270 data is wanted. In typical applications, it should read fresh data
271 into the buffer (ignoring the current state of next_input_byte and
272 bytes_in_buffer), reset the pointer & count to the start of the
273 buffer, and return TRUE indicating that the buffer has been reloaded.
274 It is not necessary to fill the buffer entirely, only to obtain at
275 least one more byte. bytes_in_buffer MUST be set to a positive value
276 if TRUE is returned. A FALSE return should only be used when I/O
277 suspension is desired.
278 */
279 METHODDEF(boolean)
fill_input_buffer(j_decompress_ptr cinfo)280 fill_input_buffer (j_decompress_ptr cinfo) {
281 freeimage_src_ptr src = (freeimage_src_ptr) cinfo->src;
282
283 size_t nbytes = src->m_io->read_proc(src->buffer, 1, INPUT_BUF_SIZE, src->infile);
284
285 if (nbytes <= 0) {
286 if (src->start_of_file) {
287 // treat empty input file as fatal error
288
289 // let the memory manager delete any temp files before we die
290 jpeg_destroy((j_common_ptr)cinfo);
291
292 JPEG_EXIT((j_common_ptr)cinfo, JERR_INPUT_EMPTY);
293 }
294
295 JPEG_WARNING((j_common_ptr)cinfo, JWRN_JPEG_EOF);
296
297 /* Insert a fake EOI marker */
298
299 src->buffer[0] = (JOCTET) 0xFF;
300 src->buffer[1] = (JOCTET) JPEG_EOI;
301
302 nbytes = 2;
303 }
304
305 src->pub.next_input_byte = src->buffer;
306 src->pub.bytes_in_buffer = nbytes;
307 src->start_of_file = FALSE;
308
309 return TRUE;
310 }
311
312 /**
313 Skip num_bytes worth of data. The buffer pointer and count should
314 be advanced over num_bytes input bytes, refilling the buffer as
315 needed. This is used to skip over a potentially large amount of
316 uninteresting data (such as an APPn marker). In some applications
317 it may be possible to optimize away the reading of the skipped data,
318 but it's not clear that being smart is worth much trouble; large
319 skips are uncommon. bytes_in_buffer may be zero on return.
320 A zero or negative skip count should be treated as a no-op.
321 */
322 METHODDEF(void)
skip_input_data(j_decompress_ptr cinfo,long num_bytes)323 skip_input_data (j_decompress_ptr cinfo, long num_bytes) {
324 freeimage_src_ptr src = (freeimage_src_ptr) cinfo->src;
325
326 /* Just a dumb implementation for now. Could use fseek() except
327 * it doesn't work on pipes. Not clear that being smart is worth
328 * any trouble anyway --- large skips are infrequent.
329 */
330
331 if (num_bytes > 0) {
332 while (num_bytes > (long) src->pub.bytes_in_buffer) {
333 num_bytes -= (long) src->pub.bytes_in_buffer;
334
335 (void) fill_input_buffer(cinfo);
336
337 /* note we assume that fill_input_buffer will never return FALSE,
338 * so suspension need not be handled.
339 */
340 }
341
342 src->pub.next_input_byte += (size_t) num_bytes;
343 src->pub.bytes_in_buffer -= (size_t) num_bytes;
344 }
345 }
346
347 /**
348 Terminate source --- called by jpeg_finish_decompress
349 after all data has been read. Often a no-op.
350
351 NB: *not* called by jpeg_abort or jpeg_destroy; surrounding
352 application must deal with any cleanup that should happen even
353 for error exit.
354 */
355 METHODDEF(void)
term_source(j_decompress_ptr cinfo)356 term_source (j_decompress_ptr cinfo) {
357 // no work necessary here
358 }
359
360 // ----------------------------------------------------------
361 // Source manager & Destination manager setup
362 // ----------------------------------------------------------
363
364 /**
365 Prepare for input from a stdio stream.
366 The caller must have already opened the stream, and is responsible
367 for closing it after finishing decompression.
368 */
369 GLOBAL(void)
jpeg_freeimage_src(j_decompress_ptr cinfo,fi_handle infile,FreeImageIO * io)370 jpeg_freeimage_src (j_decompress_ptr cinfo, fi_handle infile, FreeImageIO *io) {
371 freeimage_src_ptr src;
372
373 // allocate memory for the buffer. is released automatically in the end
374
375 if (cinfo->src == NULL) {
376 cinfo->src = (struct jpeg_source_mgr *) (*cinfo->mem->alloc_small)
377 ((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof(SourceManager));
378
379 src = (freeimage_src_ptr) cinfo->src;
380
381 src->buffer = (JOCTET *) (*cinfo->mem->alloc_small)
382 ((j_common_ptr) cinfo, JPOOL_PERMANENT, INPUT_BUF_SIZE * sizeof(JOCTET));
383 }
384
385 // initialize the jpeg pointer struct with pointers to functions
386
387 src = (freeimage_src_ptr) cinfo->src;
388 src->pub.init_source = init_source;
389 src->pub.fill_input_buffer = fill_input_buffer;
390 src->pub.skip_input_data = skip_input_data;
391 src->pub.resync_to_restart = jpeg_resync_to_restart; // use default method
392 src->pub.term_source = term_source;
393 src->infile = infile;
394 src->m_io = io;
395 src->pub.bytes_in_buffer = 0; // forces fill_input_buffer on first read
396 src->pub.next_input_byte = NULL; // until buffer loaded
397 }
398
399 /**
400 Prepare for output to a stdio stream.
401 The caller must have already opened the stream, and is responsible
402 for closing it after finishing compression.
403 */
404 GLOBAL(void)
jpeg_freeimage_dst(j_compress_ptr cinfo,fi_handle outfile,FreeImageIO * io)405 jpeg_freeimage_dst (j_compress_ptr cinfo, fi_handle outfile, FreeImageIO *io) {
406 freeimage_dst_ptr dest;
407
408 if (cinfo->dest == NULL) {
409 cinfo->dest = (struct jpeg_destination_mgr *)(*cinfo->mem->alloc_small)
410 ((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof(DestinationManager));
411 }
412
413 dest = (freeimage_dst_ptr) cinfo->dest;
414 dest->pub.init_destination = init_destination;
415 dest->pub.empty_output_buffer = empty_output_buffer;
416 dest->pub.term_destination = term_destination;
417 dest->outfile = outfile;
418 dest->m_io = io;
419 }
420
421 // ----------------------------------------------------------
422 // Special markers read functions
423 // ----------------------------------------------------------
424
425 /**
426 Read JPEG_COM marker (comment)
427 */
428 static BOOL
jpeg_read_comment(FIBITMAP * dib,const BYTE * dataptr,unsigned int datalen)429 jpeg_read_comment(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen) {
430 size_t length = datalen;
431 BYTE *profile = (BYTE*)dataptr;
432
433 // read the comment
434 char *value = (char*)malloc((length + 1) * sizeof(char));
435 if(value == NULL) return FALSE;
436 memcpy(value, profile, length);
437 value[length] = '\0';
438
439 // create a tag
440 FITAG *tag = FreeImage_CreateTag();
441 if(tag) {
442 unsigned int count = (unsigned int)length + 1; // includes the null value
443
444 FreeImage_SetTagID(tag, JPEG_COM);
445 FreeImage_SetTagKey(tag, "Comment");
446 FreeImage_SetTagLength(tag, count);
447 FreeImage_SetTagCount(tag, count);
448 FreeImage_SetTagType(tag, FIDT_ASCII);
449 FreeImage_SetTagValue(tag, value);
450
451 // store the tag
452 FreeImage_SetMetadata(FIMD_COMMENTS, dib, FreeImage_GetTagKey(tag), tag);
453
454 // destroy the tag
455 FreeImage_DeleteTag(tag);
456 }
457
458 free(value);
459
460 return TRUE;
461 }
462
463 /**
464 Read JPEG_APP2 marker (ICC profile)
465 */
466
467 /**
468 Handy subroutine to test whether a saved marker is an ICC profile marker.
469 */
470 static BOOL
marker_is_icc(jpeg_saved_marker_ptr marker)471 marker_is_icc(jpeg_saved_marker_ptr marker) {
472 // marker identifying string "ICC_PROFILE" (null-terminated)
473 const BYTE icc_signature[12] = { 0x49, 0x43, 0x43, 0x5F, 0x50, 0x52, 0x4F, 0x46, 0x49, 0x4C, 0x45, 0x00 };
474
475 if(marker->marker == ICC_MARKER) {
476 // verify the identifying string
477 if(marker->data_length >= ICC_HEADER_SIZE) {
478 if(memcmp(icc_signature, marker->data, sizeof(icc_signature)) == 0) {
479 return TRUE;
480 }
481 }
482 }
483
484 return FALSE;
485 }
486
487 /**
488 See if there was an ICC profile in the JPEG file being read;
489 if so, reassemble and return the profile data.
490
491 TRUE is returned if an ICC profile was found, FALSE if not.
492 If TRUE is returned, *icc_data_ptr is set to point to the
493 returned data, and *icc_data_len is set to its length.
494
495 IMPORTANT: the data at **icc_data_ptr has been allocated with malloc()
496 and must be freed by the caller with free() when the caller no longer
497 needs it. (Alternatively, we could write this routine to use the
498 IJG library's memory allocator, so that the data would be freed implicitly
499 at jpeg_finish_decompress() time. But it seems likely that many apps
500 will prefer to have the data stick around after decompression finishes.)
501
502 NOTE: if the file contains invalid ICC APP2 markers, we just silently
503 return FALSE. You might want to issue an error message instead.
504 */
505 static BOOL
jpeg_read_icc_profile(j_decompress_ptr cinfo,JOCTET ** icc_data_ptr,unsigned * icc_data_len)506 jpeg_read_icc_profile(j_decompress_ptr cinfo, JOCTET **icc_data_ptr, unsigned *icc_data_len) {
507 jpeg_saved_marker_ptr marker;
508 int num_markers = 0;
509 int seq_no;
510 JOCTET *icc_data;
511 unsigned total_length;
512
513 const int MAX_SEQ_NO = 255; // sufficient since marker numbers are bytes
514 BYTE marker_present[MAX_SEQ_NO+1]; // 1 if marker found
515 unsigned data_length[MAX_SEQ_NO+1]; // size of profile data in marker
516 unsigned data_offset[MAX_SEQ_NO+1]; // offset for data in marker
517
518 *icc_data_ptr = NULL; // avoid confusion if FALSE return
519 *icc_data_len = 0;
520
521 /**
522 this first pass over the saved markers discovers whether there are
523 any ICC markers and verifies the consistency of the marker numbering.
524 */
525
526 memset(marker_present, 0, (MAX_SEQ_NO + 1));
527
528 for(marker = cinfo->marker_list; marker != NULL; marker = marker->next) {
529 if (marker_is_icc(marker)) {
530 if (num_markers == 0) {
531 // number of markers
532 num_markers = GETJOCTET(marker->data[13]);
533 }
534 else if (num_markers != GETJOCTET(marker->data[13])) {
535 return FALSE; // inconsistent num_markers fields
536 }
537 // sequence number
538 seq_no = GETJOCTET(marker->data[12]);
539 if (seq_no <= 0 || seq_no > num_markers) {
540 return FALSE; // bogus sequence number
541 }
542 if (marker_present[seq_no]) {
543 return FALSE; // duplicate sequence numbers
544 }
545 marker_present[seq_no] = 1;
546 data_length[seq_no] = marker->data_length - ICC_HEADER_SIZE;
547 }
548 }
549
550 if (num_markers == 0)
551 return FALSE;
552
553 /**
554 check for missing markers, count total space needed,
555 compute offset of each marker's part of the data.
556 */
557
558 total_length = 0;
559 for(seq_no = 1; seq_no <= num_markers; seq_no++) {
560 if (marker_present[seq_no] == 0) {
561 return FALSE; // missing sequence number
562 }
563 data_offset[seq_no] = total_length;
564 total_length += data_length[seq_no];
565 }
566
567 if (total_length <= 0)
568 return FALSE; // found only empty markers ?
569
570 // allocate space for assembled data
571 icc_data = (JOCTET *) malloc(total_length * sizeof(JOCTET));
572 if (icc_data == NULL)
573 return FALSE; // out of memory
574
575 // and fill it in
576 for (marker = cinfo->marker_list; marker != NULL; marker = marker->next) {
577 if (marker_is_icc(marker)) {
578 JOCTET FAR *src_ptr;
579 JOCTET *dst_ptr;
580 unsigned length;
581 seq_no = GETJOCTET(marker->data[12]);
582 dst_ptr = icc_data + data_offset[seq_no];
583 src_ptr = marker->data + ICC_HEADER_SIZE;
584 length = data_length[seq_no];
585 while (length--) {
586 *dst_ptr++ = *src_ptr++;
587 }
588 }
589 }
590
591 *icc_data_ptr = icc_data;
592 *icc_data_len = total_length;
593
594 return TRUE;
595 }
596
597 /**
598 Read JPEG_APPD marker (IPTC or Adobe Photoshop profile)
599 */
600 static BOOL
jpeg_read_iptc_profile(FIBITMAP * dib,const BYTE * dataptr,unsigned int datalen)601 jpeg_read_iptc_profile(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen) {
602 return read_iptc_profile(dib, dataptr, datalen);
603 }
604
605 /**
606 Read JPEG_APP1 marker (XMP profile)
607 @param dib Input FIBITMAP
608 @param dataptr Pointer to the APP1 marker
609 @param datalen APP1 marker length
610 @return Returns TRUE if successful, FALSE otherwise
611 */
612 static BOOL
jpeg_read_xmp_profile(FIBITMAP * dib,const BYTE * dataptr,unsigned int datalen)613 jpeg_read_xmp_profile(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen) {
614 // marker identifying string for XMP (null terminated)
615 const char *xmp_signature = "http://ns.adobe.com/xap/1.0/";
616 // XMP signature is 29 bytes long
617 const size_t xmp_signature_size = strlen(xmp_signature) + 1;
618
619 size_t length = datalen;
620 BYTE *profile = (BYTE*)dataptr;
621
622 if(length <= xmp_signature_size) {
623 // avoid reading corrupted or empty data
624 return FALSE;
625 }
626
627 // verify the identifying string
628
629 if(memcmp(xmp_signature, profile, strlen(xmp_signature)) == 0) {
630 // XMP profile
631
632 profile += xmp_signature_size;
633 length -= xmp_signature_size;
634
635 // create a tag
636 FITAG *tag = FreeImage_CreateTag();
637 if(tag) {
638 FreeImage_SetTagID(tag, JPEG_APP0+1); // 0xFFE1
639 FreeImage_SetTagKey(tag, g_TagLib_XMPFieldName);
640 FreeImage_SetTagLength(tag, (DWORD)length);
641 FreeImage_SetTagCount(tag, (DWORD)length);
642 FreeImage_SetTagType(tag, FIDT_ASCII);
643 FreeImage_SetTagValue(tag, profile);
644
645 // store the tag
646 FreeImage_SetMetadata(FIMD_XMP, dib, FreeImage_GetTagKey(tag), tag);
647
648 // destroy the tag
649 FreeImage_DeleteTag(tag);
650 }
651
652 return TRUE;
653 }
654
655 return FALSE;
656 }
657
658 /**
659 Read JFIF "JFXX" extension APP0 marker
660 @param dib Input FIBITMAP
661 @param dataptr Pointer to the APP0 marker
662 @param datalen APP0 marker length
663 @return Returns TRUE if successful, FALSE otherwise
664 */
665 static BOOL
jpeg_read_jfxx(FIBITMAP * dib,const BYTE * dataptr,unsigned int datalen)666 jpeg_read_jfxx(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen) {
667 if(datalen < 6) {
668 return FALSE;
669 }
670
671 const int id_length = 5;
672 const BYTE *data = dataptr + id_length;
673 unsigned remaining = datalen - id_length;
674
675 const BYTE type = *data;
676 ++data, --remaining;
677
678 switch(type) {
679 case JFXX_TYPE_JPEG:
680 {
681 // load the thumbnail
682 FIMEMORY* hmem = FreeImage_OpenMemory(const_cast<BYTE*>(data), remaining);
683 FIBITMAP* thumbnail = FreeImage_LoadFromMemory(FIF_JPEG, hmem);
684 FreeImage_CloseMemory(hmem);
685 // store the thumbnail
686 FreeImage_SetThumbnail(dib, thumbnail);
687 // then delete it
688 FreeImage_Unload(thumbnail);
689 break;
690 }
691 case JFXX_TYPE_8bit:
692 // colormapped uncompressed thumbnail (no supported)
693 break;
694 case JFXX_TYPE_24bit:
695 // truecolor uncompressed thumbnail (no supported)
696 break;
697 default:
698 break;
699 }
700
701 return TRUE;
702 }
703
704
705 /**
706 Read JPEG special markers
707 */
708 static BOOL
read_markers(j_decompress_ptr cinfo,FIBITMAP * dib)709 read_markers(j_decompress_ptr cinfo, FIBITMAP *dib) {
710 jpeg_saved_marker_ptr marker;
711
712 for(marker = cinfo->marker_list; marker != NULL; marker = marker->next) {
713 switch(marker->marker) {
714 case JPEG_APP0:
715 // JFIF is handled by libjpeg already, handle JFXX
716 if(memcmp(marker->data, "JFIF" , 5) == 0) {
717 continue;
718 }
719 if(memcmp(marker->data, "JFXX" , 5) == 0) {
720 if(!cinfo->saw_JFIF_marker || cinfo->JFIF_minor_version < 2) {
721 FreeImage_OutputMessageProc(s_format_id, "Warning: non-standard JFXX segment");
722 }
723 jpeg_read_jfxx(dib, marker->data, marker->data_length);
724 }
725 // other values such as 'Picasa' : ignore safely unknown APP0 marker
726 break;
727 case JPEG_COM:
728 // JPEG comment
729 jpeg_read_comment(dib, marker->data, marker->data_length);
730 break;
731 case EXIF_MARKER:
732 // Exif or Adobe XMP profile
733 jpeg_read_exif_profile(dib, marker->data, marker->data_length);
734 jpeg_read_xmp_profile(dib, marker->data, marker->data_length);
735 jpeg_read_exif_profile_raw(dib, marker->data, marker->data_length);
736 break;
737 case IPTC_MARKER:
738 // IPTC/NAA or Adobe Photoshop profile
739 jpeg_read_iptc_profile(dib, marker->data, marker->data_length);
740 break;
741 }
742 }
743
744 // ICC profile
745 BYTE *icc_profile = NULL;
746 unsigned icc_length = 0;
747
748 if( jpeg_read_icc_profile(cinfo, &icc_profile, &icc_length) ) {
749 // copy ICC profile data
750 FreeImage_CreateICCProfile(dib, icc_profile, icc_length);
751 // clean up
752 free(icc_profile);
753 }
754
755 return TRUE;
756 }
757
758 // ----------------------------------------------------------
759 // Special markers write functions
760 // ----------------------------------------------------------
761
762 /**
763 Write JPEG_COM marker (comment)
764 */
765 static BOOL
jpeg_write_comment(j_compress_ptr cinfo,FIBITMAP * dib)766 jpeg_write_comment(j_compress_ptr cinfo, FIBITMAP *dib) {
767 FITAG *tag = NULL;
768
769 // write user comment as a JPEG_COM marker
770 FreeImage_GetMetadata(FIMD_COMMENTS, dib, "Comment", &tag);
771 if(tag) {
772 const char *tag_value = (char*)FreeImage_GetTagValue(tag);
773
774 if(NULL != tag_value) {
775 for(long i = 0; i < (long)strlen(tag_value); i+= MAX_BYTES_IN_MARKER) {
776 jpeg_write_marker(cinfo, JPEG_COM, (BYTE*)tag_value + i, MIN((long)strlen(tag_value + i), MAX_BYTES_IN_MARKER));
777 }
778 return TRUE;
779 }
780 }
781 return FALSE;
782 }
783
784 /**
785 Write JPEG_APP2 marker (ICC profile)
786 */
787 static BOOL
jpeg_write_icc_profile(j_compress_ptr cinfo,FIBITMAP * dib)788 jpeg_write_icc_profile(j_compress_ptr cinfo, FIBITMAP *dib) {
789 // marker identifying string "ICC_PROFILE" (null-terminated)
790 BYTE icc_signature[12] = { 0x49, 0x43, 0x43, 0x5F, 0x50, 0x52, 0x4F, 0x46, 0x49, 0x4C, 0x45, 0x00 };
791
792 FIICCPROFILE *iccProfile = FreeImage_GetICCProfile(dib);
793
794 if (iccProfile->size && iccProfile->data) {
795 // ICC_HEADER_SIZE: ICC signature is 'ICC_PROFILE' + 2 bytes
796
797 BYTE *profile = (BYTE*)malloc((iccProfile->size + ICC_HEADER_SIZE) * sizeof(BYTE));
798 if(profile == NULL) return FALSE;
799 memcpy(profile, icc_signature, 12);
800
801 for(long i = 0; i < (long)iccProfile->size; i += MAX_DATA_BYTES_IN_MARKER) {
802 unsigned length = MIN((long)(iccProfile->size - i), MAX_DATA_BYTES_IN_MARKER);
803 // sequence number
804 profile[12] = (BYTE) ((i / MAX_DATA_BYTES_IN_MARKER) + 1);
805 // number of markers
806 profile[13] = (BYTE) (iccProfile->size / MAX_DATA_BYTES_IN_MARKER + 1);
807
808 memcpy(profile + ICC_HEADER_SIZE, (BYTE*)iccProfile->data + i, length);
809 jpeg_write_marker(cinfo, ICC_MARKER, profile, (length + ICC_HEADER_SIZE));
810 }
811
812 free(profile);
813
814 return TRUE;
815 }
816
817 return FALSE;
818 }
819
820 /**
821 Write JPEG_APPD marker (IPTC or Adobe Photoshop profile)
822 @return Returns TRUE if successful, FALSE otherwise
823 */
824 static BOOL
jpeg_write_iptc_profile(j_compress_ptr cinfo,FIBITMAP * dib)825 jpeg_write_iptc_profile(j_compress_ptr cinfo, FIBITMAP *dib) {
826 //const char *ps_header = "Photoshop 3.0\x08BIM\x04\x04\x0\x0\x0\x0";
827 const unsigned tag_length = 26;
828
829 if(FreeImage_GetMetadataCount(FIMD_IPTC, dib)) {
830 BYTE *profile = NULL;
831 unsigned profile_size = 0;
832
833 // create a binary profile
834 if(write_iptc_profile(dib, &profile, &profile_size)) {
835
836 // write the profile
837 for(long i = 0; i < (long)profile_size; i += 65517L) {
838 unsigned length = MIN((long)profile_size - i, 65517L);
839 unsigned roundup = length & 0x01; // needed for Photoshop
840 BYTE *iptc_profile = (BYTE*)malloc(length + roundup + tag_length);
841 if(iptc_profile == NULL) break;
842 // Photoshop identification string
843 memcpy(&iptc_profile[0], "Photoshop 3.0\x0", 14);
844 // 8BIM segment type
845 memcpy(&iptc_profile[14], "8BIM\x04\x04\x0\x0\x0\x0", 10);
846 // segment size
847 iptc_profile[24] = (BYTE)(length >> 8);
848 iptc_profile[25] = (BYTE)(length & 0xFF);
849 // segment data
850 memcpy(&iptc_profile[tag_length], &profile[i], length);
851 if(roundup)
852 iptc_profile[length + tag_length] = 0;
853 jpeg_write_marker(cinfo, IPTC_MARKER, iptc_profile, length + roundup + tag_length);
854 free(iptc_profile);
855 }
856
857 // release profile
858 free(profile);
859
860 return TRUE;
861 }
862 }
863
864 return FALSE;
865 }
866
867 /**
868 Write JPEG_APP1 marker (XMP profile)
869 @return Returns TRUE if successful, FALSE otherwise
870 */
871 static BOOL
jpeg_write_xmp_profile(j_compress_ptr cinfo,FIBITMAP * dib)872 jpeg_write_xmp_profile(j_compress_ptr cinfo, FIBITMAP *dib) {
873 // marker identifying string for XMP (null terminated)
874 const char *xmp_signature = "http://ns.adobe.com/xap/1.0/";
875
876 FITAG *tag_xmp = NULL;
877 FreeImage_GetMetadata(FIMD_XMP, dib, g_TagLib_XMPFieldName, &tag_xmp);
878
879 if(tag_xmp) {
880 const BYTE *tag_value = (BYTE*)FreeImage_GetTagValue(tag_xmp);
881
882 if(NULL != tag_value) {
883 // XMP signature is 29 bytes long
884 unsigned int xmp_header_size = (unsigned int)strlen(xmp_signature) + 1;
885
886 DWORD tag_length = FreeImage_GetTagLength(tag_xmp);
887
888 BYTE *profile = (BYTE*)malloc((tag_length + xmp_header_size) * sizeof(BYTE));
889 if(profile == NULL) return FALSE;
890 memcpy(profile, xmp_signature, xmp_header_size);
891
892 for(DWORD i = 0; i < tag_length; i += 65504L) {
893 unsigned length = MIN((long)(tag_length - i), 65504L);
894
895 memcpy(profile + xmp_header_size, tag_value + i, length);
896 jpeg_write_marker(cinfo, EXIF_MARKER, profile, (length + xmp_header_size));
897 }
898
899 free(profile);
900
901 return TRUE;
902 }
903 }
904
905 return FALSE;
906 }
907
908 /**
909 Write JPEG_APP1 marker (Exif profile)
910 @return Returns TRUE if successful, FALSE otherwise
911 */
912 static BOOL
jpeg_write_exif_profile_raw(j_compress_ptr cinfo,FIBITMAP * dib)913 jpeg_write_exif_profile_raw(j_compress_ptr cinfo, FIBITMAP *dib) {
914 // marker identifying string for Exif = "Exif\0\0"
915 BYTE exif_signature[6] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 };
916
917 FITAG *tag_exif = NULL;
918 FreeImage_GetMetadata(FIMD_EXIF_RAW, dib, g_TagLib_ExifRawFieldName, &tag_exif);
919
920 if(tag_exif) {
921 const BYTE *tag_value = (BYTE*)FreeImage_GetTagValue(tag_exif);
922
923 // verify the identifying string
924 if(memcmp(exif_signature, tag_value, sizeof(exif_signature)) != 0) {
925 // not an Exif profile
926 return FALSE;
927 }
928
929 if(NULL != tag_value) {
930 DWORD tag_length = FreeImage_GetTagLength(tag_exif);
931
932 BYTE *profile = (BYTE*)malloc(tag_length * sizeof(BYTE));
933 if(profile == NULL) return FALSE;
934
935 for(DWORD i = 0; i < tag_length; i += 65504L) {
936 unsigned length = MIN((long)(tag_length - i), 65504L);
937
938 memcpy(profile, tag_value + i, length);
939 jpeg_write_marker(cinfo, EXIF_MARKER, profile, length);
940 }
941
942 free(profile);
943
944 return TRUE;
945 }
946 }
947
948 return FALSE;
949 }
950
951 /**
952 Write thumbnail (JFXX segment, JPEG compressed)
953 */
954 static BOOL
jpeg_write_jfxx(j_compress_ptr cinfo,FIBITMAP * dib)955 jpeg_write_jfxx(j_compress_ptr cinfo, FIBITMAP *dib) {
956 // get the thumbnail to be stored
957 FIBITMAP* thumbnail = FreeImage_GetThumbnail(dib);
958 if(!thumbnail) {
959 return TRUE;
960 }
961 // check for a compatible output format
962 if((FreeImage_GetImageType(thumbnail) != FIT_BITMAP) || (FreeImage_GetBPP(thumbnail) != 8) && (FreeImage_GetBPP(thumbnail) != 24)) {
963 FreeImage_OutputMessageProc(s_format_id, FI_MSG_WARNING_INVALID_THUMBNAIL);
964 return FALSE;
965 }
966
967 // stores the thumbnail as a baseline JPEG into a memory block
968 // return the memory block only if its size is within JFXX marker size limit!
969 FIMEMORY *stream = FreeImage_OpenMemory();
970
971 if(FreeImage_SaveToMemory(FIF_JPEG, thumbnail, stream, JPEG_BASELINE)) {
972 // check that the memory block size is within JFXX marker size limit
973 FreeImage_SeekMemory(stream, 0, SEEK_END);
974 const long eof = FreeImage_TellMemory(stream);
975 if(eof > MAX_JFXX_THUMB_SIZE) {
976 FreeImage_OutputMessageProc(s_format_id, "Warning: attached thumbnail is %d bytes larger than maximum supported size - Thumbnail saving aborted", eof - MAX_JFXX_THUMB_SIZE);
977 FreeImage_CloseMemory(stream);
978 return FALSE;
979 }
980 } else {
981 FreeImage_CloseMemory(stream);
982 return FALSE;
983 }
984
985 BYTE* thData = NULL;
986 DWORD thSize = 0;
987
988 FreeImage_AcquireMemory(stream, &thData, &thSize);
989
990 BYTE id_length = 5; //< "JFXX"
991 BYTE type = JFXX_TYPE_JPEG;
992
993 DWORD totalsize = id_length + sizeof(type) + thSize;
994 jpeg_write_m_header(cinfo, JPEG_APP0, totalsize);
995
996 jpeg_write_m_byte(cinfo, 'J');
997 jpeg_write_m_byte(cinfo, 'F');
998 jpeg_write_m_byte(cinfo, 'X');
999 jpeg_write_m_byte(cinfo, 'X');
1000 jpeg_write_m_byte(cinfo, '\0');
1001
1002 jpeg_write_m_byte(cinfo, type);
1003
1004 // write thumbnail to destination.
1005 // We "cram it straight into the data destination module", because write_m_byte is slow
1006
1007 freeimage_dst_ptr dest = (freeimage_dst_ptr) cinfo->dest;
1008
1009 BYTE* & out = dest->pub.next_output_byte;
1010 size_t & bufRemain = dest->pub.free_in_buffer;
1011
1012 const BYTE *thData_end = thData + thSize;
1013
1014 while(thData < thData_end) {
1015 *(out)++ = *(thData)++;
1016 if (--bufRemain == 0) {
1017 // buffer full - flush
1018 if (!dest->pub.empty_output_buffer(cinfo)) {
1019 break;
1020 }
1021 }
1022 }
1023
1024 FreeImage_CloseMemory(stream);
1025
1026 return TRUE;
1027 }
1028
1029 /**
1030 Write JPEG special markers
1031 */
1032 static BOOL
write_markers(j_compress_ptr cinfo,FIBITMAP * dib)1033 write_markers(j_compress_ptr cinfo, FIBITMAP *dib) {
1034 // write thumbnail as a JFXX marker
1035 jpeg_write_jfxx(cinfo, dib);
1036
1037 // write user comment as a JPEG_COM marker
1038 jpeg_write_comment(cinfo, dib);
1039
1040 // write ICC profile
1041 jpeg_write_icc_profile(cinfo, dib);
1042
1043 // write IPTC profile
1044 jpeg_write_iptc_profile(cinfo, dib);
1045
1046 // write Adobe XMP profile
1047 jpeg_write_xmp_profile(cinfo, dib);
1048
1049 // write Exif raw data
1050 jpeg_write_exif_profile_raw(cinfo, dib);
1051
1052 return TRUE;
1053 }
1054
1055 // ------------------------------------------------------------
1056 // Keep original size info when using scale option on loading
1057 // ------------------------------------------------------------
1058 static void
store_size_info(FIBITMAP * dib,JDIMENSION width,JDIMENSION height)1059 store_size_info(FIBITMAP *dib, JDIMENSION width, JDIMENSION height) {
1060 char buffer[256];
1061 // create a tag
1062 FITAG *tag = FreeImage_CreateTag();
1063 if(tag) {
1064 size_t length = 0;
1065 // set the original width
1066 sprintf(buffer, "%d", (int)width);
1067 length = strlen(buffer) + 1; // include the NULL/0 value
1068 FreeImage_SetTagKey(tag, "OriginalJPEGWidth");
1069 FreeImage_SetTagLength(tag, (DWORD)length);
1070 FreeImage_SetTagCount(tag, (DWORD)length);
1071 FreeImage_SetTagType(tag, FIDT_ASCII);
1072 FreeImage_SetTagValue(tag, buffer);
1073 FreeImage_SetMetadata(FIMD_COMMENTS, dib, FreeImage_GetTagKey(tag), tag);
1074 // set the original height
1075 sprintf(buffer, "%d", (int)height);
1076 length = strlen(buffer) + 1; // include the NULL/0 value
1077 FreeImage_SetTagKey(tag, "OriginalJPEGHeight");
1078 FreeImage_SetTagLength(tag, (DWORD)length);
1079 FreeImage_SetTagCount(tag, (DWORD)length);
1080 FreeImage_SetTagType(tag, FIDT_ASCII);
1081 FreeImage_SetTagValue(tag, buffer);
1082 FreeImage_SetMetadata(FIMD_COMMENTS, dib, FreeImage_GetTagKey(tag), tag);
1083 // destroy the tag
1084 FreeImage_DeleteTag(tag);
1085 }
1086 }
1087
1088 // ==========================================================
1089 // Plugin Implementation
1090 // ==========================================================
1091
1092 static const char * DLL_CALLCONV
Format()1093 Format() {
1094 return "JPEG";
1095 }
1096
1097 static const char * DLL_CALLCONV
Description()1098 Description() {
1099 return "JPEG - JFIF Compliant";
1100 }
1101
1102 static const char * DLL_CALLCONV
Extension()1103 Extension() {
1104 return "jpg,jif,jpeg,jpe";
1105 }
1106
1107 static const char * DLL_CALLCONV
RegExpr()1108 RegExpr() {
1109 return "^\377\330\377";
1110 }
1111
1112 static const char * DLL_CALLCONV
MimeType()1113 MimeType() {
1114 return "image/jpeg";
1115 }
1116
1117 static BOOL DLL_CALLCONV
Validate(FreeImageIO * io,fi_handle handle)1118 Validate(FreeImageIO *io, fi_handle handle) {
1119 BYTE jpeg_signature[] = { 0xFF, 0xD8 };
1120 BYTE signature[2] = { 0, 0 };
1121
1122 io->read_proc(signature, 1, sizeof(jpeg_signature), handle);
1123
1124 return (memcmp(jpeg_signature, signature, sizeof(jpeg_signature)) == 0);
1125 }
1126
1127 static BOOL DLL_CALLCONV
SupportsExportDepth(int depth)1128 SupportsExportDepth(int depth) {
1129 return (
1130 (depth == 8) ||
1131 (depth == 24) ||
1132 (depth == 32) // only if 32-bit CMYK
1133 );
1134 }
1135
1136 static BOOL DLL_CALLCONV
SupportsExportType(FREE_IMAGE_TYPE type)1137 SupportsExportType(FREE_IMAGE_TYPE type) {
1138 return (type == FIT_BITMAP) ? TRUE : FALSE;
1139 }
1140
1141 static BOOL DLL_CALLCONV
SupportsICCProfiles()1142 SupportsICCProfiles() {
1143 return TRUE;
1144 }
1145
1146 static BOOL DLL_CALLCONV
SupportsNoPixels()1147 SupportsNoPixels() {
1148 return TRUE;
1149 }
1150
1151 // ----------------------------------------------------------
1152
1153 static FIBITMAP * DLL_CALLCONV
Load(FreeImageIO * io,fi_handle handle,int page,int flags,void * data)1154 Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
1155 if (handle) {
1156 FIBITMAP *dib = NULL;
1157
1158 BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS;
1159
1160 // set up the jpeglib structures
1161
1162 struct jpeg_decompress_struct cinfo;
1163 ErrorManager fi_error_mgr;
1164
1165 try {
1166
1167 // step 1: allocate and initialize JPEG decompression object
1168
1169 // we set up the normal JPEG error routines, then override error_exit & output_message
1170 cinfo.err = jpeg_std_error(&fi_error_mgr.pub);
1171 fi_error_mgr.pub.error_exit = jpeg_error_exit;
1172 fi_error_mgr.pub.output_message = jpeg_output_message;
1173
1174 // establish the setjmp return context for jpeg_error_exit to use
1175 if (setjmp(fi_error_mgr.setjmp_buffer)) {
1176 // If we get here, the JPEG code has signaled an error.
1177 // We need to clean up the JPEG object, close the input file, and return.
1178 jpeg_destroy_decompress(&cinfo);
1179 throw (const char*)NULL;
1180 }
1181
1182 jpeg_create_decompress(&cinfo);
1183
1184 // step 2a: specify data source (eg, a handle)
1185
1186 jpeg_freeimage_src(&cinfo, handle, io);
1187
1188 // step 2b: save special markers for later reading
1189
1190 jpeg_save_markers(&cinfo, JPEG_COM, 0xFFFF);
1191 for(int m = 0; m < 16; m++) {
1192 jpeg_save_markers(&cinfo, JPEG_APP0 + m, 0xFFFF);
1193 }
1194
1195 // step 3: read handle parameters with jpeg_read_header()
1196
1197 jpeg_read_header(&cinfo, TRUE);
1198
1199 // step 4: set parameters for decompression
1200
1201 unsigned int scale_denom = 1; // fraction by which to scale image
1202 int requested_size = flags >> 16; // requested user size in pixels
1203 if(requested_size > 0) {
1204 // the JPEG codec can perform x2, x4 or x8 scaling on loading
1205 // try to find the more appropriate scaling according to user's need
1206 double scale = MAX((double)cinfo.image_width, (double)cinfo.image_height) / (double)requested_size;
1207 if(scale >= 8) {
1208 scale_denom = 8;
1209 } else if(scale >= 4) {
1210 scale_denom = 4;
1211 } else if(scale >= 2) {
1212 scale_denom = 2;
1213 }
1214 }
1215 cinfo.scale_num = 1;
1216 cinfo.scale_denom = scale_denom;
1217
1218 if ((flags & JPEG_ACCURATE) != JPEG_ACCURATE) {
1219 cinfo.dct_method = JDCT_IFAST;
1220 cinfo.do_fancy_upsampling = FALSE;
1221 }
1222
1223 if ((flags & JPEG_GREYSCALE) == JPEG_GREYSCALE) {
1224 // force loading as a 8-bit greyscale image
1225 cinfo.out_color_space = JCS_GRAYSCALE;
1226 }
1227
1228 // step 5a: start decompressor and calculate output width and height
1229
1230 jpeg_start_decompress(&cinfo);
1231
1232 // step 5b: allocate dib and init header
1233
1234 if((cinfo.output_components == 4) && (cinfo.out_color_space == JCS_CMYK)) {
1235 // CMYK image
1236 if((flags & JPEG_CMYK) == JPEG_CMYK) {
1237 // load as CMYK
1238 dib = FreeImage_AllocateHeader(header_only, cinfo.output_width, cinfo.output_height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
1239 if(!dib) throw FI_MSG_ERROR_DIB_MEMORY;
1240 FreeImage_GetICCProfile(dib)->flags |= FIICC_COLOR_IS_CMYK;
1241 } else {
1242 // load as CMYK and convert to RGB
1243 dib = FreeImage_AllocateHeader(header_only, cinfo.output_width, cinfo.output_height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
1244 if(!dib) throw FI_MSG_ERROR_DIB_MEMORY;
1245 }
1246 } else {
1247 // RGB or greyscale image
1248 dib = FreeImage_AllocateHeader(header_only, cinfo.output_width, cinfo.output_height, 8 * cinfo.output_components, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
1249 if(!dib) throw FI_MSG_ERROR_DIB_MEMORY;
1250
1251 if (cinfo.output_components == 1) {
1252 // build a greyscale palette
1253 RGBQUAD *colors = FreeImage_GetPalette(dib);
1254
1255 for (int i = 0; i < 256; i++) {
1256 colors[i].rgbRed = (BYTE)i;
1257 colors[i].rgbGreen = (BYTE)i;
1258 colors[i].rgbBlue = (BYTE)i;
1259 }
1260 }
1261 }
1262 if(scale_denom != 1) {
1263 // store original size info if a scaling was requested
1264 store_size_info(dib, cinfo.image_width, cinfo.image_height);
1265 }
1266
1267 // step 5c: handle metrices
1268
1269 if (cinfo.density_unit == 1) {
1270 // dots/inch
1271 FreeImage_SetDotsPerMeterX(dib, (unsigned) (((float)cinfo.X_density) / 0.0254000 + 0.5));
1272 FreeImage_SetDotsPerMeterY(dib, (unsigned) (((float)cinfo.Y_density) / 0.0254000 + 0.5));
1273 } else if (cinfo.density_unit == 2) {
1274 // dots/cm
1275 FreeImage_SetDotsPerMeterX(dib, (unsigned) (cinfo.X_density * 100));
1276 FreeImage_SetDotsPerMeterY(dib, (unsigned) (cinfo.Y_density * 100));
1277 }
1278
1279 // step 6: read special markers
1280
1281 read_markers(&cinfo, dib);
1282
1283 // --- header only mode => clean-up and return
1284
1285 if (header_only) {
1286 // release JPEG decompression object
1287 jpeg_destroy_decompress(&cinfo);
1288 // return header data
1289 return dib;
1290 }
1291
1292 // step 7a: while (scan lines remain to be read) jpeg_read_scanlines(...);
1293
1294 if((cinfo.out_color_space == JCS_CMYK) && ((flags & JPEG_CMYK) != JPEG_CMYK)) {
1295 // convert from CMYK to RGB
1296
1297 JSAMPARRAY buffer; // output row buffer
1298 unsigned row_stride; // physical row width in output buffer
1299
1300 // JSAMPLEs per row in output buffer
1301 row_stride = cinfo.output_width * cinfo.output_components;
1302 // make a one-row-high sample array that will go away when done with image
1303 buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
1304
1305 while (cinfo.output_scanline < cinfo.output_height) {
1306 JSAMPROW src = buffer[0];
1307 JSAMPROW dst = FreeImage_GetScanLine(dib, cinfo.output_height - cinfo.output_scanline - 1);
1308
1309 jpeg_read_scanlines(&cinfo, buffer, 1);
1310
1311 for(unsigned x = 0; x < cinfo.output_width; x++) {
1312 WORD K = (WORD)src[3];
1313 dst[FI_RGBA_RED] = (BYTE)((K * src[0]) / 255); // C -> R
1314 dst[FI_RGBA_GREEN] = (BYTE)((K * src[1]) / 255); // M -> G
1315 dst[FI_RGBA_BLUE] = (BYTE)((K * src[2]) / 255); // Y -> B
1316 src += 4;
1317 dst += 3;
1318 }
1319 }
1320
1321 // if original image is CMYK but is converted to RGB, remove ICC profile from Exif-TIFF metadata
1322 FreeImage_SetMetadata(FIMD_EXIF_MAIN, dib, "InterColorProfile", NULL);
1323
1324 } else if((cinfo.out_color_space == JCS_CMYK) && ((flags & JPEG_CMYK) == JPEG_CMYK)) {
1325 // convert from LibJPEG CMYK to standard CMYK
1326
1327 JSAMPARRAY buffer; // output row buffer
1328 unsigned row_stride; // physical row width in output buffer
1329
1330 // JSAMPLEs per row in output buffer
1331 row_stride = cinfo.output_width * cinfo.output_components;
1332 // make a one-row-high sample array that will go away when done with image
1333 buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
1334
1335 while (cinfo.output_scanline < cinfo.output_height) {
1336 JSAMPROW src = buffer[0];
1337 JSAMPROW dst = FreeImage_GetScanLine(dib, cinfo.output_height - cinfo.output_scanline - 1);
1338
1339 jpeg_read_scanlines(&cinfo, buffer, 1);
1340
1341 for(unsigned x = 0; x < cinfo.output_width; x++) {
1342 // CMYK pixels are inverted
1343 dst[0] = ~src[0]; // C
1344 dst[1] = ~src[1]; // M
1345 dst[2] = ~src[2]; // Y
1346 dst[3] = ~src[3]; // K
1347 src += 4;
1348 dst += 4;
1349 }
1350 }
1351
1352 } else {
1353 // normal case (RGB or greyscale image)
1354
1355 while (cinfo.output_scanline < cinfo.output_height) {
1356 JSAMPROW dst = FreeImage_GetScanLine(dib, cinfo.output_height - cinfo.output_scanline - 1);
1357
1358 jpeg_read_scanlines(&cinfo, &dst, 1);
1359 }
1360
1361 // step 7b: swap red and blue components (see LibJPEG/jmorecfg.h: #define RGB_RED, ...)
1362 // The default behavior of the JPEG library is kept "as is" because LibTIFF uses
1363 // LibJPEG "as is".
1364
1365 #if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
1366 SwapRedBlue32(dib);
1367 #endif
1368 }
1369
1370 // step 8: finish decompression
1371
1372 jpeg_finish_decompress(&cinfo);
1373
1374 // step 9: release JPEG decompression object
1375
1376 jpeg_destroy_decompress(&cinfo);
1377
1378 // check for automatic Exif rotation
1379 if(!header_only && ((flags & JPEG_EXIFROTATE) == JPEG_EXIFROTATE)) {
1380 RotateExif(&dib);
1381 }
1382
1383 // everything went well. return the loaded dib
1384
1385 return dib;
1386
1387 } catch (const char *text) {
1388 jpeg_destroy_decompress(&cinfo);
1389 if(NULL != dib) {
1390 FreeImage_Unload(dib);
1391 }
1392 if(NULL != text) {
1393 FreeImage_OutputMessageProc(s_format_id, text);
1394 }
1395 }
1396 }
1397
1398 return NULL;
1399 }
1400
1401 // ----------------------------------------------------------
1402
1403 static BOOL DLL_CALLCONV
Save(FreeImageIO * io,FIBITMAP * dib,fi_handle handle,int page,int flags,void * data)1404 Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
1405 if ((dib) && (handle)) {
1406 try {
1407 // Check dib format
1408
1409 const char *sError = "only 24-bit RGB, 8-bit greyscale/palette or 32-bit CMYK bitmaps can be saved as JPEG";
1410
1411 FREE_IMAGE_COLOR_TYPE color_type = FreeImage_GetColorType(dib);
1412 WORD bpp = (WORD)FreeImage_GetBPP(dib);
1413
1414 if ((bpp != 24) && (bpp != 8) && !(bpp == 32 && (color_type == FIC_CMYK))) {
1415 throw sError;
1416 }
1417
1418 if(bpp == 8) {
1419 // allow grey, reverse grey and palette
1420 if ((color_type != FIC_MINISBLACK) && (color_type != FIC_MINISWHITE) && (color_type != FIC_PALETTE)) {
1421 throw sError;
1422 }
1423 }
1424
1425
1426 struct jpeg_compress_struct cinfo;
1427 ErrorManager fi_error_mgr;
1428
1429 // Step 1: allocate and initialize JPEG compression object
1430
1431 // we set up the normal JPEG error routines, then override error_exit & output_message
1432 cinfo.err = jpeg_std_error(&fi_error_mgr.pub);
1433 fi_error_mgr.pub.error_exit = jpeg_error_exit;
1434 fi_error_mgr.pub.output_message = jpeg_output_message;
1435
1436 // establish the setjmp return context for jpeg_error_exit to use
1437 if (setjmp(fi_error_mgr.setjmp_buffer)) {
1438 // If we get here, the JPEG code has signaled an error.
1439 // We need to clean up the JPEG object, close the input file, and return.
1440 jpeg_destroy_compress(&cinfo);
1441 throw (const char*)NULL;
1442 }
1443
1444 // Now we can initialize the JPEG compression object
1445
1446 jpeg_create_compress(&cinfo);
1447
1448 // Step 2: specify data destination (eg, a file)
1449
1450 jpeg_freeimage_dst(&cinfo, handle, io);
1451
1452 // Step 3: set parameters for compression
1453
1454 cinfo.image_width = FreeImage_GetWidth(dib);
1455 cinfo.image_height = FreeImage_GetHeight(dib);
1456
1457 switch(color_type) {
1458 case FIC_MINISBLACK :
1459 case FIC_MINISWHITE :
1460 cinfo.in_color_space = JCS_GRAYSCALE;
1461 cinfo.input_components = 1;
1462 break;
1463 case FIC_CMYK:
1464 cinfo.in_color_space = JCS_CMYK;
1465 cinfo.input_components = 4;
1466 break;
1467 default :
1468 cinfo.in_color_space = JCS_RGB;
1469 cinfo.input_components = 3;
1470 break;
1471 }
1472
1473 jpeg_set_defaults(&cinfo);
1474
1475 // progressive-JPEG support
1476 if((flags & JPEG_PROGRESSIVE) == JPEG_PROGRESSIVE) {
1477 jpeg_simple_progression(&cinfo);
1478 }
1479
1480 // compute optimal Huffman coding tables for the image
1481 if((flags & JPEG_OPTIMIZE) == JPEG_OPTIMIZE) {
1482 cinfo.optimize_coding = TRUE;
1483 }
1484
1485 // Set JFIF density parameters from the DIB data
1486
1487 cinfo.X_density = (UINT16) (0.5 + 0.0254 * FreeImage_GetDotsPerMeterX(dib));
1488 cinfo.Y_density = (UINT16) (0.5 + 0.0254 * FreeImage_GetDotsPerMeterY(dib));
1489 cinfo.density_unit = 1; // dots / inch
1490
1491 // thumbnail support (JFIF 1.02 extension markers)
1492 if(FreeImage_GetThumbnail(dib) != NULL) {
1493 cinfo.write_JFIF_header = static_cast<boolean>(1); //<### force it, though when color is CMYK it will be incorrect
1494 cinfo.JFIF_minor_version = 2;
1495 }
1496
1497 // baseline JPEG support
1498 if ((flags & JPEG_BASELINE) == JPEG_BASELINE) {
1499 cinfo.write_JFIF_header = static_cast<boolean>(0); // No marker for non-JFIF colorspaces
1500 cinfo.write_Adobe_marker = static_cast<boolean>(0); // write no Adobe marker by default
1501 }
1502
1503 // set subsampling options if required
1504
1505 if(cinfo.in_color_space == JCS_RGB) {
1506 if((flags & JPEG_SUBSAMPLING_411) == JPEG_SUBSAMPLING_411) {
1507 // 4:1:1 (4x1 1x1 1x1) - CrH 25% - CbH 25% - CrV 100% - CbV 100%
1508 // the horizontal color resolution is quartered
1509 cinfo.comp_info[0].h_samp_factor = 4; // Y
1510 cinfo.comp_info[0].v_samp_factor = 1;
1511 cinfo.comp_info[1].h_samp_factor = 1; // Cb
1512 cinfo.comp_info[1].v_samp_factor = 1;
1513 cinfo.comp_info[2].h_samp_factor = 1; // Cr
1514 cinfo.comp_info[2].v_samp_factor = 1;
1515 } else if((flags & JPEG_SUBSAMPLING_420) == JPEG_SUBSAMPLING_420) {
1516 // 4:2:0 (2x2 1x1 1x1) - CrH 50% - CbH 50% - CrV 50% - CbV 50%
1517 // the chrominance resolution in both the horizontal and vertical directions is cut in half
1518 cinfo.comp_info[0].h_samp_factor = 2; // Y
1519 cinfo.comp_info[0].v_samp_factor = 2;
1520 cinfo.comp_info[1].h_samp_factor = 1; // Cb
1521 cinfo.comp_info[1].v_samp_factor = 1;
1522 cinfo.comp_info[2].h_samp_factor = 1; // Cr
1523 cinfo.comp_info[2].v_samp_factor = 1;
1524 } else if((flags & JPEG_SUBSAMPLING_422) == JPEG_SUBSAMPLING_422){ //2x1 (low)
1525 // 4:2:2 (2x1 1x1 1x1) - CrH 50% - CbH 50% - CrV 100% - CbV 100%
1526 // half of the horizontal resolution in the chrominance is dropped (Cb & Cr),
1527 // while the full resolution is retained in the vertical direction, with respect to the luminance
1528 cinfo.comp_info[0].h_samp_factor = 2; // Y
1529 cinfo.comp_info[0].v_samp_factor = 1;
1530 cinfo.comp_info[1].h_samp_factor = 1; // Cb
1531 cinfo.comp_info[1].v_samp_factor = 1;
1532 cinfo.comp_info[2].h_samp_factor = 1; // Cr
1533 cinfo.comp_info[2].v_samp_factor = 1;
1534 }
1535 else if((flags & JPEG_SUBSAMPLING_444) == JPEG_SUBSAMPLING_444){ //1x1 (no subsampling)
1536 // 4:4:4 (1x1 1x1 1x1) - CrH 100% - CbH 100% - CrV 100% - CbV 100%
1537 // the resolution of chrominance information (Cb & Cr) is preserved
1538 // at the same rate as the luminance (Y) information
1539 cinfo.comp_info[0].h_samp_factor = 1; // Y
1540 cinfo.comp_info[0].v_samp_factor = 1;
1541 cinfo.comp_info[1].h_samp_factor = 1; // Cb
1542 cinfo.comp_info[1].v_samp_factor = 1;
1543 cinfo.comp_info[2].h_samp_factor = 1; // Cr
1544 cinfo.comp_info[2].v_samp_factor = 1;
1545 }
1546 }
1547
1548 // Step 4: set quality
1549 // the first 7 bits are reserved for low level quality settings
1550 // the other bits are high level (i.e. enum-ish)
1551
1552 int quality;
1553
1554 if ((flags & JPEG_QUALITYBAD) == JPEG_QUALITYBAD) {
1555 quality = 10;
1556 } else if ((flags & JPEG_QUALITYAVERAGE) == JPEG_QUALITYAVERAGE) {
1557 quality = 25;
1558 } else if ((flags & JPEG_QUALITYNORMAL) == JPEG_QUALITYNORMAL) {
1559 quality = 50;
1560 } else if ((flags & JPEG_QUALITYGOOD) == JPEG_QUALITYGOOD) {
1561 quality = 75;
1562 } else if ((flags & JPEG_QUALITYSUPERB) == JPEG_QUALITYSUPERB) {
1563 quality = 100;
1564 } else {
1565 if ((flags & 0x7F) == 0) {
1566 quality = 75;
1567 } else {
1568 quality = flags & 0x7F;
1569 }
1570 }
1571
1572 jpeg_set_quality(&cinfo, quality, TRUE); /* limit to baseline-JPEG values */
1573
1574 // Step 5: Start compressor
1575
1576 jpeg_start_compress(&cinfo, TRUE);
1577
1578 // Step 6: Write special markers
1579
1580 if ((flags & JPEG_BASELINE) != JPEG_BASELINE) {
1581 write_markers(&cinfo, dib);
1582 }
1583
1584 // Step 7: while (scan lines remain to be written)
1585
1586 if(color_type == FIC_RGB) {
1587 // 24-bit RGB image : need to swap red and blue channels
1588 unsigned pitch = FreeImage_GetPitch(dib);
1589 BYTE *target = (BYTE*)malloc(pitch * sizeof(BYTE));
1590 if (target == NULL) {
1591 throw FI_MSG_ERROR_MEMORY;
1592 }
1593
1594 while (cinfo.next_scanline < cinfo.image_height) {
1595 // get a copy of the scanline
1596 memcpy(target, FreeImage_GetScanLine(dib, FreeImage_GetHeight(dib) - cinfo.next_scanline - 1), pitch);
1597 #if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
1598 // swap R and B channels
1599 BYTE *target_p = target;
1600 for(unsigned x = 0; x < cinfo.image_width; x++) {
1601 INPLACESWAP(target_p[0], target_p[2]);
1602 target_p += 3;
1603 }
1604 #endif
1605 // write the scanline
1606 jpeg_write_scanlines(&cinfo, &target, 1);
1607 }
1608 free(target);
1609 }
1610 else if(color_type == FIC_CMYK) {
1611 unsigned pitch = FreeImage_GetPitch(dib);
1612 BYTE *target = (BYTE*)malloc(pitch * sizeof(BYTE));
1613 if (target == NULL) {
1614 throw FI_MSG_ERROR_MEMORY;
1615 }
1616
1617 while (cinfo.next_scanline < cinfo.image_height) {
1618 // get a copy of the scanline
1619 memcpy(target, FreeImage_GetScanLine(dib, FreeImage_GetHeight(dib) - cinfo.next_scanline - 1), pitch);
1620
1621 BYTE *target_p = target;
1622 for(unsigned x = 0; x < cinfo.image_width; x++) {
1623 // CMYK pixels are inverted
1624 target_p[0] = ~target_p[0]; // C
1625 target_p[1] = ~target_p[1]; // M
1626 target_p[2] = ~target_p[2]; // Y
1627 target_p[3] = ~target_p[3]; // K
1628
1629 target_p += 4;
1630 }
1631
1632 // write the scanline
1633 jpeg_write_scanlines(&cinfo, &target, 1);
1634 }
1635 free(target);
1636 }
1637 else if(color_type == FIC_MINISBLACK) {
1638 // 8-bit standard greyscale images
1639 while (cinfo.next_scanline < cinfo.image_height) {
1640 JSAMPROW b = FreeImage_GetScanLine(dib, FreeImage_GetHeight(dib) - cinfo.next_scanline - 1);
1641
1642 jpeg_write_scanlines(&cinfo, &b, 1);
1643 }
1644 }
1645 else if(color_type == FIC_PALETTE) {
1646 // 8-bit palettized images are converted to 24-bit images
1647 RGBQUAD *palette = FreeImage_GetPalette(dib);
1648 BYTE *target = (BYTE*)malloc(cinfo.image_width * 3);
1649 if (target == NULL) {
1650 throw FI_MSG_ERROR_MEMORY;
1651 }
1652
1653 while (cinfo.next_scanline < cinfo.image_height) {
1654 BYTE *source = FreeImage_GetScanLine(dib, FreeImage_GetHeight(dib) - cinfo.next_scanline - 1);
1655 FreeImage_ConvertLine8To24(target, source, cinfo.image_width, palette);
1656
1657 #if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
1658 // swap R and B channels
1659 BYTE *target_p = target;
1660 for(unsigned x = 0; x < cinfo.image_width; x++) {
1661 INPLACESWAP(target_p[0], target_p[2]);
1662 target_p += 3;
1663 }
1664 #endif
1665
1666
1667 jpeg_write_scanlines(&cinfo, &target, 1);
1668 }
1669
1670 free(target);
1671 }
1672 else if(color_type == FIC_MINISWHITE) {
1673 // reverse 8-bit greyscale image, so reverse grey value on the fly
1674 unsigned i;
1675 BYTE reverse[256];
1676 BYTE *target = (BYTE *)malloc(cinfo.image_width);
1677 if (target == NULL) {
1678 throw FI_MSG_ERROR_MEMORY;
1679 }
1680
1681 for(i = 0; i < 256; i++) {
1682 reverse[i] = (BYTE)(255 - i);
1683 }
1684
1685 while(cinfo.next_scanline < cinfo.image_height) {
1686 BYTE *source = FreeImage_GetScanLine(dib, FreeImage_GetHeight(dib) - cinfo.next_scanline - 1);
1687 for(i = 0; i < cinfo.image_width; i++) {
1688 target[i] = reverse[ source[i] ];
1689 }
1690 jpeg_write_scanlines(&cinfo, &target, 1);
1691 }
1692
1693 free(target);
1694 }
1695
1696 // Step 8: Finish compression
1697
1698 jpeg_finish_compress(&cinfo);
1699
1700 // Step 9: release JPEG compression object
1701
1702 jpeg_destroy_compress(&cinfo);
1703
1704 return TRUE;
1705
1706 } catch (const char *text) {
1707 if(text) {
1708 FreeImage_OutputMessageProc(s_format_id, text);
1709 }
1710 return FALSE;
1711 }
1712 }
1713
1714 return FALSE;
1715 }
1716
1717 // ==========================================================
1718 // Init
1719 // ==========================================================
1720
1721 void DLL_CALLCONV
InitJPEG(Plugin * plugin,int format_id)1722 InitJPEG(Plugin *plugin, int format_id) {
1723 s_format_id = format_id;
1724
1725 plugin->format_proc = Format;
1726 plugin->description_proc = Description;
1727 plugin->extension_proc = Extension;
1728 plugin->regexpr_proc = RegExpr;
1729 plugin->open_proc = NULL;
1730 plugin->close_proc = NULL;
1731 plugin->pagecount_proc = NULL;
1732 plugin->pagecapability_proc = NULL;
1733 plugin->load_proc = Load;
1734 plugin->save_proc = Save;
1735 plugin->validate_proc = Validate;
1736 plugin->mime_proc = MimeType;
1737 plugin->supports_export_bpp_proc = SupportsExportDepth;
1738 plugin->supports_export_type_proc = SupportsExportType;
1739 plugin->supports_icc_profiles_proc = SupportsICCProfiles;
1740 plugin->supports_no_pixels_proc = SupportsNoPixels;
1741 }
1742