PageRenderTime 135ms CodeModel.GetById 30ms app.highlight 92ms RepoModel.GetById 1ms app.codeStats 1ms

/src/FreeImage/Source/FreeImage/PluginJPEG.cpp

https://bitbucket.org/cabalistic/ogredeps/
C++ | 1801 lines | 1042 code | 330 blank | 429 comment | 256 complexity | eac9a6561e8829034f59d4fefed92708 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   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
  33extern "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
  53static 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
  80typedef struct tagErrorManager {
  81	/// "public" fields
  82	struct jpeg_error_mgr pub;
  83	/// for return to caller
  84	jmp_buf setjmp_buffer;
  85} ErrorManager;
  86
  87typedef 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
  99typedef 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
 109typedef SourceManager*		freeimage_src_ptr;
 110typedef DestinationManager* freeimage_dst_ptr;
 111typedef ErrorManager*		freeimage_error_ptr;
 112
 113// ----------------------------------------------------------
 114//   Error handling
 115// ----------------------------------------------------------
 116
 117/** Fatal errors (print message and exit) */
 118static inline void
 119JPEG_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) */
 126static inline void
 127JPEG_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*/
 139METHODDEF(void)
 140jpeg_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*/
 161METHODDEF(void)
 162jpeg_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*/
 182METHODDEF(void)
 183init_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*/
 205METHODDEF(boolean)
 206empty_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*/
 228METHODDEF(void)
 229term_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*/
 256METHODDEF(void)
 257init_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*/
 279METHODDEF(boolean)
 280fill_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*/
 322METHODDEF(void)
 323skip_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*/
 355METHODDEF(void)
 356term_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*/
 369GLOBAL(void)
 370jpeg_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*/
 404GLOBAL(void)
 405jpeg_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*/
 428static BOOL 
 429jpeg_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/**
 468Handy subroutine to test whether a saved marker is an ICC profile marker.
 469*/
 470static BOOL 
 471marker_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*/
 505static BOOL 
 506jpeg_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*/
 600static BOOL 
 601jpeg_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*/
 612static BOOL  
 613jpeg_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 JPEG_APP1 marker (Exif profile)
 660	@param dib Input FIBITMAP
 661	@param dataptr Pointer to the APP1 marker
 662	@param datalen APP1 marker length
 663	@return Returns TRUE if successful, FALSE otherwise
 664*/
 665static BOOL  
 666jpeg_read_exif_profile_raw(FIBITMAP *dib, const BYTE *profile, unsigned int length) {
 667    // marker identifying string for Exif = "Exif\0\0"
 668    BYTE exif_signature[6] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 };
 669
 670	// verify the identifying string
 671	if(memcmp(exif_signature, profile, sizeof(exif_signature)) != 0) {
 672		// not an Exif profile
 673		return FALSE;
 674	}
 675
 676	// create a tag
 677	FITAG *tag = FreeImage_CreateTag();
 678	if(tag) {
 679		FreeImage_SetTagID(tag, EXIF_MARKER);	// (JPEG_APP0 + 1) => EXIF marker / Adobe XMP marker
 680		FreeImage_SetTagKey(tag, g_TagLib_ExifRawFieldName);
 681		FreeImage_SetTagLength(tag, (DWORD)length);
 682		FreeImage_SetTagCount(tag, (DWORD)length);
 683		FreeImage_SetTagType(tag, FIDT_BYTE);
 684		FreeImage_SetTagValue(tag, profile);
 685
 686		// store the tag
 687		FreeImage_SetMetadata(FIMD_EXIF_RAW, dib, FreeImage_GetTagKey(tag), tag);
 688
 689		// destroy the tag
 690		FreeImage_DeleteTag(tag);
 691
 692		return TRUE;
 693	}
 694
 695	return FALSE;
 696}
 697
 698/**
 699	Read JFIF "JFXX" extension APP0 marker
 700	@param dib Input FIBITMAP
 701	@param dataptr Pointer to the APP0 marker
 702	@param datalen APP0 marker length
 703	@return Returns TRUE if successful, FALSE otherwise
 704*/
 705static BOOL 
 706jpeg_read_jfxx(FIBITMAP *dib, const BYTE *dataptr, unsigned int datalen) {
 707	if(datalen < 6) {
 708		return FALSE;
 709	}
 710	
 711	const int id_length = 5;
 712	const BYTE *data = dataptr + id_length;
 713	unsigned remaining = datalen - id_length;
 714		
 715	const BYTE type = *data;
 716	++data, --remaining;
 717
 718	switch(type) {
 719		case JFXX_TYPE_JPEG:
 720		{
 721			// load the thumbnail
 722			FIMEMORY* hmem = FreeImage_OpenMemory(const_cast<BYTE*>(data), remaining);
 723			FIBITMAP* thumbnail = FreeImage_LoadFromMemory(FIF_JPEG, hmem);
 724			FreeImage_CloseMemory(hmem);
 725			// store the thumbnail
 726			FreeImage_SetThumbnail(dib, thumbnail);
 727			// then delete it
 728			FreeImage_Unload(thumbnail);
 729			break;
 730		}
 731		case JFXX_TYPE_8bit:
 732			// colormapped uncompressed thumbnail (no supported)
 733			break;
 734		case JFXX_TYPE_24bit:
 735			// truecolor uncompressed thumbnail (no supported)
 736			break;
 737		default:
 738			break;
 739	}
 740
 741	return TRUE;
 742}
 743
 744
 745/**
 746	Read JPEG special markers
 747*/
 748static BOOL 
 749read_markers(j_decompress_ptr cinfo, FIBITMAP *dib) {
 750	jpeg_saved_marker_ptr marker;
 751
 752	for(marker = cinfo->marker_list; marker != NULL; marker = marker->next) {
 753		switch(marker->marker) {
 754			case JPEG_APP0:
 755				// JFIF is handled by libjpeg already, handle JFXX
 756				if(memcmp(marker->data, "JFIF" , 5) == 0) {
 757					continue;
 758				}
 759				if(memcmp(marker->data, "JFXX" , 5) == 0) {
 760					if(!cinfo->saw_JFIF_marker || cinfo->JFIF_minor_version < 2) {
 761						FreeImage_OutputMessageProc(s_format_id, "Warning: non-standard JFXX segment");
 762					}					
 763					jpeg_read_jfxx(dib, marker->data, marker->data_length);
 764				}
 765				// other values such as 'Picasa' : ignore safely unknown APP0 marker
 766				break;
 767			case JPEG_COM:
 768				// JPEG comment
 769				jpeg_read_comment(dib, marker->data, marker->data_length);
 770				break;
 771			case EXIF_MARKER:
 772				// Exif or Adobe XMP profile
 773				jpeg_read_exif_profile(dib, marker->data, marker->data_length);
 774				jpeg_read_xmp_profile(dib, marker->data, marker->data_length);
 775				jpeg_read_exif_profile_raw(dib, marker->data, marker->data_length);
 776				break;
 777			case IPTC_MARKER:
 778				// IPTC/NAA or Adobe Photoshop profile
 779				jpeg_read_iptc_profile(dib, marker->data, marker->data_length);
 780				break;
 781		}
 782	}
 783
 784	// ICC profile
 785	BYTE *icc_profile = NULL;
 786	unsigned icc_length = 0;
 787
 788	if( jpeg_read_icc_profile(cinfo, &icc_profile, &icc_length) ) {
 789		// copy ICC profile data
 790		FreeImage_CreateICCProfile(dib, icc_profile, icc_length);
 791		// clean up
 792		free(icc_profile);
 793	}
 794
 795	return TRUE;
 796}
 797
 798// ----------------------------------------------------------
 799//   Special markers write functions
 800// ----------------------------------------------------------
 801
 802/**
 803	Write JPEG_COM marker (comment)
 804*/
 805static BOOL 
 806jpeg_write_comment(j_compress_ptr cinfo, FIBITMAP *dib) {
 807	FITAG *tag = NULL;
 808
 809	// write user comment as a JPEG_COM marker
 810	FreeImage_GetMetadata(FIMD_COMMENTS, dib, "Comment", &tag);
 811	if(tag) {
 812		const char *tag_value = (char*)FreeImage_GetTagValue(tag);
 813
 814		if(NULL != tag_value) {
 815			for(long i = 0; i < (long)strlen(tag_value); i+= MAX_BYTES_IN_MARKER) {
 816				jpeg_write_marker(cinfo, JPEG_COM, (BYTE*)tag_value + i, MIN((long)strlen(tag_value + i), MAX_BYTES_IN_MARKER));
 817			}
 818			return TRUE;
 819		}
 820	}
 821	return FALSE;
 822}
 823
 824/** 
 825	Write JPEG_APP2 marker (ICC profile)
 826*/
 827static BOOL 
 828jpeg_write_icc_profile(j_compress_ptr cinfo, FIBITMAP *dib) {
 829    // marker identifying string "ICC_PROFILE" (null-terminated)
 830	BYTE icc_signature[12] = { 0x49, 0x43, 0x43, 0x5F, 0x50, 0x52, 0x4F, 0x46, 0x49, 0x4C, 0x45, 0x00 };
 831
 832	FIICCPROFILE *iccProfile = FreeImage_GetICCProfile(dib);
 833
 834	if (iccProfile->size && iccProfile->data) {
 835		// ICC_HEADER_SIZE: ICC signature is 'ICC_PROFILE' + 2 bytes
 836
 837		BYTE *profile = (BYTE*)malloc((iccProfile->size + ICC_HEADER_SIZE) * sizeof(BYTE));
 838		if(profile == NULL) return FALSE;
 839		memcpy(profile, icc_signature, 12);
 840
 841		for(long i = 0; i < (long)iccProfile->size; i += MAX_DATA_BYTES_IN_MARKER) {
 842			unsigned length = MIN((long)(iccProfile->size - i), MAX_DATA_BYTES_IN_MARKER);
 843			// sequence number
 844			profile[12] = (BYTE) ((i / MAX_DATA_BYTES_IN_MARKER) + 1);
 845			// number of markers
 846			profile[13] = (BYTE) (iccProfile->size / MAX_DATA_BYTES_IN_MARKER + 1);
 847
 848			memcpy(profile + ICC_HEADER_SIZE, (BYTE*)iccProfile->data + i, length);
 849			jpeg_write_marker(cinfo, ICC_MARKER, profile, (length + ICC_HEADER_SIZE));
 850        }
 851
 852		free(profile);
 853
 854		return TRUE;		
 855	}
 856	
 857	return FALSE;
 858}
 859
 860/** 
 861	Write JPEG_APPD marker (IPTC or Adobe Photoshop profile)
 862	@return Returns TRUE if successful, FALSE otherwise
 863*/
 864static BOOL  
 865jpeg_write_iptc_profile(j_compress_ptr cinfo, FIBITMAP *dib) {
 866	//const char *ps_header = "Photoshop 3.0\x08BIM\x04\x04\x0\x0\x0\x0";
 867	const unsigned tag_length = 26;
 868
 869	if(FreeImage_GetMetadataCount(FIMD_IPTC, dib)) {
 870		BYTE *profile = NULL;
 871		unsigned profile_size = 0;
 872
 873		// create a binary profile
 874		if(write_iptc_profile(dib, &profile, &profile_size)) {
 875
 876			// write the profile
 877			for(long i = 0; i < (long)profile_size; i += 65517L) {
 878				unsigned length = MIN((long)profile_size - i, 65517L);
 879				unsigned roundup = length & 0x01;	// needed for Photoshop
 880				BYTE *iptc_profile = (BYTE*)malloc(length + roundup + tag_length);
 881				if(iptc_profile == NULL) break;
 882				// Photoshop identification string
 883				memcpy(&iptc_profile[0], "Photoshop 3.0\x0", 14);
 884				// 8BIM segment type
 885				memcpy(&iptc_profile[14], "8BIM\x04\x04\x0\x0\x0\x0", 10);
 886				// segment size
 887				iptc_profile[24] = (BYTE)(length >> 8);
 888				iptc_profile[25] = (BYTE)(length & 0xFF);
 889				// segment data
 890				memcpy(&iptc_profile[tag_length], &profile[i], length);
 891				if(roundup)
 892					iptc_profile[length + tag_length] = 0;
 893				jpeg_write_marker(cinfo, IPTC_MARKER, iptc_profile, length + roundup + tag_length);
 894				free(iptc_profile);
 895			}
 896
 897			// release profile
 898			free(profile);
 899
 900			return TRUE;
 901		}
 902	}
 903
 904	return FALSE;
 905}
 906
 907/** 
 908	Write JPEG_APP1 marker (XMP profile)
 909	@return Returns TRUE if successful, FALSE otherwise
 910*/
 911static BOOL  
 912jpeg_write_xmp_profile(j_compress_ptr cinfo, FIBITMAP *dib) {
 913	// marker identifying string for XMP (null terminated)
 914	const char *xmp_signature = "http://ns.adobe.com/xap/1.0/";
 915
 916	FITAG *tag_xmp = NULL;
 917	FreeImage_GetMetadata(FIMD_XMP, dib, g_TagLib_XMPFieldName, &tag_xmp);
 918
 919	if(tag_xmp) {
 920		const BYTE *tag_value = (BYTE*)FreeImage_GetTagValue(tag_xmp);
 921
 922		if(NULL != tag_value) {
 923			// XMP signature is 29 bytes long
 924			unsigned int xmp_header_size = (unsigned int)strlen(xmp_signature) + 1;
 925
 926			DWORD tag_length = FreeImage_GetTagLength(tag_xmp);
 927
 928			BYTE *profile = (BYTE*)malloc((tag_length + xmp_header_size) * sizeof(BYTE));
 929			if(profile == NULL) return FALSE;
 930			memcpy(profile, xmp_signature, xmp_header_size);
 931
 932			for(DWORD i = 0; i < tag_length; i += 65504L) {
 933				unsigned length = MIN((long)(tag_length - i), 65504L);
 934				
 935				memcpy(profile + xmp_header_size, tag_value + i, length);
 936				jpeg_write_marker(cinfo, EXIF_MARKER, profile, (length + xmp_header_size));
 937			}
 938
 939			free(profile);
 940
 941			return TRUE;	
 942		}
 943	}
 944
 945	return FALSE;
 946}
 947
 948/** 
 949	Write JPEG_APP1 marker (Exif profile)
 950	@return Returns TRUE if successful, FALSE otherwise
 951*/
 952static BOOL 
 953jpeg_write_exif_profile_raw(j_compress_ptr cinfo, FIBITMAP *dib) {
 954    // marker identifying string for Exif = "Exif\0\0"
 955    BYTE exif_signature[6] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 };
 956
 957	FITAG *tag_exif = NULL;
 958	FreeImage_GetMetadata(FIMD_EXIF_RAW, dib, g_TagLib_ExifRawFieldName, &tag_exif);
 959
 960	if(tag_exif) {
 961		const BYTE *tag_value = (BYTE*)FreeImage_GetTagValue(tag_exif);
 962		
 963		// verify the identifying string
 964		if(memcmp(exif_signature, tag_value, sizeof(exif_signature)) != 0) {
 965			// not an Exif profile
 966			return FALSE;
 967		}
 968
 969		if(NULL != tag_value) {
 970			DWORD tag_length = FreeImage_GetTagLength(tag_exif);
 971
 972			BYTE *profile = (BYTE*)malloc(tag_length * sizeof(BYTE));
 973			if(profile == NULL) return FALSE;
 974
 975			for(DWORD i = 0; i < tag_length; i += 65504L) {
 976				unsigned length = MIN((long)(tag_length - i), 65504L);
 977				
 978				memcpy(profile, tag_value + i, length);
 979				jpeg_write_marker(cinfo, EXIF_MARKER, profile, length);
 980			}
 981
 982			free(profile);
 983
 984			return TRUE;	
 985		}
 986	}
 987
 988	return FALSE;
 989}
 990
 991/**
 992	Write thumbnail (JFXX segment, JPEG compressed)
 993*/
 994static BOOL
 995jpeg_write_jfxx(j_compress_ptr cinfo, FIBITMAP *dib) {
 996	// get the thumbnail to be stored
 997	FIBITMAP* thumbnail = FreeImage_GetThumbnail(dib);
 998	if(!thumbnail) {
 999		return TRUE;
1000	}
1001	// check for a compatible output format
1002	if((FreeImage_GetImageType(thumbnail) != FIT_BITMAP) || (FreeImage_GetBPP(thumbnail) != 8) && (FreeImage_GetBPP(thumbnail) != 24)) {
1003		FreeImage_OutputMessageProc(s_format_id, FI_MSG_WARNING_INVALID_THUMBNAIL);
1004		return FALSE;
1005	}
1006	
1007	// stores the thumbnail as a baseline JPEG into a memory block
1008	// return the memory block only if its size is within JFXX marker size limit!
1009	FIMEMORY *stream = FreeImage_OpenMemory();
1010	
1011	if(FreeImage_SaveToMemory(FIF_JPEG, thumbnail, stream, JPEG_BASELINE)) {
1012		// check that the memory block size is within JFXX marker size limit
1013		FreeImage_SeekMemory(stream, 0, SEEK_END);
1014		const long eof = FreeImage_TellMemory(stream);
1015		if(eof > MAX_JFXX_THUMB_SIZE) {
1016			FreeImage_OutputMessageProc(s_format_id, "Warning: attached thumbnail is %d bytes larger than maximum supported size - Thumbnail saving aborted", eof - MAX_JFXX_THUMB_SIZE);
1017			FreeImage_CloseMemory(stream);
1018			return FALSE;
1019		}
1020	} else {
1021		FreeImage_CloseMemory(stream);
1022		return FALSE;
1023	}
1024
1025	BYTE* thData = NULL;
1026	DWORD thSize = 0;
1027	
1028	FreeImage_AcquireMemory(stream, &thData, &thSize);	
1029	
1030	BYTE id_length = 5; //< "JFXX"
1031	BYTE type = JFXX_TYPE_JPEG;
1032	
1033	DWORD totalsize = id_length + sizeof(type) + thSize;
1034	jpeg_write_m_header(cinfo, JPEG_APP0, totalsize);
1035	
1036	jpeg_write_m_byte(cinfo, 'J');
1037	jpeg_write_m_byte(cinfo, 'F');
1038	jpeg_write_m_byte(cinfo, 'X');
1039	jpeg_write_m_byte(cinfo, 'X');
1040	jpeg_write_m_byte(cinfo, '\0');
1041	
1042	jpeg_write_m_byte(cinfo, type);
1043	
1044	// write thumbnail to destination.
1045	// We "cram it straight into the data destination module", because write_m_byte is slow
1046	
1047	freeimage_dst_ptr dest = (freeimage_dst_ptr) cinfo->dest;
1048	
1049	BYTE* & out = dest->pub.next_output_byte;
1050	size_t & bufRemain = dest->pub.free_in_buffer;
1051	
1052	const BYTE *thData_end = thData + thSize;
1053
1054	while(thData < thData_end) {
1055		*(out)++ = *(thData)++;
1056		if (--bufRemain == 0) {	
1057			// buffer full - flush
1058			if (!dest->pub.empty_output_buffer(cinfo)) {
1059				break;
1060			}
1061		}
1062	}
1063	
1064	FreeImage_CloseMemory(stream);
1065
1066	return TRUE;
1067}
1068
1069/**
1070	Write JPEG special markers
1071*/
1072static BOOL 
1073write_markers(j_compress_ptr cinfo, FIBITMAP *dib) {
1074	// write thumbnail as a JFXX marker
1075	jpeg_write_jfxx(cinfo, dib);
1076
1077	// write user comment as a JPEG_COM marker
1078	jpeg_write_comment(cinfo, dib);
1079
1080	// write ICC profile
1081	jpeg_write_icc_profile(cinfo, dib);
1082
1083	// write IPTC profile
1084	jpeg_write_iptc_profile(cinfo, dib);
1085
1086	// write Adobe XMP profile
1087	jpeg_write_xmp_profile(cinfo, dib);
1088
1089	// write Exif raw data
1090	jpeg_write_exif_profile_raw(cinfo, dib);
1091
1092	return TRUE;
1093}
1094
1095// ------------------------------------------------------------
1096//   Keep original size info when using scale option on loading
1097// ------------------------------------------------------------
1098static void 
1099store_size_info(FIBITMAP *dib, JDIMENSION width, JDIMENSION height) {
1100	char buffer[256];
1101	// create a tag
1102	FITAG *tag = FreeImage_CreateTag();
1103	if(tag) {
1104		size_t length = 0;
1105		// set the original width
1106		sprintf(buffer, "%d", (int)width);
1107		length = strlen(buffer) + 1;	// include the NULL/0 value
1108		FreeImage_SetTagKey(tag, "OriginalJPEGWidth");
1109		FreeImage_SetTagLength(tag, (DWORD)length);
1110		FreeImage_SetTagCount(tag, (DWORD)length);
1111		FreeImage_SetTagType(tag, FIDT_ASCII);
1112		FreeImage_SetTagValue(tag, buffer);
1113		FreeImage_SetMetadata(FIMD_COMMENTS, dib, FreeImage_GetTagKey(tag), tag);
1114		// set the original height
1115		sprintf(buffer, "%d", (int)height);
1116		length = strlen(buffer) + 1;	// include the NULL/0 value
1117		FreeImage_SetTagKey(tag, "OriginalJPEGHeight");
1118		FreeImage_SetTagLength(tag, (DWORD)length);
1119		FreeImage_SetTagCount(tag, (DWORD)length);
1120		FreeImage_SetTagType(tag, FIDT_ASCII);
1121		FreeImage_SetTagValue(tag, buffer);
1122		FreeImage_SetMetadata(FIMD_COMMENTS, dib, FreeImage_GetTagKey(tag), tag);
1123		// destroy the tag
1124		FreeImage_DeleteTag(tag);
1125	}
1126}
1127
1128// ------------------------------------------------------------
1129//   Rotate a dib according to Exif info
1130// ------------------------------------------------------------
1131
1132static void 
1133rotate_exif(FIBITMAP **dib) {
1134	// check for Exif rotation
1135	if(FreeImage_GetMetadataCount(FIMD_EXIF_MAIN, *dib)) {
1136		FIBITMAP *rotated = NULL;
1137		// process Exif rotation
1138		FITAG *tag = NULL;
1139		FreeImage_GetMetadata(FIMD_EXIF_MAIN, *dib, "Orientation", &tag);
1140		if(tag != NULL) {
1141			if(FreeImage_GetTagID(tag) == TAG_ORIENTATION) {
1142				unsigned short orientation = *((unsigned short *)FreeImage_GetTagValue(tag));
1143				switch (orientation) {
1144					case 1:		// "top, left side" => 0°
1145						break;
1146					case 2:		// "top, right side" => flip left-right
1147						FreeImage_FlipHorizontal(*dib);
1148						break;
1149					case 3:		// "bottom, right side"; => -180°
1150						rotated = FreeImage_Rotate(*dib, 180);
1151						FreeImage_Unload(*dib);
1152						*dib = rotated;
1153						break;
1154					case 4:		// "bottom, left side" => flip up-down
1155						FreeImage_FlipVertical(*dib);
1156						break;
1157					case 5:		// "left side, top" => +90° + flip up-down
1158						rotated = FreeImage_Rotate(*dib, 90);
1159						FreeImage_Unload(*dib);
1160						*dib = rotated;
1161						FreeImage_FlipVertical(*dib);
1162						break;
1163					case 6:		// "right side, top" => -90°
1164						rotated = FreeImage_Rotate(*dib, -90);
1165						FreeImage_Unload(*dib);
1166						*dib = rotated;
1167						break;
1168					case 7:		// "right side, bottom" => -90° + flip up-down
1169						rotated = FreeImage_Rotate(*dib, -90);
1170						FreeImage_Unload(*dib);
1171						*dib = rotated;
1172						FreeImage_FlipVertical(*dib);
1173						break;
1174					case 8:		// "left side, bottom" => +90°
1175						rotated = FreeImage_Rotate(*dib, 90);
1176						FreeImage_Unload(*dib);
1177						*dib = rotated;
1178						break;
1179					default:
1180						break;
1181				}
1182			}
1183		}
1184	}
1185}
1186
1187
1188// ==========================================================
1189// Plugin Implementation
1190// ==========================================================
1191
1192static const char * DLL_CALLCONV
1193Format() {
1194	return "JPEG";
1195}
1196
1197static const char * DLL_CALLCONV
1198Description() {
1199	return "JPEG - JFIF Compliant";
1200}
1201
1202static const char * DLL_CALLCONV
1203Extension() {
1204	return "jpg,jif,jpeg,jpe";
1205}
1206
1207static const char * DLL_CALLCONV
1208RegExpr() {
1209	return "^\377\330\377";
1210}
1211
1212static const char * DLL_CALLCONV
1213MimeType() {
1214	return "image/jpeg";
1215}
1216
1217static BOOL DLL_CALLCONV
1218Validate(FreeImageIO *io, fi_handle handle) {
1219	BYTE jpeg_signature[] = { 0xFF, 0xD8 };
1220	BYTE signature[2] = { 0, 0 };
1221
1222	io->read_proc(signature, 1, sizeof(jpeg_signature), handle);
1223
1224	return (memcmp(jpeg_signature, signature, sizeof(jpeg_signature)) == 0);
1225}
1226
1227static BOOL DLL_CALLCONV
1228SupportsExportDepth(int depth) {
1229	return (
1230			(depth == 8) ||
1231			(depth == 24)
1232		);
1233}
1234
1235static BOOL DLL_CALLCONV 
1236SupportsExportType(FREE_IMAGE_TYPE type) {
1237	return (type == FIT_BITMAP) ? TRUE : FALSE;
1238}
1239
1240static BOOL DLL_CALLCONV
1241SupportsICCProfiles() {
1242	return TRUE;
1243}
1244
1245static BOOL DLL_CALLCONV
1246SupportsNoPixels() {
1247	return TRUE;
1248}
1249
1250// ----------------------------------------------------------
1251
1252static FIBITMAP * DLL_CALLCONV
1253Load(FreeImageIO *io, fi_handle handle, int page, int flags, void *data) {
1254	if (handle) {
1255		FIBITMAP *dib = NULL;
1256
1257		BOOL header_only = (flags & FIF_LOAD_NOPIXELS) == FIF_LOAD_NOPIXELS;
1258
1259		// set up the jpeglib structures
1260
1261		struct jpeg_decompress_struct cinfo;
1262		ErrorManager fi_error_mgr;
1263
1264		try {
1265
1266			// step 1: allocate and initialize JPEG decompression object
1267
1268			// we set up the normal JPEG error routines, then override error_exit & output_message
1269			cinfo.err = jpeg_std_error(&fi_error_mgr.pub);
1270			fi_error_mgr.pub.error_exit     = jpeg_error_exit;
1271			fi_error_mgr.pub.output_message = jpeg_output_message;
1272			
1273			// establish the setjmp return context for jpeg_error_exit to use
1274			if (setjmp(fi_error_mgr.setjmp_buffer)) {
1275				// If we get here, the JPEG code has signaled an error.
1276				// We need to clean up the JPEG object, close the input file, and return.
1277				jpeg_destroy_decompress(&cinfo);
1278				throw (const char*)NULL;
1279			}
1280
1281			jpeg_create_decompress(&cinfo);
1282
1283			// step 2a: specify data source (eg, a handle)
1284
1285			jpeg_freeimage_src(&cinfo, handle, io);
1286
1287			// step 2b: save special markers for later reading
1288			
1289			jpeg_save_markers(&cinfo, JPEG_COM, 0xFFFF);
1290			for(int m = 0; m < 16; m++) {
1291				jpeg_save_markers(&cinfo, JPEG_APP0 + m, 0xFFFF);
1292			}
1293
1294			// step 3: read handle parameters with jpeg_read_header()
1295
1296			jpeg_read_header(&cinfo, TRUE);
1297
1298			// step 4: set parameters for decompression
1299
1300			unsigned int scale_denom = 1;		// fraction by which to scale image
1301			int	requested_size = flags >> 16;	// requested user size in pixels
1302			if(requested_size > 0) {
1303				// the JPEG codec can perform x2, x4 or x8 scaling on loading
1304				// try to find the more appropriate scaling according to user's need
1305				double scale = MAX((double)cinfo.image_width, (double)cinfo.image_height) / (double)requested_size;
1306				if(scale >= 8) {
1307					scale_denom = 8;
1308				} else if(scale >= 4) {
1309					scale_denom = 4;
1310				} else if(scale >= 2) {
1311					scale_denom = 2;
1312				}
1313			}
1314			cinfo.scale_num = 1;
1315			cinfo.scale_denom = scale_denom;
1316
1317			if ((flags & JPEG_ACCURATE) != JPEG_ACCURATE) {
1318				cinfo.dct_method          = JDCT_IFAST;
1319				cinfo.do_fancy_upsampling = FALSE;
1320			}
1321
1322			// step 5a: start decompressor and calculate output width and height
1323
1324			jpeg_start_decompress(&cinfo);
1325
1326			// step 5b: allocate dib and init header
1327
1328			if((cinfo.num_components == 4) && (cinfo.out_color_space == JCS_CMYK)) {
1329				// CMYK image
1330				if((flags & JPEG_CMYK) == JPEG_CMYK) {
1331					// load as CMYK
1332					dib = FreeImage_AllocateHeader(header_only, cinfo.output_width, cinfo.output_height, 32, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
1333					if(!dib) throw FI_MSG_ERROR_DIB_MEMORY;
1334					FreeImage_GetICCProfile(dib)->flags |= FIICC_COLOR_IS_CMYK;
1335				} else {
1336					// load as CMYK and convert to RGB
1337					dib = FreeImage_AllocateHeader(header_only, cinfo.output_width, cinfo.output_height, 24, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
1338					if(!dib) throw FI_MSG_ERROR_DIB_MEMORY;
1339				}
1340			} else {
1341				// RGB or greyscale image
1342				dib = FreeImage_AllocateHeader(header_only, cinfo.output_width, cinfo.output_height, 8 * cinfo.num_components, FI_RGBA_RED_MASK, FI_RGBA_GREEN_MASK, FI_RGBA_BLUE_MASK);
1343				if(!dib) throw FI_MSG_ERROR_DIB_MEMORY;
1344
1345				if (cinfo.num_components == 1) {
1346					// build a greyscale palette
1347					RGBQUAD *colors = FreeImage_GetPalette(dib);
1348
1349					for (int i = 0; i < 256; i++) {
1350						colors[i].rgbRed   = (BYTE)i;
1351						colors[i].rgbGreen = (BYTE)i;
1352						colors[i].rgbBlue  = (BYTE)i;
1353					}
1354				}
1355			}
1356			if(scale_denom != 1) {
1357				// store original size info if a scaling was requested
1358				store_size_info(dib, cinfo.image_width, cinfo.image_height);
1359			}
1360
1361			// step 5c: handle metrices
1362
1363			if (cinfo.density_unit == 1) {
1364				// dots/inch
1365				FreeImage_SetDotsPerMeterX(dib, (unsigned) (((float)cinfo.X_density) / 0.0254000 + 0.5));
1366				FreeImage_SetDotsPerMeterY(dib, (unsigned) (((float)cinfo.Y_density) / 0.0254000 + 0.5));
1367			} else if (cinfo.density_unit == 2) {
1368				// dots/cm
1369				FreeImage_SetDotsPerMeterX(dib, (unsigned) (cinfo.X_density * 100));
1370				FreeImage_SetDotsPerMeterY(dib, (unsigned) (cinfo.Y_density * 100));
1371			}
1372			
1373			// step 6: read special markers
1374			
1375			read_markers(&cinfo, dib);
1376
1377			// --- header only mode => clean-up and return
1378
1379			if (header_only) {
1380				// release JPEG decompression object
1381				jpeg_destroy_decompress(&cinfo);
1382				// return header data
1383				return dib;
1384			}
1385
1386			// step 7a: while (scan lines remain to be read) jpeg_read_scanlines(...);
1387
1388			if((cinfo.out_color_space == JCS_CMYK) && ((flags & JPEG_CMYK) != JPEG_CMYK)) {
1389				// convert from CMYK to RGB
1390
1391				JSAMPARRAY buffer;		// output row buffer
1392				unsigned row_stride;	// physical row width in output buffer
1393
1394				// JSAMPLEs per row in output buffer
1395				row_stride = cinfo.output_width * cinfo.output_components;
1396				// make a one-row-high sample array that will go away when done with image
1397				buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
1398
1399				while (cinfo.output_scanline < cinfo.output_height) {
1400					JSAMPROW src = buffer[0];
1401					JSAMPROW dst = FreeImage_GetScanLine(dib, cinfo.output_height - cinfo.output_scanline - 1);
1402
1403					jpeg_read_scanlines(&cinfo, buffer, 1);
1404
1405					for(unsigned x = 0; x < cinfo.output_width; x++) {
1406						WORD K = (WORD)src[3];
1407						dst[FI_RGBA_RED]   = (BYTE)((K * src[0]) / 255);	// C -> R
1408						dst[FI_RGBA_GREEN] = (BYTE)((K * src[1]) / 255);	// M -> G
1409						dst[FI_RGBA_BLUE]  = (BYTE)((K * src[2]) / 255);	// Y -> B
1410						src += 4;
1411						dst += 3;
1412					}
1413				}
1414			} else if((cinfo.out_color_space == JCS_CMYK) && ((flags & JPEG_CMYK) == JPEG_CMYK)) {
1415				// convert from LibJPEG CMYK to standard CMYK
1416
1417				JSAMPARRAY buffer;		// output row buffer
1418				unsigned row_stride;	// physical row width in output buffer
1419
1420				// JSAMPLEs per row in output buffer
1421				row_stride = cinfo.output_width * cinfo.output_components;
1422				// make a one-row-high sample array that will go away when done with image
1423				buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
1424
1425				while (cinfo.output_scanline < cinfo.output_height) {
1426					JSAMPROW src = buffer[0];
1427					JSAMPROW dst = FreeImage_GetScanLine(dib, cinfo.output_height - cinfo.output_scanline - 1);
1428
1429					jpeg_read_scanlines(&cinfo, buffer, 1);
1430
1431					for(unsigned x = 0; x < cinfo.output_width; x++) {
1432						// CMYK pixels are inverted
1433						dst[0] = ~src[0];	// C
1434						dst[1] = ~src[1];	// M
1435						dst[2] = ~src[2];	// Y
1436						dst[3] = ~src[3];	// K
1437						src += 4;
1438						dst += 4;
1439					}
1440				}
1441
1442			} else {
1443				// normal case (RGB or greyscale image)
1444
1445				while (cinfo.output_scanline < cinfo.output_height) {
1446					JSAMPROW dst = FreeImage_GetScanLine(dib, cinfo.output_height - cinfo.output_scanline - 1);
1447
1448					jpeg_read_scanlines(&cinfo, &dst, 1);
1449				}
1450
1451				// step 7b: swap red and blue components (see LibJPEG/jmorecfg.h: #define RGB_RED, ...)
1452				// The default behavior of the JPEG library is kept "as is" because LibTIFF uses 
1453				// LibJPEG "as is".
1454
1455#if FREEIMAGE_COLORORDER == FREEIMAGE_COLORORDER_BGR
1456				SwapRedBlue32(dib);
1457#endif
1458			}
1459
1460			// step 8: finish decompression
1461
1462			jpeg_finish_decompress(&cinfo);
1463
1464			// step 9: release JPEG decompression object
1465
1466			jpeg_destroy_decompress(&cinfo);
1467
1468			// check for automatic Exif rotation
1469			if(!header_only && ((flags & JPEG_EXIFROTATE) == JPEG_EXIFROTATE)) {
1470				rotate_exif(&dib);
1471			}
1472
1473			// everything went well. return the loaded dib
1474
1475			return dib;
1476
1477		} catch (const char *text) {
1478			jpeg_destroy_decompress(&cinfo);
1479			if(NULL != dib) {
1480				FreeImage_Unload(dib);
1481			}
1482			if(NULL != text) {
1483				FreeImage_OutputMessageProc(s_format_id, text);
1484			}
1485		}
1486	}
1487
1488	return NULL;
1489}
1490
1491// ----------------------------------------------------------
1492
1493static BOOL DLL_CALLCONV
1494Save(FreeImageIO *io, FIBITMAP *dib, fi_handle handle, int page, int flags, void *data) {
1495	if ((dib) && (handle)) {
1496		try {
1497			// Check dib format
1498
1499			const char *sError = "only 24-bit highcolor or 8-bit greyscale/palette bitmaps can be saved as JPEG";
1500
1501			FREE_IMAGE_COLOR_TYPE color_type = FreeImage_GetColorType(dib);
1502			WORD bpp = (WORD)FreeImage_GetBPP(dib);
1503
1504			if ((bpp != 24) && (bpp != 8)) {
1505				throw sError;
1506			}
1507
1508			if(bpp == 8) {
1509				// allow grey, reverse grey and palette 
1510				if ((color_type != FIC_MINISBLACK) && (color_type != FIC_MINISWHITE) && (color_type != FIC_PALETTE)) {
1511					throw sError;
1512				}
1513			}
1514
1515
1516			struct jpeg_compress_struct cinfo;
1517			ErrorManager fi_error_mgr;
1518
1519			// Step 1: allocate and initialize JPEG compression object
1520
1521			// we set up the normal JPEG error routines, then override error_exit & output_message
1522			cinfo.err = jpeg_std_error(&fi_error_mgr.pub);
1523			fi_error_mgr.pub.error_exit     = jpeg_error_exit;
1524			fi_error_mgr.pub.output_message = jpeg_output_message;
1525			
1526			// establish the setjmp return context for jpeg_error_exit to use
1527			if (setjmp(fi_error_mgr.setjmp_buffer)) {
1528				// If we get here, the JPEG code has signaled an error.
1529				// We need to clean up the JPEG object, close the input file, and return.
1530				jpeg_destroy_compress(&cinfo);
1531				throw (const char*)NULL;
1532			}
1533
1534			// Now we can initialize the JPEG compression object
1535
1536			jpeg_create_compress(&cinfo);
1537
1538			// Step 2: specify data destination (eg, a file)
1539
1540			jpeg_freeimage_dst(&cinfo, handle, io);
1541
1542			// Step 3: set parameters for compression 
1543
1544			cinfo.image_width = FreeImage_GetWidth(dib);
1545			cinfo.image_height = FreeImage_GetHeight(dib);
1546
1547			switch(color_type) {
1548				case FIC_MINISBLACK :
1549				case FIC_MINISWHITE :
1550					cinfo.in_color_space = JCS_GRAYSCALE;
1551					cinfo.input_components = 1;
1552					break;
1553
1554				default :
1555					cinfo.in_color_space = JCS_RGB;
1556					cinfo.input_components = 3;
1557					break;
1558			}
1559
1560			jpeg_set_defaults(&cinfo);
1561
1562		    // progressive-JPEG support
1563			if((flags & JPEG_PROGRESSIVE) == JPEG_PROGRESSIVE) {
1564				jpeg_simple_progression(&cinfo);
1565			}
1566			
1567			// compute optimal Huffman coding tables for the image
1568			if((flags & JPEG_OPTIMIZE) == JPEG_OPTIMIZE) {
1569				cinfo.optimize_coding = TRUE;
1570			}
1571
1572			// Set JFIF density parameters from the DIB data
1573
1574			cinfo.X_density = (UINT16) (0.5 + 0.0254 * FreeImage_GetDotsPerMeterX(dib));
1575			cinfo.Y_density = (UINT16) (0.5 + 0.0254 * FreeImage_GetDotsPerMeterY(dib));
1576			cinfo.density_unit = 1;	// dots / inch
1577
1578			// thumbnail support (JFIF 1.02 extension markers)
1579			if(FreeImage_GetThumbnail(dib) != NULL) {
1580				cinfo.write_JFIF_header = 1; //<### force it, though when color is CMYK it will be incorrect
1581				cinfo.JFIF_minor_version = 2;
1582			}
1583
1584			// baseline JPEG support
1585			if ((flags & JPEG_BASELINE) ==  JPEG_BASELINE) {
1586				cinfo.write_JFIF_header = 0;	// No marker for non-JFIF colorspaces
1587				cinfo.write_Adobe_marker = 0;	// write no Adobe marker by default				
1588			}
1589
1590			// set subsampling options if required
1591
1592			if(cinfo.in_color_space == JCS_RGB) {
1593				if((flags & JPEG_SUBSAMPLING_411) == JPEG_SUBSAMPLING_411) { 
1594					// 4:1:1 (4x1 1x1 1x1) - CrH 25% - CbH 25% - CrV 100% - CbV 100%
1595					// the horizontal color resolution is quartered
1596					cinfo.comp_info[0].h_samp_factor = 4;	// Y 
1597					cinfo.comp_info[0].v_samp_factor = 1; 
1598					cinfo.comp_info[1].h_samp_factor = 1;	// Cb 
1599					cinfo.comp_info[1].v_samp_factor = 1; 
1600					cinfo.comp_info[2].h_samp_factor = 1;	// Cr 
1601					cinfo.comp_info[2].v_samp_factor = 1; 
1602				} else if((flags & JPEG_SUBSAMPLING_420) == JPEG_SUBSAMPLING_420) {
1603					// 4:2:0 (2x2 1x1 1x1) - CrH 50% - CbH 50% - CrV 50% - CbV 50%
1604					// the chrominance resolution in both the horizontal and vertical directions is cut in half
1605					cinfo.comp_info[0].h_samp_factor = 2;	// Y
1606					cinfo.comp_info[0].v_samp_factor = 2; 
1607					cinfo.comp_info[1].h_samp_factor = 1;	// Cb
1608					cinfo.comp_info[1].v_samp_factor = 1; 
1609					cinfo.comp_info[2].h_samp_factor = 1;	// Cr
1610					cinfo.comp_info[2].v_samp_factor = 1; 
1611				} else if((flags & JPEG_SUBSAMPLING_422) == JPEG_SUBSAMPLING_422){ //2x1 (low) 
1612					// 4:2:2 (2x1 1x1 1x1) - CrH 50% - CbH 50% - CrV 100% - CbV 100%
1613					// half of the horizontal resolution in the chrominance is dropped (Cb & Cr), 
1614					// while the full resolution is retained in the vertical direction, with respect to the luminance
1615					cinfo.comp_info[0].h_samp_factor = 2;	// Y 
1616					cinfo.comp_info[0].v_samp_factor = 1; 
1617					cinfo.comp_info[1].h_samp_factor = 1;	// Cb 
1618					cinfo.comp_info[1].v_samp_factor = 1; 
1619					cinfo.comp_info[2].h_samp_factor = 1;	// Cr 
1620					cinfo.comp_info[2].v_samp_factor = 1; 
1621				} 
1622				else if((flags & JPEG_SUBSAMPLING_444) == JPEG_SUBSAMPLING_444){ //1x1 (no subsampling) 
1623					// 4:4:4 (1x1 1x1 1x1) - CrH 100% - CbH 100% - CrV 100% - CbV 100%
1624					// the resolution of chrominance information (Cb & Cr) is preserved 
1625					// at the same rat…

Large files files are truncated, but you can click here to view the full file