/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, ¶ms)) { |
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 | } |