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