Coverage Report

Created: 2023-12-08 06:53

/src/freeimage-svn/FreeImage/trunk/Source/Metadata/XTIFF.cpp
Line
Count
Source (jump to first uncovered line)
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
*/
50
static const TIFFFieldInfo xtiffFieldInfo[] = {
51
  { TIFFTAG_GEOPIXELSCALE, -1, -1, TIFF_DOUBLE, FIELD_CUSTOM, TRUE, TRUE, (char*)"GeoPixelScale" },
52
  { TIFFTAG_INTERGRAPH_MATRIX, -1, -1, TIFF_DOUBLE, FIELD_CUSTOM, TRUE, TRUE, (char*)"Intergraph TransformationMatrix" },
53
  { TIFFTAG_GEOTRANSMATRIX, -1, -1, TIFF_DOUBLE, FIELD_CUSTOM, TRUE, TRUE, (char*)"GeoTransformationMatrix" },
54
  { TIFFTAG_GEOTIEPOINTS, -1, -1, TIFF_DOUBLE, FIELD_CUSTOM, TRUE, TRUE, (char*)"GeoTiePoints" },
55
  { TIFFTAG_GEOKEYDIRECTORY,-1,-1, TIFF_SHORT, FIELD_CUSTOM, TRUE, TRUE, (char*)"GeoKeyDirectory" },
56
  { TIFFTAG_GEODOUBLEPARAMS, -1, -1, TIFF_DOUBLE, FIELD_CUSTOM, TRUE, TRUE, (char*)"GeoDoubleParams" },
57
  { TIFFTAG_GEOASCIIPARAMS, -1, -1, TIFF_ASCII, FIELD_CUSTOM, TRUE, FALSE, (char*) "GeoASCIIParams" },
58
  { TIFFTAG_JPL_CARTO_IFD, 1, 1, TIFF_LONG, FIELD_CUSTOM, TRUE, TRUE, (char*)"JPL Carto IFD offset" }  /** Don't use this! **/
59
};
60
61
static void
62
0
_XTIFFLocalDefaultDirectory(TIFF *tif) {
63
0
  int tag_size = sizeof(xtiffFieldInfo) / sizeof(xtiffFieldInfo[0]);
64
  // Install the extended Tag field info
65
0
  TIFFMergeFieldInfo(tif, xtiffFieldInfo, tag_size);
66
0
}
67
68
static TIFFExtendProc _ParentExtender;
69
70
/**
71
This is the callback procedure, and is
72
called by the DefaultDirectory method
73
every time a new TIFF directory is opened.
74
*/
75
static void
76
0
_XTIFFDefaultDirectory(TIFF *tif) {
77
  // set up our own defaults
78
0
  _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
0
  if (_ParentExtender) {
86
0
    (*_ParentExtender)(tif);
87
0
  }
88
0
}
89
90
/**
91
XTIFF Initializer -- sets up the callback procedure for the TIFF module.
92
@see PluginTIFF::InitTIFF
93
*/
94
void
95
2
XTIFFInitialize(void) {
96
2
  static int first_time = 1;
97
98
2
  if (! first_time) {
99
0
    return; /* Been there. Done that. */
100
0
  }
101
2
  first_time = 0;
102
103
  // Grab the inherited method and install
104
2
  _ParentExtender = TIFFSetTagExtender(_XTIFFDefaultDirectory);
105
2
}
106
107
// ----------------------------------------------------------
108
//   GeoTIFF tag reading / writing
109
// ----------------------------------------------------------
110
111
BOOL
112
0
tiff_read_geotiff_profile(TIFF *tif, FIBITMAP *dib) {
113
0
  char defaultKey[16];
114
115
  // first check for a mandatory tag
116
0
  {
117
0
    short tag_count = 0;
118
0
    void* data = NULL;
119
    
120
0
    if(!TIFFGetField(tif, TIFFTAG_GEOKEYDIRECTORY, &tag_count, &data)) {
121
      // no GeoTIFF tag here
122
0
      return TRUE;
123
0
    }
124
0
  }
125
126
  // next, read GeoTIFF tags
127
128
0
  const size_t tag_size = sizeof(xtiffFieldInfo) / sizeof(xtiffFieldInfo[0]);
129
130
0
  TagLib& tag_lib = TagLib::instance();
131
132
0
  for(size_t i = 0; i < tag_size; i++) {
133
134
0
    const TIFFFieldInfo *fieldInfo = &xtiffFieldInfo[i];
135
136
0
    if(fieldInfo->field_type == TIFF_ASCII) {
137
0
      char *params = NULL;
138
139
0
      if(TIFFGetField(tif, fieldInfo->field_tag, &params)) {
140
        // create a tag
141
0
        FITAG *tag = FreeImage_CreateTag();
142
0
        if(!tag) {
143
0
          return FALSE;
144
0
        }
145
146
0
        WORD tag_id = (WORD)fieldInfo->field_tag;
147
148
0
        FreeImage_SetTagType(tag, (FREE_IMAGE_MDTYPE)fieldInfo->field_type);
149
0
        FreeImage_SetTagID(tag, tag_id);
150
0
        FreeImage_SetTagKey(tag, tag_lib.getTagFieldName(TagLib::GEOTIFF, tag_id, defaultKey));
151
0
        FreeImage_SetTagDescription(tag, tag_lib.getTagDescription(TagLib::GEOTIFF, tag_id));
152
0
        FreeImage_SetTagLength(tag, (DWORD)strlen(params) + 1);
153
0
        FreeImage_SetTagCount(tag, FreeImage_GetTagLength(tag));
154
0
        FreeImage_SetTagValue(tag, params);
155
0
        FreeImage_SetMetadata(FIMD_GEOTIFF, dib, FreeImage_GetTagKey(tag), tag);
156
157
        // delete the tag
158
0
        FreeImage_DeleteTag(tag);
159
0
      }
160
0
    } else {
161
0
      short tag_count = 0;
162
0
      void* data = NULL;
163
164
0
      if(TIFFGetField(tif, fieldInfo->field_tag, &tag_count, &data)) {
165
        // create a tag
166
0
        FITAG *tag = FreeImage_CreateTag();
167
0
        if(!tag) {
168
0
          return FALSE;
169
0
        }
170
171
0
        WORD tag_id = (WORD)fieldInfo->field_tag;
172
0
        FREE_IMAGE_MDTYPE tag_type = (FREE_IMAGE_MDTYPE)fieldInfo->field_type;
173
174
0
        FreeImage_SetTagType(tag, tag_type);
175
0
        FreeImage_SetTagID(tag, tag_id);
176
0
        FreeImage_SetTagKey(tag, tag_lib.getTagFieldName(TagLib::GEOTIFF, tag_id, defaultKey));
177
0
        FreeImage_SetTagDescription(tag, tag_lib.getTagDescription(TagLib::GEOTIFF, tag_id));
178
0
        FreeImage_SetTagLength(tag, FreeImage_TagDataWidth(tag_type) * tag_count);
179
0
        FreeImage_SetTagCount(tag, tag_count);
180
0
        FreeImage_SetTagValue(tag, data);
181
0
        FreeImage_SetMetadata(FIMD_GEOTIFF, dib, FreeImage_GetTagKey(tag), tag);
182
183
        // delete the tag
184
0
        FreeImage_DeleteTag(tag);
185
0
      }
186
0
    }
187
0
  } // for(tag_size)
188
189
0
  return TRUE;
190
0
}
191
192
BOOL
193
0
tiff_write_geotiff_profile(TIFF *tif, FIBITMAP *dib) {
194
0
  char defaultKey[16];
195
196
0
  if(FreeImage_GetMetadataCount(FIMD_GEOTIFF, dib) == 0) {
197
    // no GeoTIFF tag here
198
0
    return TRUE;
199
0
  }
200
201
0
  const size_t tag_size = sizeof(xtiffFieldInfo) / sizeof(xtiffFieldInfo[0]);
202
203
0
  TagLib& tag_lib = TagLib::instance();
204
205
0
  for(size_t i = 0; i < tag_size; i++) {
206
0
    const TIFFFieldInfo *fieldInfo = &xtiffFieldInfo[i];
207
208
0
    FITAG *tag = NULL;
209
0
    const char *key = tag_lib.getTagFieldName(TagLib::GEOTIFF, (WORD)fieldInfo->field_tag, defaultKey);
210
211
0
    if(FreeImage_GetMetadata(FIMD_GEOTIFF, dib, key, &tag)) {
212
0
      if(FreeImage_GetTagType(tag) == FIDT_ASCII) {
213
0
        TIFFSetField(tif, fieldInfo->field_tag, FreeImage_GetTagValue(tag));
214
0
      } else {
215
0
        TIFFSetField(tif, fieldInfo->field_tag, FreeImage_GetTagCount(tag), FreeImage_GetTagValue(tag));
216
0
      }
217
0
    }
218
0
  }
219
220
0
  return TRUE;
221
0
}
222
223
// ----------------------------------------------------------
224
//   TIFF EXIF tag reading & writing
225
// ----------------------------------------------------------
226
227
/**
228
Read a single Exif tag
229
230
@param tif TIFF handle
231
@param tag_id TIFF Tag ID
232
@param dib Image being read
233
@param md_model Metadata model where to store the tag
234
@return Returns TRUE if successful, returns FALSE otherwise
235
*/
236
static BOOL 
237
0
tiff_read_exif_tag(TIFF *tif, uint32_t tag_id, FIBITMAP *dib, TagLib::MDMODEL md_model) {
238
0
  uint32_t value_count = 0;
239
0
  int mem_alloc = 0;
240
0
  void *raw_data = NULL;
241
242
0
  if(tag_id == TIFFTAG_EXIFIFD) {
243
    // Exif IFD offset - skip this tag
244
    // md_model should be EXIF_MAIN, the Exif IFD is processed later using the EXIF_EXIF metadata model
245
0
    return TRUE;
246
0
  }
247
0
  if((tag_id == TIFFTAG_GPSIFD) && (md_model == TagLib::EXIF_MAIN)) {
248
    // Exif GPS IFD offset - skip this tag
249
    // should be processed in another way ...
250
0
    return TRUE;
251
0
  }
252
  
253
0
  TagLib& tagLib = TagLib::instance();
254
255
  // get the tag key - use NULL to avoid reading GeoTIFF tags
256
0
  const char *key = tagLib.getTagFieldName(md_model, (WORD)tag_id, NULL);
257
0
  if(key == NULL) {
258
0
    return TRUE;
259
0
  }
260
261
0
  const TIFFField *fip = TIFFFieldWithTag(tif, tag_id);
262
0
  if(fip == NULL) {
263
0
    return TRUE;
264
0
  }
265
266
0
  if(TIFFFieldPassCount(fip)) { 
267
    // a count value is required for 'TIFFGetField'
268
269
0
    if (TIFFFieldReadCount(fip) != TIFF_VARIABLE2) {
270
      // a count is required, it will be of type uint16_t
271
0
      uint16_t value_count16 = 0;
272
0
      if(TIFFGetField(tif, tag_id, &value_count16, &raw_data) != 1) {
273
        // stop, ignore error
274
0
        return TRUE;
275
0
      }
276
0
      value_count = value_count16;
277
0
    } else {
278
      // a count is required, it will be of type uint32_t
279
0
      uint32_t value_count32 = 0;
280
0
      if(TIFFGetField(tif, tag_id, &value_count32, &raw_data) != 1) {
281
        // stop, ignore error
282
0
        return TRUE;
283
0
      }
284
0
      value_count = value_count32;
285
0
    }
286
287
0
  } else {
288
    // determine count
289
290
0
    if (TIFFFieldReadCount(fip) == TIFF_VARIABLE || TIFFFieldReadCount(fip) == TIFF_VARIABLE2) {
291
0
      value_count = 1;
292
0
    } else if (TIFFFieldReadCount(fip) == TIFF_SPP) {
293
0
      uint16_t spp;
294
0
      TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &spp);
295
0
      value_count = spp;
296
0
    } else {
297
0
      value_count = TIFFFieldReadCount(fip);
298
0
    }
299
300
    // access fields as pointers to data
301
    // (### determining this is NOT robust... and hardly can be. It is implemented looking the _TIFFVGetField code)
302
303
0
    if(TIFFFieldTag(fip) == TIFFTAG_TRANSFERFUNCTION) {
304
      // reading this tag cause a bug probably located somewhere inside libtiff
305
0
      return TRUE;
306
0
    }
307
308
0
    if ((TIFFFieldDataType(fip) == TIFF_ASCII
309
0
         || TIFFFieldReadCount(fip) == TIFF_VARIABLE
310
0
         || TIFFFieldReadCount(fip) == TIFF_VARIABLE2
311
0
         || TIFFFieldReadCount(fip) == TIFF_SPP
312
0
       || value_count > 1)
313
       
314
0
       && TIFFFieldTag(fip) != TIFFTAG_PAGENUMBER
315
0
       && TIFFFieldTag(fip) != TIFFTAG_HALFTONEHINTS
316
0
       && TIFFFieldTag(fip) != TIFFTAG_YCBCRSUBSAMPLING
317
0
       && TIFFFieldTag(fip) != TIFFTAG_DOTRANGE
318
319
       && TIFFFieldTag(fip) != TIFFTAG_BITSPERSAMPLE  //<- these two are tricky - 
320
       && TIFFFieldTag(fip) != TIFFTAG_COMPRESSION  //<- they are defined as TIFF_VARIABLE but in reality return a single value
321
0
       ) {
322
0
         if(TIFFGetField(tif, tag_id, &raw_data) != 1) {
323
           // stop, ignore error
324
0
           return TRUE;
325
0
         }
326
0
    } else {
327
0
      int value_size = 0;
328
329
      // access fields as values
330
331
      // Note: 
332
      // For TIFF_RATIONAL values, TIFFDataWidth() returns 8, but LibTIFF use internaly 4-byte float to represent rationals.
333
0
      {
334
0
        TIFFDataType tag_type = TIFFFieldDataType(fip);
335
0
        switch(tag_type) {
336
0
          case TIFF_RATIONAL:
337
0
          case TIFF_SRATIONAL:
338
0
            value_size = 4;
339
0
            break;
340
0
          default:
341
0
            value_size = TIFFDataWidth(tag_type);
342
0
            break;
343
0
        }
344
0
      }
345
346
0
      raw_data = _TIFFmalloc(value_size * value_count);
347
0
      mem_alloc = 1;
348
0
      int ok = FALSE;
349
      
350
      // ### if value_count > 1, tag is PAGENUMBER or HALFTONEHINTS or YCBCRSUBSAMPLING or DOTRANGE, 
351
      // all off which are value_count == 2 (see tif_dirinfo.c)
352
0
      switch(value_count)
353
0
      {
354
0
        case 1:
355
0
          ok = TIFFGetField(tif, tag_id, raw_data);
356
0
          break;
357
0
        case 2:
358
0
          ok = TIFFGetField(tif, tag_id, raw_data, (BYTE*)(raw_data) + value_size*1);
359
0
          break;
360
/* # we might need more in the future:
361
        case 3:
362
          ok = TIFFGetField(tif, tag_id, raw_data, (BYTE*)(raw_data) + value_size*1, (BYTE*)(raw_data) + value_size*2);
363
          break;
364
*/
365
0
        default:
366
0
          FreeImage_OutputMessageProc(FIF_TIFF, "Unimplemented variable number of parameters for Tiff Tag %s", TIFFFieldName(fip));
367
0
          break;
368
0
      }
369
0
      if(ok != 1) {
370
0
        _TIFFfree(raw_data);
371
0
        return TRUE;
372
0
      }
373
0
    }
374
0
  }
375
376
  // build FreeImage tag from Tiff Tag data we collected
377
378
0
  FITAG *fitag = FreeImage_CreateTag();
379
0
  if(!fitag) {
380
0
    if(mem_alloc) {
381
0
      _TIFFfree(raw_data);
382
0
    }
383
0
    return FALSE;
384
0
  }
385
386
0
  FreeImage_SetTagID(fitag, (WORD)tag_id);
387
0
  FreeImage_SetTagKey(fitag, key);
388
389
0
  switch(TIFFFieldDataType(fip)) {
390
0
    case TIFF_BYTE:
391
0
      FreeImage_SetTagType(fitag, FIDT_BYTE);
392
0
      FreeImage_SetTagLength(fitag, TIFFDataWidth( TIFFFieldDataType(fip) ) * value_count);
393
0
      FreeImage_SetTagCount(fitag, value_count);
394
0
      FreeImage_SetTagValue(fitag, raw_data);
395
0
      break;
396
397
0
    case TIFF_UNDEFINED:
398
0
      FreeImage_SetTagType(fitag, FIDT_UNDEFINED);
399
0
      FreeImage_SetTagLength(fitag, TIFFDataWidth( TIFFFieldDataType(fip) ) * value_count);
400
0
      FreeImage_SetTagCount(fitag, value_count);
401
0
      FreeImage_SetTagValue(fitag, raw_data);
402
0
      break;
403
404
0
    case TIFF_SBYTE:
405
0
      FreeImage_SetTagType(fitag, FIDT_SBYTE);
406
0
      FreeImage_SetTagLength(fitag, TIFFDataWidth( TIFFFieldDataType(fip) ) * value_count);
407
0
      FreeImage_SetTagCount(fitag, value_count);
408
0
      FreeImage_SetTagValue(fitag, raw_data);
409
0
      break;
410
411
0
    case TIFF_SHORT:
412
0
      FreeImage_SetTagType(fitag, FIDT_SHORT);
413
0
      FreeImage_SetTagLength(fitag, TIFFDataWidth( TIFFFieldDataType(fip) ) * value_count);
414
0
      FreeImage_SetTagCount(fitag, value_count);
415
0
      FreeImage_SetTagValue(fitag, raw_data);
416
0
      break;
417
418
0
    case TIFF_SSHORT:
419
0
      FreeImage_SetTagType(fitag, FIDT_SSHORT);
420
0
      FreeImage_SetTagLength(fitag, TIFFDataWidth( TIFFFieldDataType(fip) ) * value_count);
421
0
      FreeImage_SetTagCount(fitag, value_count);
422
0
      FreeImage_SetTagValue(fitag, raw_data);
423
0
      break;
424
425
0
    case TIFF_LONG:
426
0
      FreeImage_SetTagType(fitag, FIDT_LONG);
427
0
      FreeImage_SetTagLength(fitag, TIFFDataWidth( TIFFFieldDataType(fip) ) * value_count);
428
0
      FreeImage_SetTagCount(fitag, value_count);
429
0
      FreeImage_SetTagValue(fitag, raw_data);
430
0
      break;
431
432
0
    case TIFF_IFD:
433
0
      FreeImage_SetTagType(fitag, FIDT_IFD);
434
0
      FreeImage_SetTagLength(fitag, TIFFDataWidth( TIFFFieldDataType(fip) ) * value_count);
435
0
      FreeImage_SetTagCount(fitag, value_count);
436
0
      FreeImage_SetTagValue(fitag, raw_data);
437
0
      break;
438
439
0
    case TIFF_SLONG:
440
0
      FreeImage_SetTagType(fitag, FIDT_SLONG);
441
0
      FreeImage_SetTagLength(fitag, TIFFDataWidth( TIFFFieldDataType(fip) ) * value_count);
442
0
      FreeImage_SetTagCount(fitag, value_count);
443
0
      FreeImage_SetTagValue(fitag, raw_data);
444
0
      break;
445
446
0
    case TIFF_RATIONAL: {
447
      // LibTIFF converts rational to floats : reconvert floats to rationals
448
0
      DWORD *rvalue = (DWORD*)malloc(2 * value_count * sizeof(DWORD));
449
0
      for(uint32_t i = 0; i < value_count; i++) {
450
0
        float *fv = (float*)raw_data;
451
0
        FIRational rational(fv[i]);
452
0
        rvalue[2*i] = rational.getNumerator();
453
0
        rvalue[2*i+1] = rational.getDenominator();
454
0
      }
455
0
      FreeImage_SetTagType(fitag, FIDT_RATIONAL);
456
0
      FreeImage_SetTagLength(fitag, TIFFDataWidth( TIFFFieldDataType(fip) ) * value_count);
457
0
      FreeImage_SetTagCount(fitag, value_count);
458
0
      FreeImage_SetTagValue(fitag, rvalue);
459
0
      free(rvalue);
460
0
    }
461
0
    break;
462
463
0
    case TIFF_SRATIONAL: {
464
      // LibTIFF converts rational to floats : reconvert floats to rationals
465
0
      LONG *rvalue = (LONG*)malloc(2 * value_count * sizeof(LONG));
466
0
      for(uint32_t i = 0; i < value_count; i++) {
467
0
        float *fv = (float*)raw_data;
468
0
        FIRational rational(fv[i]);
469
0
        rvalue[2*i] = rational.getNumerator();
470
0
        rvalue[2*i+1] = rational.getDenominator();
471
0
      }
472
0
      FreeImage_SetTagType(fitag, FIDT_RATIONAL);
473
0
      FreeImage_SetTagLength(fitag, TIFFDataWidth( TIFFFieldDataType(fip) ) * value_count);
474
0
      FreeImage_SetTagCount(fitag, value_count);
475
0
      FreeImage_SetTagValue(fitag, rvalue);
476
0
      free(rvalue);
477
0
    }
478
0
    break;
479
480
0
    case TIFF_FLOAT:
481
0
      FreeImage_SetTagType(fitag, FIDT_FLOAT);
482
0
      FreeImage_SetTagLength(fitag, TIFFDataWidth( TIFFFieldDataType(fip) ) * value_count);
483
0
      FreeImage_SetTagCount(fitag, value_count);
484
0
      FreeImage_SetTagValue(fitag, raw_data);
485
0
      break;
486
487
0
    case TIFF_DOUBLE:
488
0
      FreeImage_SetTagType(fitag, FIDT_DOUBLE);
489
0
      FreeImage_SetTagLength(fitag, TIFFDataWidth( TIFFFieldDataType(fip) ) * value_count);
490
0
      FreeImage_SetTagCount(fitag, value_count);
491
0
      FreeImage_SetTagValue(fitag, raw_data);
492
0
      break;
493
494
0
    case TIFF_LONG8:  // BigTIFF 64-bit unsigned integer 
495
0
      FreeImage_SetTagType(fitag, FIDT_LONG8);
496
0
      FreeImage_SetTagLength(fitag, TIFFDataWidth( TIFFFieldDataType(fip) ) * value_count);
497
0
      FreeImage_SetTagCount(fitag, value_count);
498
0
      FreeImage_SetTagValue(fitag, raw_data);
499
0
      break;
500
501
0
    case TIFF_IFD8:   // BigTIFF 64-bit unsigned integer (offset) 
502
0
      FreeImage_SetTagType(fitag, FIDT_IFD8);
503
0
      FreeImage_SetTagLength(fitag, TIFFDataWidth( TIFFFieldDataType(fip) ) * value_count);
504
0
      FreeImage_SetTagCount(fitag, value_count);
505
0
      FreeImage_SetTagValue(fitag, raw_data);
506
0
      break;
507
508
0
    case TIFF_SLONG8:   // BigTIFF 64-bit signed integer 
509
0
      FreeImage_SetTagType(fitag, FIDT_SLONG8);
510
0
      FreeImage_SetTagLength(fitag, TIFFDataWidth( TIFFFieldDataType(fip) ) * value_count);
511
0
      FreeImage_SetTagCount(fitag, value_count);
512
0
      FreeImage_SetTagValue(fitag, raw_data);
513
0
      break;
514
515
0
    case TIFF_ASCII:
516
0
    default: {
517
0
      size_t length = 0;
518
0
      if(!mem_alloc && (TIFFFieldDataType(fip) == TIFF_ASCII) && (TIFFFieldReadCount(fip) == TIFF_VARIABLE)) {
519
        // when metadata tag is of type ASCII and it's value is of variable size (TIFF_VARIABLE),
520
        // tiff_read_exif_tag function gives length of 1 so all strings are truncated ...
521
        // ... try to avoid this by using an explicit calculation for 'length'
522
0
        length = strlen((char*)raw_data) + 1;
523
0
      }
524
0
      else if(mem_alloc) {
525
        // raw_data allocated by us as _TIFFmalloc(value_size * value_count);
526
0
        const int value_size = TIFFDataWidth( TIFFFieldDataType(fip) );
527
0
        length = value_size * value_count;
528
0
      }
529
0
      FreeImage_SetTagType(fitag, FIDT_ASCII);
530
0
      FreeImage_SetTagLength(fitag, (DWORD)length);
531
0
      FreeImage_SetTagCount(fitag, (DWORD)length);
532
0
      FreeImage_SetTagValue(fitag, raw_data);
533
0
    }
534
0
    break;
535
0
  }
536
537
0
  const char *description = tagLib.getTagDescription(md_model, (WORD)tag_id);
538
0
  if(description) {
539
0
    FreeImage_SetTagDescription(fitag, description);
540
0
  }
541
  // store the tag
542
0
  FreeImage_SetMetadata(tagLib.getFreeImageModel(md_model), dib, FreeImage_GetTagKey(fitag), fitag);
543
544
  // destroy the tag
545
0
  FreeImage_DeleteTag(fitag);
546
547
0
  if(mem_alloc) {
548
0
    _TIFFfree(raw_data);
549
0
  }
550
0
  return TRUE;
551
0
}
552
553
/**
554
Read all known exif tags
555
556
@param tif TIFF handle
557
@param md_model Metadata model where to store the tags
558
@param dib Image being read
559
@return Returns TRUE if successful, returns FALSE otherwise
560
*/
561
BOOL 
562
0
tiff_read_exif_tags(TIFF *tif, TagLib::MDMODEL md_model, FIBITMAP *dib) {
563
564
0
  TagLib& tagLib = TagLib::instance();
565
566
0
  const int count = TIFFGetTagListCount(tif);
567
0
  for(int i = 0; i < count; i++) {
568
0
    uint32_t tag_id = TIFFGetTagListEntry(tif, i);
569
    // read the tag
570
0
    if (!tiff_read_exif_tag(tif, tag_id, dib, md_model))
571
0
      return FALSE;
572
0
  }
573
574
  // we want to know values of standard tags too!!
575
576
  // loop over all Core Directory Tags
577
  // ### uses private data, but there is no other way
578
0
  if(md_model == TagLib::EXIF_MAIN) {
579
0
    const TIFFDirectory *td = &tif->tif_dir;
580
581
0
    uint32_t lastTag = 0; //<- used to prevent reading some tags twice (as stored in tif_fieldinfo)
582
583
0
    for (int fi = 0, nfi = (int)tif->tif_nfields; nfi > 0; nfi--, fi++) {
584
0
      const TIFFField *fld = tif->tif_fields[fi];
585
586
0
      const uint32_t tag_id = TIFFFieldTag(fld);
587
588
0
      if(tag_id == lastTag) {
589
0
        continue;
590
0
      }
591
592
      // test if tag value is set
593
      // (lifted directly from LibTiff _TIFFWriteDirectory)
594
595
0
      if( fld->field_bit == FIELD_CUSTOM ) {
596
0
        int is_set = FALSE;
597
598
0
        for(int ci = 0; ci < td->td_customValueCount; ci++ ) {
599
0
          is_set |= (td->td_customValues[ci].info == fld);
600
0
        }
601
602
0
        if( !is_set ) {
603
0
          continue;
604
0
        }
605
606
0
      } else if(!TIFFFieldSet(tif, fld->field_bit)) {
607
0
        continue;
608
0
      }
609
610
      // process *all* other tags (some will be ignored)
611
612
0
      tiff_read_exif_tag(tif, tag_id, dib, md_model);
613
614
0
      lastTag = tag_id;
615
0
    }
616
617
0
  }
618
619
0
  return TRUE;
620
0
}
621
622
623
/**
624
Skip tags that are already handled by the LibTIFF writing process
625
*/
626
static BOOL 
627
0
skip_write_field(TIFF* tif, uint32_t tag) {
628
0
  switch (tag) {
629
0
    case TIFFTAG_SUBFILETYPE:
630
0
    case TIFFTAG_OSUBFILETYPE:
631
0
    case TIFFTAG_IMAGEWIDTH:
632
0
    case TIFFTAG_IMAGELENGTH:
633
0
    case TIFFTAG_BITSPERSAMPLE:
634
0
    case TIFFTAG_COMPRESSION:
635
0
    case TIFFTAG_PHOTOMETRIC:
636
0
    case TIFFTAG_THRESHHOLDING:
637
0
    case TIFFTAG_CELLWIDTH:
638
0
    case TIFFTAG_CELLLENGTH:
639
0
    case TIFFTAG_FILLORDER:
640
0
    case TIFFTAG_STRIPOFFSETS:
641
0
    case TIFFTAG_ORIENTATION:
642
0
    case TIFFTAG_SAMPLESPERPIXEL:
643
0
    case TIFFTAG_ROWSPERSTRIP:
644
0
    case TIFFTAG_STRIPBYTECOUNTS:
645
0
    case TIFFTAG_MINSAMPLEVALUE:
646
0
    case TIFFTAG_MAXSAMPLEVALUE:
647
0
    case TIFFTAG_XRESOLUTION:
648
0
    case TIFFTAG_YRESOLUTION:
649
0
    case TIFFTAG_PLANARCONFIG:
650
0
    case TIFFTAG_FREEOFFSETS:
651
0
    case TIFFTAG_FREEBYTECOUNTS:
652
0
    case TIFFTAG_GRAYRESPONSEUNIT:
653
0
    case TIFFTAG_GRAYRESPONSECURVE:
654
0
    case TIFFTAG_GROUP3OPTIONS:
655
0
    case TIFFTAG_GROUP4OPTIONS:
656
0
    case TIFFTAG_RESOLUTIONUNIT:
657
0
    case TIFFTAG_PAGENUMBER:
658
0
    case TIFFTAG_COLORRESPONSEUNIT:
659
0
    case TIFFTAG_PREDICTOR:
660
0
    case TIFFTAG_COLORMAP:
661
0
    case TIFFTAG_HALFTONEHINTS:
662
0
    case TIFFTAG_TILEWIDTH:
663
0
    case TIFFTAG_TILELENGTH:
664
0
    case TIFFTAG_TILEOFFSETS:
665
0
    case TIFFTAG_TILEBYTECOUNTS:
666
0
    case TIFFTAG_EXTRASAMPLES:
667
0
    case TIFFTAG_SAMPLEFORMAT:
668
0
    case TIFFTAG_SMINSAMPLEVALUE:
669
0
    case TIFFTAG_SMAXSAMPLEVALUE:
670
      // skip always, values have been set in SaveOneTIFF()
671
0
      return TRUE;
672
0
      break;
673
    
674
0
    case TIFFTAG_RICHTIFFIPTC:
675
      // skip always, IPTC metadata model is set in tiff_write_iptc_profile()
676
0
      return TRUE;
677
0
      break;
678
679
0
    case TIFFTAG_YCBCRCOEFFICIENTS:
680
0
    case TIFFTAG_REFERENCEBLACKWHITE:
681
0
    case TIFFTAG_YCBCRSUBSAMPLING:
682
      // skip as they cannot be filled yet
683
0
      return TRUE;
684
0
      break;
685
      
686
0
    case TIFFTAG_PAGENAME:
687
0
    {
688
0
      char *value = NULL;
689
0
      TIFFGetField(tif, TIFFTAG_PAGENAME, &value);
690
      // only skip if no value has been set
691
0
      if(value == NULL) {
692
0
        return FALSE;
693
0
      } else {
694
0
        return TRUE;
695
0
      }
696
0
    }
697
0
    default:
698
0
      return FALSE;
699
0
      break;
700
0
  }
701
0
}
702
703
/**
704
Write all known exif tags
705
706
@param tif TIFF handle
707
@param md_model Metadata model from where to load the tags
708
@param dib Image being written
709
@return Returns TRUE if successful, returns FALSE otherwise
710
*/
711
BOOL 
712
0
tiff_write_exif_tags(TIFF *tif, TagLib::MDMODEL md_model, FIBITMAP *dib) {
713
0
  char defaultKey[16];
714
  
715
  // only EXIF_MAIN so far
716
0
  if(md_model != TagLib::EXIF_MAIN) {
717
0
    return FALSE;
718
0
  }
719
  
720
0
  if(FreeImage_GetMetadataCount(FIMD_EXIF_MAIN, dib) == 0) {
721
0
    return FALSE;
722
0
  }
723
  
724
0
  TagLib& tag_lib = TagLib::instance();
725
  
726
0
  for (int fi = 0, nfi = (int)tif->tif_nfields; nfi > 0; nfi--, fi++) {
727
0
    const TIFFField *fld = tif->tif_fields[fi];
728
    
729
0
    const uint32_t tag_id = TIFFFieldTag(fld);
730
731
0
    if(skip_write_field(tif, tag_id)) {
732
      // skip tags that are already handled by the LibTIFF writing process
733
0
      continue;
734
0
    }
735
736
0
    FITAG *tag = NULL;
737
    // get the tag key
738
0
    const char *key = tag_lib.getTagFieldName(TagLib::EXIF_MAIN, (WORD)tag_id, defaultKey);
739
740
0
    if(FreeImage_GetMetadata(FIMD_EXIF_MAIN, dib, key, &tag)) {
741
0
      FREE_IMAGE_MDTYPE tag_type = FreeImage_GetTagType(tag);
742
0
      TIFFDataType tif_tag_type = TIFFFieldDataType(fld);
743
      
744
      // check for identical formats
745
746
      // (enum value are the sames between FREE_IMAGE_MDTYPE and TIFFDataType types)
747
0
      if((int)tif_tag_type != (int)tag_type) {
748
        // skip tag or _TIFFmemcpy will fail
749
0
        continue;
750
0
      }
751
      // type of storage may differ (e.g. rationnal array vs float array type)
752
0
      if((unsigned)TIFFDataWidth(tif_tag_type) != FreeImage_TagDataWidth(tag_type)) {
753
        // skip tag or _TIFFmemcpy will fail
754
0
        continue;
755
0
      }
756
757
0
      if(tag_type == FIDT_ASCII) {
758
0
        TIFFSetField(tif, tag_id, FreeImage_GetTagValue(tag));
759
0
      } else {
760
0
        TIFFSetField(tif, tag_id, FreeImage_GetTagCount(tag), FreeImage_GetTagValue(tag));
761
0
      }
762
0
    }
763
0
  }
764
765
0
  return TRUE;
766
0
}