PageRenderTime 116ms CodeModel.GetById 22ms app.highlight 86ms RepoModel.GetById 1ms app.codeStats 1ms

/src/FreeImage/Source/Metadata/XTIFF.cpp

https://bitbucket.org/cabalistic/ogredeps/
C++ | 661 lines | 438 code | 111 blank | 112 comment | 106 complexity | 465348e31b471aa45273d03c75e70773 MD5 | raw file
  1// ==========================================================
  2// Metadata functions implementation
  3// Extended TIFF Directory GEO Tag Support
  4//
  5// Design and implementation by
  6// - Hervé Drolon (drolon@infonie.fr)
  7// - Thorsten Radde (support@IdealSoftware.com)
  8// - Berend Engelbrecht (softwarecave@users.sourceforge.net)
  9// - Mihail Naydenov (mnaydenov@users.sourceforge.net)
 10//
 11// Based on the LibTIFF xtiffio sample and on LibGeoTIFF
 12//
 13// This file is part of FreeImage 3
 14//
 15// COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY
 16// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
 17// THAT THE COVERED CODE IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE
 18// OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED
 19// CODE IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT
 20// THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY
 21// SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL
 22// PART OF THIS LICENSE. NO USE OF ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER
 23// THIS DISCLAIMER.
 24//
 25// Use at your own risk!
 26// ========================================================== 
 27
 28#ifdef _MSC_VER
 29#pragma warning (disable : 4786) // identifier was truncated to 'number' characters
 30#endif
 31
 32#include "../LibTIFF4/tiffiop.h"
 33
 34#include "FreeImage.h"
 35#include "Utilities.h"
 36#include "FreeImageTag.h"
 37#include "FIRational.h"
 38
 39// ----------------------------------------------------------
 40//   Extended TIFF Directory GEO Tag Support
 41// ----------------------------------------------------------
 42
 43/**
 44  Tiff info structure.
 45  Entry format:
 46  { TAGNUMBER, ReadCount, WriteCount, DataType, FIELDNUM, OkToChange, PassDirCountOnSet, AsciiName }
 47
 48  For ReadCount, WriteCount, -1 = unknown.
 49*/
 50static const TIFFFieldInfo xtiffFieldInfo[] = {
 51	{ TIFFTAG_GEOPIXELSCALE, -1, -1, TIFF_DOUBLE, FIELD_CUSTOM, TRUE, TRUE, "GeoPixelScale" },
 52	{ TIFFTAG_INTERGRAPH_MATRIX, -1, -1, TIFF_DOUBLE, FIELD_CUSTOM, TRUE, TRUE, "Intergraph TransformationMatrix" },
 53	{ TIFFTAG_GEOTRANSMATRIX, -1, -1, TIFF_DOUBLE, FIELD_CUSTOM, TRUE, TRUE, "GeoTransformationMatrix" },
 54	{ TIFFTAG_GEOTIEPOINTS,	-1, -1, TIFF_DOUBLE, FIELD_CUSTOM, TRUE, TRUE, "GeoTiePoints" },
 55	{ TIFFTAG_GEOKEYDIRECTORY,-1,-1, TIFF_SHORT, FIELD_CUSTOM, TRUE, TRUE, "GeoKeyDirectory" },
 56	{ TIFFTAG_GEODOUBLEPARAMS, -1, -1, TIFF_DOUBLE,	FIELD_CUSTOM, TRUE,	TRUE, "GeoDoubleParams" },
 57	{ TIFFTAG_GEOASCIIPARAMS, -1, -1, TIFF_ASCII, FIELD_CUSTOM, TRUE, FALSE, "GeoASCIIParams" },
 58	{ TIFFTAG_JPL_CARTO_IFD, 1, 1, TIFF_LONG, FIELD_CUSTOM, TRUE, TRUE,	"JPL Carto IFD offset" }  /** Don't use this! **/
 59};
 60
 61static void
 62_XTIFFLocalDefaultDirectory(TIFF *tif) {
 63	int tag_size = sizeof(xtiffFieldInfo) / sizeof(xtiffFieldInfo[0]);
 64	// Install the extended Tag field info
 65	TIFFMergeFieldInfo(tif, xtiffFieldInfo, tag_size);
 66}
 67
 68static TIFFExtendProc _ParentExtender;
 69
 70/**
 71This is the callback procedure, and is
 72called by the DefaultDirectory method
 73every time a new TIFF directory is opened.
 74*/
 75static void
 76_XTIFFDefaultDirectory(TIFF *tif) {
 77	// set up our own defaults
 78	_XTIFFLocalDefaultDirectory(tif);
 79
 80	/*
 81	Since an XTIFF client module may have overridden
 82	the default directory method, we call it now to
 83	allow it to set up the rest of its own methods.
 84	*/
 85	if (_ParentExtender)
 86		(*_ParentExtender)(tif);
 87}
 88
 89/**
 90XTIFF Initializer -- sets up the callback procedure for the TIFF module
 91*/
 92void
 93XTIFFInitialize(void) {
 94	static int first_time = 1;
 95
 96	if (! first_time)
 97		return; /* Been there. Done that. */
 98	first_time = 0;
 99
100	// Grab the inherited method and install
101	_ParentExtender = TIFFSetTagExtender(_XTIFFDefaultDirectory);
102}
103
104// ----------------------------------------------------------
105//   GeoTIFF tag reading / writing
106// ----------------------------------------------------------
107
108void
109tiff_read_geotiff_profile(TIFF *tif, FIBITMAP *dib) {
110	char defaultKey[16];
111
112	size_t tag_size = sizeof(xtiffFieldInfo) / sizeof(xtiffFieldInfo[0]);
113
114	TagLib& tag_lib = TagLib::instance();
115
116	for(unsigned i = 0; i < tag_size; i++) {
117
118		const TIFFFieldInfo *fieldInfo = &xtiffFieldInfo[i];
119
120		if(fieldInfo->field_type == TIFF_ASCII) {
121			char *params = NULL;
122
123			if(TIFFGetField(tif, fieldInfo->field_tag, &params)) {
124				// create a tag
125				FITAG *tag = FreeImage_CreateTag();
126				if(!tag)
127					return;
128
129				WORD tag_id = (WORD)fieldInfo->field_tag;
130
131				FreeImage_SetTagType(tag, (FREE_IMAGE_MDTYPE)fieldInfo->field_type);
132				FreeImage_SetTagID(tag, tag_id);
133				FreeImage_SetTagKey(tag, tag_lib.getTagFieldName(TagLib::GEOTIFF, tag_id, defaultKey));
134				FreeImage_SetTagDescription(tag, tag_lib.getTagDescription(TagLib::GEOTIFF, tag_id));
135				FreeImage_SetTagLength(tag, (DWORD)strlen(params) + 1);
136				FreeImage_SetTagCount(tag, FreeImage_GetTagLength(tag));
137				FreeImage_SetTagValue(tag, params);
138				FreeImage_SetMetadata(FIMD_GEOTIFF, dib, FreeImage_GetTagKey(tag), tag);
139
140				// delete the tag
141				FreeImage_DeleteTag(tag);
142			}
143		} else {
144			short tag_count = 0;
145			void* data = NULL;
146
147			if(TIFFGetField(tif, fieldInfo->field_tag, &tag_count, &data)) {
148				// create a tag
149				FITAG *tag = FreeImage_CreateTag();
150				if(!tag)
151					return;
152
153				WORD tag_id = (WORD)fieldInfo->field_tag;
154				FREE_IMAGE_MDTYPE tag_type = (FREE_IMAGE_MDTYPE)fieldInfo->field_type;
155
156				FreeImage_SetTagType(tag, tag_type);
157				FreeImage_SetTagID(tag, tag_id);
158				FreeImage_SetTagKey(tag, tag_lib.getTagFieldName(TagLib::GEOTIFF, tag_id, defaultKey));
159				FreeImage_SetTagDescription(tag, tag_lib.getTagDescription(TagLib::GEOTIFF, tag_id));
160				FreeImage_SetTagLength(tag, FreeImage_TagDataWidth(tag_type) * tag_count);
161				FreeImage_SetTagCount(tag, tag_count);
162				FreeImage_SetTagValue(tag, data);
163				FreeImage_SetMetadata(FIMD_GEOTIFF, dib, FreeImage_GetTagKey(tag), tag);
164
165				// delete the tag
166				FreeImage_DeleteTag(tag);
167			}
168		}
169	} // for(tag_size)
170}
171
172void
173tiff_write_geotiff_profile(TIFF *tif, FIBITMAP *dib) {
174	char defaultKey[16];
175
176	if(FreeImage_GetMetadataCount(FIMD_GEOTIFF, dib) == 0) {
177		return;
178	}
179
180	size_t tag_size = sizeof(xtiffFieldInfo) / sizeof(xtiffFieldInfo[0]);
181
182	TagLib& tag_lib = TagLib::instance();
183
184	for(unsigned i = 0; i < tag_size; i++) {
185		const TIFFFieldInfo *fieldInfo = &xtiffFieldInfo[i];
186
187		FITAG *tag = NULL;
188		const char *key = tag_lib.getTagFieldName(TagLib::GEOTIFF, (WORD)fieldInfo->field_tag, defaultKey);
189
190		if(FreeImage_GetMetadata(FIMD_GEOTIFF, dib, key, &tag)) {
191			if(FreeImage_GetTagType(tag) == FIDT_ASCII) {
192				TIFFSetField(tif, fieldInfo->field_tag, FreeImage_GetTagValue(tag));
193			} else {
194				TIFFSetField(tif, fieldInfo->field_tag, FreeImage_GetTagCount(tag), FreeImage_GetTagValue(tag));
195			}
196		}
197	}
198}
199
200// ----------------------------------------------------------
201//   EXIF tag reading & writing
202// ----------------------------------------------------------
203
204/**
205Read a single exif tag
206*/
207static BOOL 
208tiff_read_exif_tag(TIFF *tif, TagLib::MDMODEL md_model, FIBITMAP *dib, TagLib& tagLib, TIFFDirectory *td, uint32 tag) {
209	const TIFFField *fip;
210	uint32 value_count;
211	int mem_alloc = 0;
212	void *raw_data = NULL;
213
214	if(tag == TIFFTAG_EXIFIFD) {
215		return TRUE;
216	}
217
218	// get the tag key - use NULL to avoid reading GeoTIFF tags
219	const char *key = tagLib.getTagFieldName(md_model, (WORD)tag, NULL);
220	if(key == NULL) {
221		return TRUE;
222	}
223
224	fip = TIFFFieldWithTag(tif, tag);
225	if(fip == NULL) {
226		return TRUE;
227	}
228
229	if(fip->field_passcount) { //<- "passcount" means "returns count"
230		if (fip->field_readcount != TIFF_VARIABLE2) { //<- TIFF_VARIABLE2 means "uses LONG count"
231
232			// assume TIFF_VARIABLE (uses SHORT count)
233			uint16 value_count16;
234			if(TIFFGetField(tif, tag, &value_count16, &raw_data) != 1) {
235				return TRUE;
236			}
237			value_count = value_count16;
238		} else {
239			if(TIFFGetField(tif, tag, &value_count, &raw_data) != 1) {
240				return TRUE;
241			}
242		}
243	} else {
244
245		// determine count
246
247		if (fip->field_readcount == TIFF_VARIABLE || fip->field_readcount == TIFF_VARIABLE2) {
248			value_count = 1;
249		} else if (fip->field_readcount == TIFF_SPP) {
250			value_count = td->td_samplesperpixel;
251		} else {
252			value_count = fip->field_readcount;
253		}
254
255		// access fields as pointers to data
256		// (### determining this is NOT robust... and hardly can be. It is implemented looking the _TIFFVGetField code)
257
258		if(fip->field_tag == TIFFTAG_TRANSFERFUNCTION) {
259			// reading this tag cause a bug probably located somewhere inside libtiff
260			return TRUE;
261		}
262
263		if ((fip->field_type == TIFF_ASCII
264		     || fip->field_readcount == TIFF_VARIABLE
265		     || fip->field_readcount == TIFF_VARIABLE2
266		     || fip->field_readcount == TIFF_SPP
267			 || value_count > 1)
268			 
269			 && fip->field_tag != TIFFTAG_PAGENUMBER
270			 && fip->field_tag != TIFFTAG_HALFTONEHINTS
271			 && fip->field_tag != TIFFTAG_YCBCRSUBSAMPLING
272			 && fip->field_tag != TIFFTAG_DOTRANGE
273
274			 && fip->field_tag != TIFFTAG_BITSPERSAMPLE	//<- these two are tricky - 
275			 && fip->field_tag != TIFFTAG_COMPRESSION	//<- they are defined as TIFF_VARIABLE but in reality return a single value
276			 ) {
277				 if(TIFFGetField(tif, tag, &raw_data) != 1) {
278					 return TRUE;
279				 }
280		} else {
281
282			// access fields as values
283
284			const int value_size = _TIFFDataSize(fip->field_type);
285			raw_data = _TIFFmalloc(value_size * value_count);
286			mem_alloc = 1;
287			int ok = FALSE;
288			
289			// ### if value_count > 1, tag is PAGENUMBER or HALFTONEHINTS or YCBCRSUBSAMPLING or DOTRANGE, 
290			// all off which are value_count == 2 (see tif_dirinfo.c)
291			switch(value_count)
292			{
293				case 1:
294					ok = TIFFGetField(tif, tag, raw_data);
295					break;
296				case 2:
297					ok = TIFFGetField(tif, tag, raw_data, (BYTE*)(raw_data) + value_size*1);
298					break;
299/* # we might need more in the future:
300				case 3:
301					ok = TIFFGetField(tif, tag, raw_data, (BYTE*)(raw_data) + value_size*1, (BYTE*)(raw_data) + value_size*2);
302					break;
303*/
304				default:
305					FreeImage_OutputMessageProc(FIF_TIFF, "Unimplemented variable number of parameters for Tiff Tag %s", fip->field_name);
306					break;
307			}
308			if(ok != 1) {
309				_TIFFfree(raw_data);
310				return TRUE;
311			}
312		}
313	}
314
315	// build FreeImage tag from Tiff Tag data we collected
316
317	FITAG *fitag = FreeImage_CreateTag();
318	if(!fitag) {
319		if(mem_alloc) {
320			_TIFFfree(raw_data);
321		}
322		return FALSE;
323	}
324
325	FreeImage_SetTagID(fitag, (WORD)tag);
326	FreeImage_SetTagKey(fitag, key);
327
328	switch(fip->field_type) {
329		case TIFF_BYTE:
330			FreeImage_SetTagType(fitag, FIDT_BYTE);
331			FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
332			FreeImage_SetTagCount(fitag, value_count);
333			FreeImage_SetTagValue(fitag, raw_data);
334			break;
335
336		case TIFF_UNDEFINED:
337			FreeImage_SetTagType(fitag, FIDT_UNDEFINED);
338			FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
339			FreeImage_SetTagCount(fitag, value_count);
340			FreeImage_SetTagValue(fitag, raw_data);
341			break;
342
343		case TIFF_SBYTE:
344			FreeImage_SetTagType(fitag, FIDT_SBYTE);
345			FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
346			FreeImage_SetTagCount(fitag, value_count);
347			FreeImage_SetTagValue(fitag, raw_data);
348			break;
349
350		case TIFF_SHORT:
351			FreeImage_SetTagType(fitag, FIDT_SHORT);
352			FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
353			FreeImage_SetTagCount(fitag, value_count);
354			FreeImage_SetTagValue(fitag, raw_data);
355			break;
356
357		case TIFF_SSHORT:
358			FreeImage_SetTagType(fitag, FIDT_SSHORT);
359			FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
360			FreeImage_SetTagCount(fitag, value_count);
361			FreeImage_SetTagValue(fitag, raw_data);
362			break;
363
364		case TIFF_LONG:
365			FreeImage_SetTagType(fitag, FIDT_LONG);
366			FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
367			FreeImage_SetTagCount(fitag, value_count);
368			FreeImage_SetTagValue(fitag, raw_data);
369			break;
370
371		case TIFF_IFD:
372			FreeImage_SetTagType(fitag, FIDT_IFD);
373			FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
374			FreeImage_SetTagCount(fitag, value_count);
375			FreeImage_SetTagValue(fitag, raw_data);
376			break;
377
378		case TIFF_SLONG:
379			FreeImage_SetTagType(fitag, FIDT_SLONG);
380			FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
381			FreeImage_SetTagCount(fitag, value_count);
382			FreeImage_SetTagValue(fitag, raw_data);
383			break;
384
385		case TIFF_RATIONAL: {
386			// LibTIFF converts rational to floats : reconvert floats to rationals
387			DWORD *rvalue = (DWORD*)malloc(2 * value_count * sizeof(DWORD));
388			for(uint32 i = 0; i < value_count; i++) {
389				float *fv = (float*)raw_data;
390				FIRational rational(fv[i]);
391				rvalue[2*i] = rational.getNumerator();
392				rvalue[2*i+1] = rational.getDenominator();
393			}
394			FreeImage_SetTagType(fitag, FIDT_RATIONAL);
395			FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
396			FreeImage_SetTagCount(fitag, value_count);
397			FreeImage_SetTagValue(fitag, rvalue);
398			free(rvalue);
399		}
400		break;
401
402		case TIFF_SRATIONAL: {
403			// LibTIFF converts rational to floats : reconvert floats to rationals
404			LONG *rvalue = (LONG*)malloc(2 * value_count * sizeof(LONG));
405			for(uint32 i = 0; i < value_count; i++) {
406				float *fv = (float*)raw_data;
407				FIRational rational(fv[i]);
408				rvalue[2*i] = rational.getNumerator();
409				rvalue[2*i+1] = rational.getDenominator();
410			}
411			FreeImage_SetTagType(fitag, FIDT_RATIONAL);
412			FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
413			FreeImage_SetTagCount(fitag, value_count);
414			FreeImage_SetTagValue(fitag, rvalue);
415			free(rvalue);
416		}
417		break;
418
419		case TIFF_FLOAT:
420			FreeImage_SetTagType(fitag, FIDT_FLOAT);
421			FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
422			FreeImage_SetTagCount(fitag, value_count);
423			FreeImage_SetTagValue(fitag, raw_data);
424			break;
425
426		case TIFF_DOUBLE:
427			FreeImage_SetTagType(fitag, FIDT_DOUBLE);
428			FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
429			FreeImage_SetTagCount(fitag, value_count);
430			FreeImage_SetTagValue(fitag, raw_data);
431			break;
432
433		case TIFF_LONG8:	// BigTIFF 64-bit unsigned integer 
434			FreeImage_SetTagType(fitag, FIDT_LONG8);
435			FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
436			FreeImage_SetTagCount(fitag, value_count);
437			FreeImage_SetTagValue(fitag, raw_data);
438			break;
439
440		case TIFF_IFD8:		// BigTIFF 64-bit unsigned integer (offset) 
441			FreeImage_SetTagType(fitag, FIDT_IFD8);
442			FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
443			FreeImage_SetTagCount(fitag, value_count);
444			FreeImage_SetTagValue(fitag, raw_data);
445			break;
446
447		case TIFF_SLONG8:		// BigTIFF 64-bit signed integer 
448			FreeImage_SetTagType(fitag, FIDT_SLONG8);
449			FreeImage_SetTagLength(fitag, TIFFDataWidth(fip->field_type) * value_count);
450			FreeImage_SetTagCount(fitag, value_count);
451			FreeImage_SetTagValue(fitag, raw_data);
452			break;
453
454		default: {
455			size_t length = strlen((char*)raw_data) + 1;
456			FreeImage_SetTagType(fitag, FIDT_ASCII);
457			FreeImage_SetTagLength(fitag, (DWORD)length);
458			FreeImage_SetTagCount(fitag, (DWORD)length);
459			FreeImage_SetTagValue(fitag, raw_data);
460		}
461		break;
462	}
463
464	const char *description = tagLib.getTagDescription(md_model, (WORD)tag);
465	if(description) {
466		FreeImage_SetTagDescription(fitag, description);
467	}
468	// store the tag
469	FreeImage_SetMetadata(tagLib.getFreeImageModel(md_model), dib, FreeImage_GetTagKey(fitag), fitag);
470
471	// destroy the tag
472	FreeImage_DeleteTag(fitag);
473
474	if(mem_alloc) {
475		_TIFFfree(raw_data);
476	}
477	return TRUE;
478}
479
480/**
481Read all known exif tags
482*/
483BOOL 
484tiff_read_exif_tags(TIFF *tif, TagLib::MDMODEL md_model, FIBITMAP *dib) {
485	int  i;
486	short count;
487
488	TagLib& tagLib = TagLib::instance();
489
490	TIFFDirectory *td = &tif->tif_dir;
491
492	count = (short) TIFFGetTagListCount(tif);
493	for(i = 0; i < count; i++) {
494		uint32 tag = TIFFGetTagListEntry(tif, i);
495		// read the tag
496		if (!tiff_read_exif_tag(tif, md_model, dib, tagLib, td, tag))
497			return FALSE;
498	}
499
500	// we want to know values of standard tags too!!
501
502	// loop over all Core Directory Tags
503	// ### uses private data, but there is no other way
504	if(md_model == TagLib::EXIF_MAIN) {
505
506		uint32 lastTag = 0;	//<- used to prevent reading some tags twice (as stored in tif_fieldinfo)
507
508		for (int fi = 0, nfi = (int)tif->tif_nfields; nfi > 0; nfi--, fi++) {
509			const TIFFField *fld = tif->tif_fields[fi];
510
511			if(fld->field_tag == lastTag)
512				continue;
513
514			// test if tag value is set
515			// (lifted directly form LibTiff _TIFFWriteDirectory)
516
517			if( fld->field_bit == FIELD_CUSTOM ) {
518				int ci, is_set = FALSE;
519
520				for( ci = 0; ci < td->td_customValueCount; ci++ ) {
521					is_set |= (td->td_customValues[ci].info == fld);
522				}
523
524				if( !is_set ) {
525					continue;
526				}
527
528			} else if(!TIFFFieldSet(tif, fld->field_bit)) {
529				continue;
530			}
531
532			// process *all* other tags (some will be ignored)
533
534			tiff_read_exif_tag(tif, md_model, dib, tagLib, td, fld->field_tag);
535
536
537			lastTag = fld->field_tag;
538		}
539
540	}
541
542	return TRUE;
543
544}
545
546
547/**
548Skip tags that are already handled by the LibTIFF writing process
549*/
550static BOOL 
551skip_write_field(TIFF* tif, uint32 tag) {
552	switch (tag) {
553		case TIFFTAG_SAMPLEFORMAT:
554		case TIFFTAG_IMAGEWIDTH:
555		case TIFFTAG_IMAGELENGTH:
556		case TIFFTAG_SAMPLESPERPIXEL:
557		case TIFFTAG_BITSPERSAMPLE:
558		case TIFFTAG_PHOTOMETRIC:
559		case TIFFTAG_PLANARCONFIG:
560		case TIFFTAG_ROWSPERSTRIP:
561		case TIFFTAG_RESOLUTIONUNIT:
562		case TIFFTAG_XRESOLUTION:
563		case TIFFTAG_YRESOLUTION:
564		case TIFFTAG_SUBFILETYPE:
565		case TIFFTAG_PAGENUMBER:
566		case TIFFTAG_COLORMAP:
567		case TIFFTAG_ORIENTATION:
568		case TIFFTAG_COMPRESSION:
569		case TIFFTAG_PREDICTOR:
570		case TIFFTAG_GROUP3OPTIONS:
571		case TIFFTAG_FILLORDER:
572			// skip always, values have been set in SaveOneTIFF()
573			return TRUE;
574			break;
575		
576		case TIFFTAG_RICHTIFFIPTC:
577			// skip always, IPTC metadata model is set in tiff_write_iptc_profile()
578			return TRUE;
579			break;
580
581		case TIFFTAG_YCBCRCOEFFICIENTS:
582		case TIFFTAG_REFERENCEBLACKWHITE:
583		case TIFFTAG_YCBCRSUBSAMPLING:
584			// skip as they cannot be filled yet
585			return TRUE;
586			break;
587			
588		case TIFFTAG_PAGENAME:
589		{
590			char *value = NULL;
591			TIFFGetField(tif, TIFFTAG_PAGENAME, &value);
592			// only skip if no value has been set
593			if(value == NULL) {
594				return FALSE;
595			} else {
596				return TRUE;
597			}
598		}
599		default:
600			return FALSE;
601			break;
602	}
603}
604
605/**
606Write all known exif tags
607*/
608BOOL 
609tiff_write_exif_tags(TIFF *tif, TagLib::MDMODEL md_model, FIBITMAP *dib) {
610	char defaultKey[16];
611	
612	// only EXIF_MAIN so far
613	if(md_model != TagLib::EXIF_MAIN) {
614		return FALSE;
615	}
616	
617	if(FreeImage_GetMetadataCount(FIMD_EXIF_MAIN, dib) == 0) {
618		return FALSE;
619	}
620	
621	TagLib& tag_lib = TagLib::instance();
622	
623	for (int fi = 0, nfi = (int)tif->tif_nfields; nfi > 0; nfi--, fi++) {
624		const TIFFField *fld = tif->tif_fields[fi];
625
626		if(skip_write_field(tif, fld->field_tag)) {
627			// skip tags that are already handled by the LibTIFF writing process
628			continue;
629		}
630
631		FITAG *tag = NULL;
632		// get the tag key
633		const char *key = tag_lib.getTagFieldName(TagLib::EXIF_MAIN, (WORD)fld->field_tag, defaultKey);
634
635		if(FreeImage_GetMetadata(FIMD_EXIF_MAIN, dib, key, &tag)) {
636			FREE_IMAGE_MDTYPE tag_type = FreeImage_GetTagType(tag);
637			TIFFDataType tif_tag_type = fld->field_type;
638			
639			// check for identical formats
640
641			// (enum value are the sames between FREE_IMAGE_MDTYPE and TIFFDataType types)
642			if((int)tif_tag_type != (int)tag_type) {
643				// skip tag or _TIFFmemcpy will fail
644				continue;
645			}
646			// type of storage may differ (e.g. rationnal array vs float array type)
647			if(_TIFFDataSize(tif_tag_type) != FreeImage_TagDataWidth(tag_type)) {
648				// skip tag or _TIFFmemcpy will fail
649				continue;
650			}
651
652			if(tag_type == FIDT_ASCII) {
653				TIFFSetField(tif, fld->field_tag, FreeImage_GetTagValue(tag));
654			} else {
655				TIFFSetField(tif, fld->field_tag, FreeImage_GetTagCount(tag), FreeImage_GetTagValue(tag));
656			}
657		}
658	}
659
660	return TRUE;
661}