Refactoring the iff decoder
[deark.git] / modules / tiff.c
blobb8fe7f7c5ec9acb7dbc50e51a315e4f421e40807
1 // This file is part of Deark.
2 // Copyright (C) 2016 Jason Summers
3 // See the file COPYING for terms of use.
5 // Extract various things from TIFF (and similar) image files
7 #include <deark-config.h>
8 #include <deark-private.h>
9 #include <deark-fmtutil.h>
10 DE_DECLARE_MODULE(de_module_tiff);
12 #define ITEMS_IN_ARRAY DE_ARRAYCOUNT
13 #define MAX_IFDS 1000
14 #define DE_TIFF_MAX_STRILES 65536
15 #define DE_TIFF_MAX_SAMPLES 10
17 #define DE_TIFF_MAX_VALUES_TO_PRINT 100
18 #define DE_TIFF_MAX_CHARS_TO_PRINT DE_DBG_MAX_STRLEN
20 #define DATATYPE_BYTE 1
21 #define DATATYPE_ASCII 2
22 #define DATATYPE_UINT16 3
23 #define DATATYPE_UINT32 4
24 #define DATATYPE_RATIONAL 5
25 #define DATATYPE_SBYTE 6
26 #define DATATYPE_UNDEF 7
27 #define DATATYPE_SINT16 8
28 #define DATATYPE_SINT32 9
29 #define DATATYPE_SRATIONAL 10
30 #define DATATYPE_FLOAT32 11
31 #define DATATYPE_FLOAT64 12
32 #define DATATYPE_IFD32 13
33 #define DATATYPE_UINT64 16
34 #define DATATYPE_SINT64 17
35 #define DATATYPE_IFD64 18
37 #define DE_TIFFFMT_TIFF 1
38 #define DE_TIFFFMT_BIGTIFF 2
39 #define DE_TIFFFMT_PANASONIC 3 // Panasonic RAW / RW2
40 #define DE_TIFFFMT_ORF 4 // Olympus RAW
41 #define DE_TIFFFMT_DCP 5 // DNG Camera Profile (DCP)
42 #define DE_TIFFFMT_MDI 6 // Microsoft Office Document Imaging
43 #define DE_TIFFFMT_JPEGXR 7 // JPEG XR
44 #define DE_TIFFFMT_MPEXT 8 // "MP Extension" data from MPF format
45 #define DE_TIFFFMT_NIKONMN 9 // Nikon MakerNote
46 #define DE_TIFFFMT_APPLEMN 10 // Apple iOS MakerNote
47 #define DE_TIFFFMT_FUJIFILMMN 11 // FujiFilm MakerNote
49 #define IFDTYPE_NORMAL 0
50 #define IFDTYPE_SUBIFD 1
51 #define IFDTYPE_EXIF 2
52 #define IFDTYPE_EXIFINTEROP 3
53 #define IFDTYPE_GPS 4
54 #define IFDTYPE_GLOBALPARAMS 5 // TIFF-FX
55 #define IFDTYPE_NIKONMN 6 // First IFD of a Nikon MakerNote
56 #define IFDTYPE_NIKONPREVIEW 7
57 #define IFDTYPE_APPLEMN 8
58 #define IFDTYPE_MASKSUBIFD 9
59 #define IFDTYPE_FUJIFILMMN 10
61 #define TAG_NEWSUBFILETYPE 254
62 #define TAG_OLDSUBFILETYPE 255
63 #define TAG_IMAGEWIDTH 256
64 #define TAG_IMAGELENGTH 257
65 #define TAG_BITSPERSAMPLE 258
66 #define TAG_COMPRESSION 259
67 #define TAG_PHOTOMETRIC 262
68 #define TAG_FILLORDER 266
69 #define TAG_STRIPOFFSETS 273
70 #define TAG_ORIENTATION 274
71 #define TAG_SAMPLESPERPIXEL 277
72 #define TAG_ROWSPERSTRIP 278
73 #define TAG_STRIPBYTECOUNTS 279
74 #define TAG_XRESOLUTION 282
75 #define TAG_YRESOLUTION 283
76 #define TAG_PLANARCONFIG 284
77 #define TAG_T4OPTIONS 292
78 #define TAG_T6OPTIONS 293
79 #define TAG_RESOLUTIONUNIT 296
80 #define TAG_DATETIME 306
81 #define TAG_PREDICTOR 317
82 #define TAG_TILEWIDTH 322
83 #define TAG_TILELENGTH 323
84 #define TAG_TILEOFFSETS 324
85 #define TAG_TILEBYTECOUNTS 325
86 #define TAG_SAMPLEFORMAT 339
87 #define TAG_JPEGTABLES 347
88 #define TAG_JPEGINTERCHANGEFORMAT 513
89 #define TAG_JPEGINTERCHANGEFORMATLENGTH 514
90 #define TAG_YCBCRPOSITIONING 531
92 #define CMPR_NONE 1
93 #define CMPR_CCITTRLE 2
94 #define CMPR_FAX3 3
95 #define CMPR_FAX4 4
96 #define CMPR_LZW 5
97 #define CMPR_OLDJPEG 6
98 #define CMPR_NEWJPEG 7
99 #define CMPR_DEFLATE 8
100 #define CMPR_PACKBITS 32773
101 #define CMPR_DEFLATE_ALT 32946
103 struct page_ctx;
104 struct decode_page_ctx;
105 struct localctx_struct;
106 typedef struct localctx_struct lctx;
107 struct taginfo;
108 struct tagnuminfo;
110 struct ifdstack_item {
111 i64 offset;
112 u8 ifdtype;
113 u8 is_in_main_ifd_list;
116 typedef void (*handler_fn_type)(deark *c, lctx *d, const struct taginfo *tg,
117 const struct tagnuminfo *tni);
119 struct valdec_params {
120 lctx *d;
121 const struct taginfo *tg;
122 i64 idx;
123 i64 n;
125 struct valdec_result {
126 // Value decoders will be called with a valid, empty ucstring 's'.
127 de_ucstring *s;
130 typedef int (*val_decoder_fn_type)(deark *c, const struct valdec_params *vp, struct valdec_result *vr);
132 struct tagnuminfo {
133 int tagnum;
135 // 0x0001=NOT valid in normal TIFF files/IFDs
136 // 0x0004=multi-string ASCII type expected
137 // 0x08=suppress auto display of values
138 // 0x10=this is an Exif tag
139 // 0x20=an Exif Interoperability-IFD tag
140 // 0x40=a GPS attribute tag
141 // 0x80=a DNG tag
142 // 0x0100=TIFF/EP
143 // 0x0200=TIFF/IT
144 // 0x0400=tags valid in JPEG XR files (from the spec, and jxrlib)
145 // 0x0800=tags for Multi-Picture Format (.MPO) extensions
146 // 0x1000=tags for Nikon MakerNote
147 // 0x2000=tags for Apple iOS MakerNote
148 // 0x4000=Panasonic RAW/RW2
149 // 0x8000=FUJIFILM
150 unsigned int flags;
152 const char *tagname;
153 handler_fn_type hfn;
154 val_decoder_fn_type vdfn;
157 typedef void (*decompressor_fn)(deark *c, lctx *d, struct page_ctx *pg,
158 struct decode_page_ctx *dctx);
160 struct cmpr_meth_info {
161 u32 id;
162 UI flags;
163 const char *name;
164 decompressor_fn decompressor;
167 struct strile_data_struct {
168 i64 pos;
169 i64 len;
172 struct page_ctx {
173 i64 ifdpos;
174 int ifd_idx;
175 int ifd_idx_in_main_list; // -1 if not in main list
176 u8 ifdtype;
178 u8 have_imagewidth;
179 u8 have_jpeglength;
180 u8 is_thumb;
181 u8 have_density;
182 u8 have_strip_tags, have_tile_tags;
183 u8 have_jpegtables;
185 u32 compression;
186 u32 orientation;
187 u32 ycbcrpositioning;
188 u32 bits_per_sample;
189 u32 samples_per_pixel;
190 u32 photometric;
191 u32 fill_order;
192 u32 planarconfig;
193 u32 predictor;
194 u32 sample_format;
195 u32 resolution_unit;
196 u32 t4options, t6options;
197 double density_ImageWidth, density_ImageLength;
198 i64 imagewidth, imagelength; // Raw tag values, before considering Orientation
199 i64 jpegoffset;
200 i64 jpeglength;
201 i64 rows_per_strip;
202 i64 tile_width, tile_height;
203 u8 is_old_lzw;
204 u8 extrasamples_count;
205 u8 extrasample_type[DE_TIFF_MAX_SAMPLES]; // [0] = first *extra* sample, not first sample
206 const struct cmpr_meth_info *cmi;
208 i64 strile_count;
209 struct strile_data_struct *strile_data; // array[strile_count]
210 struct de_timestamp internal_mod_time;
211 de_color pal[256];
212 char errmsgtoken_ifd[40];
215 // Data associated with an actual tag in an IFD in the file
216 struct taginfo {
217 // Might be more logical for us to have a separate struct for page_ctx, but
218 // I don't want to add a param to every "handler" function
219 struct page_ctx *pg;
221 int tagnum;
222 int datatype;
223 int tag_known;
224 i64 valcount;
225 i64 val_offset;
226 i64 unit_size;
227 i64 total_size;
230 struct localctx_struct {
231 int is_le;
232 int fmt;
233 u8 is_bigtiff;
234 u8 is_xiff;
235 int is_exif_submodule;
236 int host_is_le;
237 int can_decode_fltpt;
238 u8 opt_decode;
239 u8 is_deark_iptc, is_deark_8bim;
241 u32 first_ifd_orientation; // Valid if != 0
242 u32 exif_version_as_uint32; // Valid if != 0
243 u8 has_exif_gps;
244 u8 first_ifd_cosited;
246 struct ifdstack_item *ifdstack;
247 int ifdstack_capacity;
248 int ifdstack_numused;
249 int current_textfield_encoding;
251 struct de_inthashtable *ifds_seen;
252 int ifd_count; // Number of IFDs that we currently know of
253 int num_main_ifds_processed;
255 i64 ifdhdrsize;
256 i64 ifditemsize;
257 i64 offsetoffset;
258 i64 offsetsize; // Number of bytes in a file offset
260 const struct de_module_in_params *in_params;
262 unsigned int mpf_main_image_count;
264 char errmsgtoken_module[40];
267 static void detiff_err(deark *c, lctx *d, struct page_ctx *pg, const char *fmt, ...)
268 de_gnuc_attribute ((format (printf, 4, 5)));
270 // pg can be NULL (if not in IFD context)
271 static void detiff_err(deark *c, lctx *d, struct page_ctx *pg, const char *fmt, ...)
273 va_list ap;
274 char buf[256];
276 va_start(ap, fmt);
277 if(d->errmsgtoken_module[0] && pg) {
278 de_vsnprintf(buf, sizeof(buf), fmt, ap);
279 de_err(c, "[%s:%s] %s", d->errmsgtoken_module, pg->errmsgtoken_ifd, buf);
281 else if(d->errmsgtoken_module[0]) {
282 de_vsnprintf(buf, sizeof(buf), fmt, ap);
283 de_err(c, "[%s] %s", d->errmsgtoken_module, buf);
285 else if(pg) {
286 de_vsnprintf(buf, sizeof(buf), fmt, ap);
287 de_err(c, "[%s] %s", pg->errmsgtoken_ifd, buf);
289 else {
290 de_verr(c, fmt, ap);
292 va_end(ap);
295 static void detiff_warn(deark *c, lctx *d, struct page_ctx *pg, const char *fmt, ...)
296 de_gnuc_attribute ((format (printf, 4, 5)));
298 static void detiff_warn(deark *c, lctx *d, struct page_ctx *pg, const char *fmt, ...)
300 va_list ap;
301 char buf[256];
303 va_start(ap, fmt);
304 if(d->errmsgtoken_module[0] && pg) {
305 de_vsnprintf(buf, sizeof(buf), fmt, ap);
306 de_warn(c, "[%s:%s] %s", d->errmsgtoken_module, pg->errmsgtoken_ifd, buf);
308 else if(d->errmsgtoken_module[0]) {
309 de_vsnprintf(buf, sizeof(buf), fmt, ap);
310 de_warn(c, "[%s] %s", d->errmsgtoken_module, buf);
312 else if(pg) {
313 de_vsnprintf(buf, sizeof(buf), fmt, ap);
314 de_warn(c, "[%s] %s", pg->errmsgtoken_ifd, buf);
316 else {
317 de_vwarn(c, fmt, ap);
319 va_end(ap);
322 // Returns 0 if stack is empty.
323 static i64 pop_ifd(deark *c, lctx *d, u8 *ifdtype, u8 *is_in_main_ifd_list)
325 i64 ifdpos;
326 if(!d->ifdstack) return 0;
327 if(d->ifdstack_numused<1) return 0;
328 ifdpos = d->ifdstack[d->ifdstack_numused-1].offset;
329 *ifdtype = d->ifdstack[d->ifdstack_numused-1].ifdtype;
330 *is_in_main_ifd_list = d->ifdstack[d->ifdstack_numused-1].is_in_main_ifd_list;
331 d->ifdstack_numused--;
332 return ifdpos;
335 static void push_ifd(deark *c, lctx *d, i64 ifdpos, u8 ifdtype, u8 is_in_main_ifd_list)
337 if(ifdpos==0) return;
339 if(ifdpos < 0 || ifdpos >= c->infile->len) {
340 detiff_warn(c, d, NULL, "Invalid IFD offset: %"I64_FMT, ifdpos);
341 return;
344 // Append to the IFD list (of all IFDs). This is only used for loop detection.
345 if(!d->ifds_seen) {
346 d->ifds_seen = de_inthashtable_create(c);
348 if(d->ifd_count >= MAX_IFDS) {
349 detiff_warn(c, d, NULL, "Too many TIFF IFDs");
350 return;
352 if(!de_inthashtable_add_item(c, d->ifds_seen, ifdpos, NULL)) {
353 detiff_err(c, d, NULL, "IFD loop detected");
354 return;
356 d->ifd_count++;
358 // Add to the IFD stack (of unprocessed IFDs).
359 if(!d->ifdstack) {
360 d->ifdstack_capacity = 200;
361 d->ifdstack = de_mallocarray(c, d->ifdstack_capacity, sizeof(struct ifdstack_item));
362 d->ifdstack_numused = 0;
364 if(d->ifdstack_numused >= d->ifdstack_capacity) {
365 detiff_warn(c, d, NULL, "Too many TIFF IFDs");
366 return;
368 d->ifdstack[d->ifdstack_numused].offset = ifdpos;
369 d->ifdstack[d->ifdstack_numused].ifdtype = ifdtype;
370 d->ifdstack[d->ifdstack_numused].is_in_main_ifd_list = is_in_main_ifd_list;
371 d->ifdstack_numused++;
374 static int size_of_data_type(int tt)
376 switch(tt) {
377 case DATATYPE_BYTE: case DATATYPE_SBYTE:
378 case DATATYPE_ASCII:
379 case DATATYPE_UNDEF:
380 return 1;
381 case DATATYPE_UINT16: case DATATYPE_SINT16:
382 return 2;
383 case DATATYPE_UINT32: case DATATYPE_SINT32:
384 case DATATYPE_FLOAT32:
385 case DATATYPE_IFD32:
386 return 4;
387 case DATATYPE_RATIONAL: case DATATYPE_SRATIONAL:
388 case DATATYPE_FLOAT64:
389 case DATATYPE_UINT64: case DATATYPE_SINT64:
390 case DATATYPE_IFD64:
391 return 8;
393 return 0;
396 static int read_rational_as_double(deark *c, lctx *d, i64 pos, double *n)
398 i64 num, den;
400 *n = 0.0;
401 num = dbuf_getu32x(c->infile, pos, d->is_le);
402 den = dbuf_getu32x(c->infile, pos+4, d->is_le);
403 if(den==0) return 0;
404 *n = (double)num/(double)den;
405 return 1;
408 static int read_srational_as_double(deark *c, lctx *d, i64 pos, double *n)
410 i64 num, den;
412 *n = 0.0;
413 num = dbuf_geti32x(c->infile, pos, d->is_le);
414 den = dbuf_geti32x(c->infile, pos+4, d->is_le);
415 if(den==0) return 0;
416 *n = (double)num/(double)den;
417 return 1;
420 // FIXME: This function seems superfluous.
421 // It should somehow be consolidated with read_numeric_value().
422 static int read_tag_value_as_double(deark *c, lctx *d, const struct taginfo *tg,
423 i64 value_index, double *n)
425 i64 offs;
427 *n = 0.0;
428 if(value_index<0 || value_index>=tg->valcount) return 0;
429 offs = tg->val_offset + value_index*tg->unit_size;
431 switch(tg->datatype) {
432 case DATATYPE_RATIONAL:
433 return read_rational_as_double(c, d, offs, n);
434 case DATATYPE_SRATIONAL:
435 return read_srational_as_double(c, d, offs, n);
436 case DATATYPE_FLOAT32:
437 if(!d->can_decode_fltpt) return 0;
438 *n = dbuf_getfloat32x(c->infile, offs, d->is_le);
439 return 1;
440 case DATATYPE_FLOAT64:
441 if(!d->can_decode_fltpt) return 0;
442 *n = dbuf_getfloat64x(c->infile, offs, d->is_le);
443 return 1;
445 // There should be no need to support other data types (like UINT32).
447 return 0;
450 static int read_tag_value_as_int64(deark *c, lctx *d, const struct taginfo *tg,
451 i64 value_index, i64 *n)
453 double v_dbl;
454 i64 offs;
456 *n = 0;
457 if(value_index<0 || value_index>=tg->valcount) return 0;
458 offs = tg->val_offset + value_index*tg->unit_size;
460 switch(tg->datatype) {
461 case DATATYPE_UINT16:
462 *n = dbuf_getu16x(c->infile, offs, d->is_le);
463 return 1;
464 case DATATYPE_UINT32:
465 case DATATYPE_IFD32:
466 *n = dbuf_getu32x(c->infile, offs, d->is_le);
467 return 1;
468 case DATATYPE_BYTE:
469 case DATATYPE_UNDEF:
470 case DATATYPE_ASCII:
471 *n = (i64)de_getbyte(offs);
472 return 1;
473 case DATATYPE_UINT64:
474 case DATATYPE_IFD64:
475 // TODO: Somehow support unsigned 64-bit ints that don't fit into
476 // a i64?
477 *n = dbuf_geti64x(c->infile, offs, d->is_le);
478 if(*n < 0) return 0;
479 return 1;
480 case DATATYPE_SINT16:
481 *n = dbuf_geti16x(c->infile, offs, d->is_le);
482 return 1;
483 case DATATYPE_SINT32:
484 *n = dbuf_geti32x(c->infile, offs, d->is_le);
485 return 1;
486 case DATATYPE_SINT64:
487 *n = dbuf_geti64x(c->infile, offs, d->is_le);
488 return 1;
489 case DATATYPE_SBYTE:
490 *n = dbuf_geti8(c->infile, offs);
491 return 1;
492 case DATATYPE_RATIONAL:
493 case DATATYPE_SRATIONAL:
494 case DATATYPE_FLOAT32:
495 case DATATYPE_FLOAT64:
496 if(read_tag_value_as_double(c, d, tg, value_index, &v_dbl)) {
497 *n = (i64)v_dbl;
498 return 1;
500 return 0;
502 return 0;
505 static void format_double(de_ucstring *s, double val)
507 // TODO: Formatting should be more intelligent
508 ucstring_printf(s, DE_ENCODING_LATIN1, "%f", val);
511 struct numeric_value {
512 int isvalid;
513 i64 val_int64;
514 double val_double;
517 // Do-it-all function for reading numeric values.
518 // If dbglinebuf!=NULL, print a string representation of the value to it.
519 static void read_numeric_value(deark *c, lctx *d, const struct taginfo *tg,
520 i64 value_index, struct numeric_value *nv, de_ucstring *dbgline)
522 int ret;
523 i64 offs;
525 nv->isvalid = 0;
526 nv->val_int64 = 0;
527 nv->val_double = 0.0;
529 // FIXME: This is recalculated in read_tag_value_as_int64.
530 offs = tg->val_offset + value_index*tg->unit_size;
532 switch(tg->datatype) {
533 case DATATYPE_BYTE:
534 case DATATYPE_SBYTE:
535 case DATATYPE_UNDEF:
536 case DATATYPE_ASCII:
537 case DATATYPE_UINT16:
538 case DATATYPE_SINT16:
539 case DATATYPE_UINT32:
540 case DATATYPE_SINT32:
541 case DATATYPE_IFD32:
542 case DATATYPE_UINT64:
543 case DATATYPE_SINT64:
544 case DATATYPE_IFD64:
545 ret = read_tag_value_as_int64(c, d, tg, value_index, &nv->val_int64);
546 nv->val_double = (double)nv->val_int64;
547 nv->isvalid = ret;
548 if(dbgline) {
549 if(nv->isvalid)
550 ucstring_printf(dbgline, DE_ENCODING_LATIN1, "%" I64_FMT, nv->val_int64);
551 else
552 ucstring_append_sz(dbgline, "?", DE_ENCODING_LATIN1);
554 break;
556 case DATATYPE_RATIONAL:
557 case DATATYPE_SRATIONAL:
559 i64 num, den;
561 if(tg->datatype==DATATYPE_SRATIONAL) {
562 num = dbuf_geti32x(c->infile, offs, d->is_le);
563 den = dbuf_geti32x(c->infile, offs+4, d->is_le);
565 else {
566 num = dbuf_getu32x(c->infile, offs, d->is_le);
567 den = dbuf_getu32x(c->infile, offs+4, d->is_le);
570 if(den==0) {
571 nv->isvalid = 0;
572 nv->val_double = 0.0;
573 nv->val_int64 = 0;
574 if(dbgline) {
575 ucstring_printf(dbgline, DE_ENCODING_LATIN1, "%" I64_FMT "/%" I64_FMT, num, den);
579 else {
580 nv->isvalid = 1;
581 nv->val_double = (double)num/(double)den;
582 nv->val_int64 = (i64)nv->val_double;
583 if(dbgline) {
584 format_double(dbgline, nv->val_double);
588 break;
590 case DATATYPE_FLOAT32:
591 case DATATYPE_FLOAT64:
592 if(tg->datatype==DATATYPE_FLOAT64) {
593 nv->val_double = dbuf_getfloat64x(c->infile, offs, d->is_le);
595 else {
596 nv->val_double = dbuf_getfloat32x(c->infile, offs, d->is_le);
598 nv->val_int64 = (i64)nv->val_double;
599 nv->isvalid = 1;
600 if(dbgline) {
601 format_double(dbgline, nv->val_double);
603 break;
605 default:
606 if(dbgline) {
607 ucstring_append_sz(dbgline, "?", DE_ENCODING_LATIN1);
612 static i64 getfpos(deark *c, lctx *d, i64 pos)
614 if(d->is_bigtiff) {
615 return dbuf_geti64x(c->infile, pos, d->is_le);
617 return dbuf_getu32x(c->infile, pos, d->is_le);
620 static void do_oldjpeg(deark *c, lctx *d, struct page_ctx *pg)
622 const char *extension;
623 unsigned int createflags;
624 i64 jpeglength = pg->jpeglength;
626 if(pg->jpegoffset==0) return;
627 if(!pg->have_jpeglength) {
628 // Missing JPEGInterchangeFormatLength tag. Assume it goes to the end
629 // of the file.
630 jpeglength = c->infile->len - pg->jpegoffset;
632 if(jpeglength<1 || jpeglength>DE_MAX_SANE_OBJECT_SIZE) {
633 return;
636 if(pg->jpegoffset+jpeglength>c->infile->len) {
637 detiff_warn(c, d, pg, "Invalid offset/length of embedded JPEG data (offset=%"I64_FMT
638 ", len=%"I64_FMT")", pg->jpegoffset, jpeglength);
639 return;
642 if(dbuf_memcmp(c->infile, pg->jpegoffset, "\xff\xd8\xff", 3)) {
643 detiff_warn(c, d, pg, "Expected JPEG data at %"I64_FMT" not found", pg->jpegoffset);
644 return;
647 // Found an embedded JPEG image or thumbnail that we can extract.
648 if(d->is_exif_submodule) {
649 extension = "exifthumb.jpg";
650 createflags = DE_CREATEFLAG_IS_AUX;
652 else if(d->fmt==DE_TIFFFMT_NIKONMN) {
653 extension = "nikonthumb.jpg";
654 createflags = DE_CREATEFLAG_IS_AUX;
656 else {
657 extension = "jpg";
658 // TODO: Should createflags be set to DE_CREATEFLAG_IS_AUX in some cases?
659 createflags = 0;
661 dbuf_create_file_from_slice(c->infile, pg->jpegoffset, jpeglength, extension, NULL, createflags);
664 static void do_leaf_metadata(deark *c, lctx *d, i64 pos1, i64 len)
666 i64 pos;
667 u8 buf[4];
668 u8 segtype[40];
669 i64 data_len;
671 if(len<1) return;
672 if(pos1+len > c->infile->len) return;
673 de_dbg(c, "leaf metadata at %d size=%d", (int)pos1, (int)len);
675 // This format appears to be hierarchical, but for now we only care about
676 // the top level.
678 pos = pos1;
679 while(pos < pos1+len) {
680 de_read(buf, pos, 4);
681 if(de_memcmp(buf, "PKTS", 4)) {
682 break;
684 pos+=4;
686 pos+=4; // Don't know what these 4 bytes are for.
688 de_read(segtype, pos, 40);
689 pos+=40;
691 // TODO: Is this always big-endian?
692 data_len = de_getu32be(pos);
693 pos+=4;
695 if(!de_memcmp(segtype, "JPEG_preview_data\0", 18)) {
696 de_dbg(c, "jpeg preview at %d len=%d", (int)pos, (int)data_len);
697 dbuf_create_file_from_slice(c->infile, pos, data_len, "leafthumb.jpg", NULL, DE_CREATEFLAG_IS_AUX);
699 pos += data_len;
703 struct int_and_str {
704 i64 n;
705 const char *s;
708 static const char *lookup_str(const struct int_and_str *items, size_t num_items, i64 n)
710 i64 i;
712 for(i=0; i<(i64)num_items; i++) {
713 if(items[i].n==n && items[i].s!=NULL) {
714 return items[i].s;
717 return "?";
720 static void lookup_str_and_append_to_ucstring(const struct int_and_str *items, size_t num_items,
721 i64 n, de_ucstring *s)
723 const char *sz;
725 sz = lookup_str(items, num_items, n);
726 ucstring_append_sz(s, sz, DE_ENCODING_UTF8);
729 static int valdec_newsubfiletype(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
731 i64 n = vp->n;
733 if(n<1) return 0;
735 if(n&0x1) {
736 ucstring_append_flags_item(vr->s, "reduced-res");
737 n -= 0x1;
739 if(n&0x2) {
740 ucstring_append_flags_item(vr->s, "one-page-of-many");
741 n -= 0x2;
743 if(n&0x4) {
744 ucstring_append_flags_item(vr->s, "mask");
745 n -= 0x4;
747 if(n&0x10) {
748 ucstring_append_flags_item(vr->s, "MRC-related");
749 n -= 0x10;
751 if(n!=0) {
752 ucstring_append_flags_itemf(vr->s, "0x%x", (unsigned int)n);
755 return 1;
758 static int valdec_oldsubfiletype(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
760 static const struct int_and_str name_map[] = {
761 {1, "full-res"}, {2, "reduced-res"}, {3, "one-page-of-many"}
763 lookup_str_and_append_to_ucstring(name_map, ITEMS_IN_ARRAY(name_map), vp->n, vr->s);
764 return 1;
767 static const struct cmpr_meth_info *find_cmpr_meth_info(u32 id);
769 static int valdec_compression(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
771 const struct cmpr_meth_info *cmi;
773 cmi = find_cmpr_meth_info((u32)vp->n);
775 if(cmi && cmi->name) {
776 ucstring_append_sz(vr->s, cmi->name, DE_ENCODING_UTF8);
778 else {
779 ucstring_append_sz(vr->s, "?", DE_ENCODING_LATIN1);
781 return 1;
784 static const struct int_and_str photometric_name_map[] = {
785 {0, "grayscale/white-is-0"}, {1, "grayscale/black-is-0"},
786 {2, "RGB"}, {3, "palette"}, {4, "Holdout Mask"}, {5, "CMYK"}, {6, "YCbCr"},
787 {8, "CIELab"}, {9, "ICCLab"}, {10, "ITULab"},
788 {32803, "CFA"}, {32844, "CIELog2L"}, {32845, "CIELog2Luv"},
789 {34892, "LinearRaw"}
791 static int valdec_photometric(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
793 lookup_str_and_append_to_ucstring(photometric_name_map, ITEMS_IN_ARRAY(photometric_name_map), vp->n, vr->s);
794 return 1;
797 static int valdec_threshholding(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
799 static const struct int_and_str name_map[] = {
800 {1, "not dithered"}, {2, "ordered dither"}, {3, "error diffusion"}
802 lookup_str_and_append_to_ucstring(name_map, ITEMS_IN_ARRAY(name_map), vp->n, vr->s);
803 return 1;
806 static int valdec_fillorder(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
808 static const struct int_and_str name_map[] = {
809 {1, "MSB-first"}, {2, "LSB-first"}
811 lookup_str_and_append_to_ucstring(name_map, ITEMS_IN_ARRAY(name_map), vp->n, vr->s);
812 return 1;
815 static int valdec_orientation(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
817 ucstring_append_sz(vr->s, fmtutil_tiff_orientation_name(vp->n), DE_ENCODING_UTF8);
818 return 1;
821 static int valdec_planarconfiguration(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
823 static const struct int_and_str name_map[] = {
824 {1, "contiguous"}, {2, "separated"}
826 lookup_str_and_append_to_ucstring(name_map, ITEMS_IN_ARRAY(name_map), vp->n, vr->s);
827 return 1;
830 static int valdec_t4options(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
832 if(vp->n<1) return 0;
834 if(vp->n&0x1) {
835 ucstring_append_flags_item(vr->s, "2-d encoding");
837 if(vp->n&0x2) {
838 ucstring_append_flags_item(vr->s, "uncompressed mode allowed");
840 if(vp->n&0x4) {
841 ucstring_append_flags_item(vr->s, "has fill bits");
843 if((vp->n & ~0x7)!=0) {
844 ucstring_append_flags_item(vr->s, "?");
847 return 1;
850 static int valdec_t6options(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
852 if(vp->n<1) return 0;
854 if(vp->n&0x2) {
855 ucstring_append_flags_item(vr->s, "uncompressed mode allowed");
857 if((vp->n & ~0x2)!=0) {
858 ucstring_append_flags_item(vr->s, "?");
861 return 1;
864 static int valdec_resolutionunit(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
866 static const struct int_and_str name_map[] = {
867 {1, "unspecified"}, {2, "pixels/inch"}, {3, "pixels/cm"}
869 lookup_str_and_append_to_ucstring(name_map, ITEMS_IN_ARRAY(name_map), vp->n, vr->s);
870 return 1;
873 static int valdec_pagenumber(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
875 if(vp->idx==0) {
876 ucstring_printf(vr->s, DE_ENCODING_LATIN1, "page %d", (int)(vp->n+1));
877 return 1;
879 if(vp->idx==1) {
880 if(vp->n==0) {
881 ucstring_append_sz(vr->s, "of an unknown number", DE_ENCODING_LATIN1);
883 else {
884 ucstring_printf(vr->s, DE_ENCODING_LATIN1, "of %d", (int)vp->n);
886 return 1;
888 return 0;
891 static int valdec_predictor(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
893 static const struct int_and_str name_map[] = {
894 {1, "none"}, {2, "horizontal differencing"}
896 lookup_str_and_append_to_ucstring(name_map, ITEMS_IN_ARRAY(name_map), vp->n, vr->s);
897 return 1;
900 static int valdec_inkset(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
902 static const struct int_and_str name_map[] = {
903 {1, "CMYK"}, {2, "not CMYK"}
905 lookup_str_and_append_to_ucstring(name_map, ITEMS_IN_ARRAY(name_map), vp->n, vr->s);
906 return 1;
909 static int valdec_extrasamples(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
911 static const struct int_and_str name_map[] = {
912 {0, "unspecified"}, {1, "assoc-alpha"}, {2, "unassoc-alpha"}
914 lookup_str_and_append_to_ucstring(name_map, ITEMS_IN_ARRAY(name_map), vp->n, vr->s);
915 return 1;
918 static int valdec_sampleformat(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
920 static const struct int_and_str name_map[] = {
921 {1, "uint"}, {2, "signed int"}, {3, "float"}, {4, "undefined"}
923 lookup_str_and_append_to_ucstring(name_map, ITEMS_IN_ARRAY(name_map), vp->n, vr->s);
924 return 1;
927 static int valdec_jpegproc(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
929 static const struct int_and_str name_map[] = {
930 {1, "baseline"}, {14, "lossless+huffman"}
932 lookup_str_and_append_to_ucstring(name_map, ITEMS_IN_ARRAY(name_map), vp->n, vr->s);
933 return 1;
936 static int valdec_ycbcrpositioning(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
938 static const struct int_and_str name_map[] = {
939 {1, "centered"}, {2, "cosited"}
941 lookup_str_and_append_to_ucstring(name_map, ITEMS_IN_ARRAY(name_map), vp->n, vr->s);
942 return 1;
945 static int valdec_exposureprogram(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
947 static const struct int_and_str name_map[] = {
948 {0, "not defined"}, {1, "manual"}, {2, "normal program"}, {3, "aperture priority"},
949 {4, "shutter priority"}, {5, "creative program"}, {6, "action program"},
950 {7, "portrait mode"}, {8, "landscape mode"}
952 lookup_str_and_append_to_ucstring(name_map, ITEMS_IN_ARRAY(name_map), vp->n, vr->s);
953 return 1;
956 static int valdec_componentsconfiguration(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
958 static const struct int_and_str name_map[] = {
959 {0, "n/a"}, {1, "Y"}, {2, "Cb"}, {3, "Cr"}, {4, "R"}, {5, "G"}, {6, "B"},
960 {48, "n/a?"}, {49, "Y?"}, {50, "Cb?"}, {51, "Cr?"}, {52, "R?"}, {53, "G?"}, {54, "B?"}
962 lookup_str_and_append_to_ucstring(name_map, ITEMS_IN_ARRAY(name_map), vp->n, vr->s);
963 return 1;
966 static int valdec_meteringmode(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
968 static const struct int_and_str name_map[] = {
969 {0, "unknown"}, {1, "Average"}, {2, "CenterWeightedAverage"},
970 {3, "Spot"}, {4, "MultiSpot"}, {5, "Pattern"}, {6, "Partial"},
971 {255, "other"}
973 lookup_str_and_append_to_ucstring(name_map, ITEMS_IN_ARRAY(name_map), vp->n, vr->s);
974 return 1;
977 static int valdec_lightsource(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
979 static const struct int_and_str name_map[] = {
980 {0, "unknown"}, {1, "Daylight"}, {2, "Fluorescent"},
981 {3, "Tungsten"}, {4, "Flash"}, {9, "Fine weather"}, {10, "Cloudy weather"},
982 {11, "Shade"}, {12, "D 5700-7100K"}, {13, "N 4600-5500K"},
983 {14, "W 3800-4500K"}, {15, "WW 3250-3800K"}, {16, "L 2600-3260K"},
984 {17, "Standard light A"}, {18, "Standard light B"}, {19, "Standard light C"},
985 {20, "D55"}, {21, "D65"}, {22, "D75"}, {23, "D50"}, {24, "ISO studio tungsten"},
986 {255, "other"}
988 lookup_str_and_append_to_ucstring(name_map, ITEMS_IN_ARRAY(name_map), vp->n, vr->s);
989 return 1;
992 static int valdec_flash(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
994 i64 v;
996 ucstring_append_flags_item(vr->s, (vp->n&0x01)?"flash fired":"flash did not fire");
998 v = (vp->n&0x06)>>1;
999 if(v==0) ucstring_append_flags_item(vr->s, "no strobe return detection function");
1000 else if(v==2) ucstring_append_flags_item(vr->s, "strobe return light not detected");
1001 else if(v==3) ucstring_append_flags_item(vr->s, "strobe return light detected");
1003 v = (vp->n&0x18)>>3;
1004 if(v==1) ucstring_append_flags_item(vr->s, "compulsory flash firing");
1005 else if(v==2) ucstring_append_flags_item(vr->s, "compulsory flash suppression");
1006 else if(v==3) ucstring_append_flags_item(vr->s, "auto mode");
1008 ucstring_append_flags_item(vr->s, (vp->n&0x20)?"no flash function":"flash function present");
1010 if(vp->n&0x40) ucstring_append_flags_item(vr->s, "red eye reduction supported");
1012 if((vp->n & ~0x7f)!=0) {
1013 ucstring_append_flags_item(vr->s, "?");
1016 return 1;
1019 static int valdec_exifcolorspace(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
1021 static const struct int_and_str name_map[] = {
1022 {1, "sRGB"}, {0xffff, "Uncalibrated"}
1024 lookup_str_and_append_to_ucstring(name_map, ITEMS_IN_ARRAY(name_map), vp->n, vr->s);
1025 return 1;
1028 static int valdec_filesource(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
1030 static const struct int_and_str name_map[] = {
1031 {0, "others"}, {1, "scanner of transparent type"},
1032 {2, "scanner of reflex type"}, {3, "DSC"}
1034 lookup_str_and_append_to_ucstring(name_map, ITEMS_IN_ARRAY(name_map), vp->n, vr->s);
1035 return 1;
1038 static int valdec_scenetype(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
1040 static const struct int_and_str name_map[] = {
1041 {1, "directly photographed"}
1043 lookup_str_and_append_to_ucstring(name_map, ITEMS_IN_ARRAY(name_map), vp->n, vr->s);
1044 return 1;
1047 static int valdec_sensingmethod(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
1049 static const struct int_and_str name_map[] = {
1050 {1, "not defined"}, {2, "1-chip color area"}, {3, "2-chip color area"},
1051 {4, "3-chip color area"}, {5, "color sequential area"}, {7, "trilinear"},
1052 {8, "color sequential linear"}
1054 lookup_str_and_append_to_ucstring(name_map, ITEMS_IN_ARRAY(name_map), vp->n, vr->s);
1055 return 1;
1058 static int valdec_customrendered(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
1060 static const struct int_and_str name_map[] = {
1061 {0, "normal"}, {1, "custom"}
1063 lookup_str_and_append_to_ucstring(name_map, ITEMS_IN_ARRAY(name_map), vp->n, vr->s);
1064 return 1;
1067 static int valdec_exposuremode(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
1069 static const struct int_and_str name_map[] = {
1070 {0, "auto"}, {1, "manual"}, {2, "auto bracket"}
1072 lookup_str_and_append_to_ucstring(name_map, ITEMS_IN_ARRAY(name_map), vp->n, vr->s);
1073 return 1;
1076 static int valdec_whitebalance(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
1078 static const struct int_and_str name_map[] = {
1079 {0, "auto"}, {1, "manual"}
1081 lookup_str_and_append_to_ucstring(name_map, ITEMS_IN_ARRAY(name_map), vp->n, vr->s);
1082 return 1;
1085 static int valdec_scenecapturetype(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
1087 static const struct int_and_str name_map[] = {
1088 {0, "standard"}, {1, "landscape"}, {2, "portrait"}, {3, "night scene"}
1090 lookup_str_and_append_to_ucstring(name_map, ITEMS_IN_ARRAY(name_map), vp->n, vr->s);
1091 return 1;
1094 static int valdec_gaincontrol(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
1096 static const struct int_and_str name_map[] = {
1097 {0, "none"}, {1, "low gain up"}, {2, "high gain up"},
1098 {3, "low gain down"}, {4, "high gain down"}
1100 lookup_str_and_append_to_ucstring(name_map, ITEMS_IN_ARRAY(name_map), vp->n, vr->s);
1101 return 1;
1104 static int valdec_contrast(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
1106 static const struct int_and_str name_map[] = {
1107 {0, "normal"}, {1, "soft"}, {2, "hard"}
1109 lookup_str_and_append_to_ucstring(name_map, ITEMS_IN_ARRAY(name_map), vp->n, vr->s);
1110 return 1;
1113 static int valdec_saturation(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
1115 static const struct int_and_str name_map[] = {
1116 {0, "normal"}, {1, "low"}, {2, "high"}
1118 lookup_str_and_append_to_ucstring(name_map, ITEMS_IN_ARRAY(name_map), vp->n, vr->s);
1119 return 1;
1122 static int valdec_sharpness(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
1124 static const struct int_and_str name_map[] = {
1125 {0, "normal"}, {1, "soft"}, {2, "hard"}
1127 lookup_str_and_append_to_ucstring(name_map, ITEMS_IN_ARRAY(name_map), vp->n, vr->s);
1128 return 1;
1131 static int valdec_subjectdistancerange(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
1133 static const struct int_and_str name_map[] = {
1134 {0, "unknown"}, {1, "macro"}, {2, "close"}, {3, "distant"}
1136 lookup_str_and_append_to_ucstring(name_map, ITEMS_IN_ARRAY(name_map), vp->n, vr->s);
1137 return 1;
1140 static int valdec_profileembedpolicy(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
1142 static const struct int_and_str name_map[] = {
1143 {0, "allow copying"}, {1, "embed if used"}, {2, "embed never"}, {3, "no restrictions"}
1145 lookup_str_and_append_to_ucstring(name_map, ITEMS_IN_ARRAY(name_map), vp->n, vr->s);
1146 return 1;
1149 static int valdec_dngcolorspace(deark *c, const struct valdec_params *vp, struct valdec_result *vr)
1151 static const struct int_and_str name_map[] = {
1152 {0, "unknown"}, {1, "gray gamma 2.2"}, {2, "sRGB"}, {3, "Adobe RGB"},
1153 {4, "ProPhoto RGB"}
1155 lookup_str_and_append_to_ucstring(name_map, ITEMS_IN_ARRAY(name_map), vp->n, vr->s);
1156 return 1;
1159 static void handler_hexdump(deark *c, lctx *d, const struct taginfo *tg, const struct tagnuminfo *tni)
1161 de_dbg_hexdump(c, c->infile, tg->val_offset, tg->total_size, 256, NULL, 0x1);
1164 // Hex dump with no ASCII
1165 static void handler_hexdumpb(deark *c, lctx *d, const struct taginfo *tg, const struct tagnuminfo *tni)
1167 de_dbg_hexdump(c, c->infile, tg->val_offset, tg->total_size, 256, NULL, 0);
1170 static void handler_bplist(deark *c, lctx *d, const struct taginfo *tg, const struct tagnuminfo *tni)
1172 if(tg->total_size>=40 &&
1173 !dbuf_memcmp(c->infile, tg->val_offset, "bplist", 6))
1175 de_dbg(c, "binary .plist at %"I64_FMT", len=%"I64_FMT, tg->val_offset, tg->total_size);
1176 de_dbg_indent(c, 1);
1177 fmtutil_handle_plist(c, c->infile, tg->val_offset, tg->total_size, NULL, 0x0);
1178 de_dbg_indent(c, -1);
1180 else {
1181 handler_hexdump(c, d, tg, tni);
1185 static void handler_colormap(deark *c, lctx *d, const struct taginfo *tg, const struct tagnuminfo *tni)
1187 i64 num_entries;
1188 i64 i;
1189 struct page_ctx *pg = tg->pg;
1191 if(tg->datatype!=3) return;
1192 num_entries = tg->valcount / 3;
1193 de_dbg(c, "ColorMap with %d entries", (int)num_entries);
1194 for(i=0; i<num_entries; i++) {
1195 i64 r1, g1, b1;
1196 de_colorsample r2, g2, b2;
1197 de_color clr;
1198 char tmps[80];
1200 read_tag_value_as_int64(c, d, tg, num_entries*0 + i, &r1);
1201 read_tag_value_as_int64(c, d, tg, num_entries*1 + i, &g1);
1202 read_tag_value_as_int64(c, d, tg, num_entries*2 + i, &b1);
1203 r2 = (de_colorsample)(r1>>8);
1204 g2 = (de_colorsample)(g1>>8);
1205 b2 = (de_colorsample)(b1>>8);
1206 clr = DE_MAKE_RGB(r2, g2, b2);
1207 if(c->debug_level>=2) {
1208 de_snprintf(tmps, sizeof(tmps), "(%5d,%5d,%5d) "DE_CHAR_RIGHTARROW" ",
1209 (int)r1, (int)g1, (int)b1);
1210 de_dbg_pal_entry2(c, i, clr, tmps, NULL, NULL);
1212 if(i<256) {
1213 pg->pal[i] = clr;
1218 static void handler_subifd(deark *c, lctx *d, const struct taginfo *tg, const struct tagnuminfo *tni)
1220 i64 j;
1221 i64 tmpoffset;
1222 u8 ifdtype = IFDTYPE_NORMAL;
1224 if(d->fmt==DE_TIFFFMT_NIKONMN && tg->tagnum==0x11) ifdtype = IFDTYPE_NIKONPREVIEW;
1225 else if(tg->tagnum==330) ifdtype = IFDTYPE_SUBIFD;
1226 else if(tg->tagnum==400) ifdtype = IFDTYPE_GLOBALPARAMS;
1227 else if(tg->tagnum==34665) ifdtype = IFDTYPE_EXIF;
1228 else if(tg->tagnum==34731) ifdtype = IFDTYPE_MASKSUBIFD;
1229 else if(tg->tagnum==34853) ifdtype = IFDTYPE_GPS;
1230 else if(tg->tagnum==40965) ifdtype = IFDTYPE_EXIFINTEROP;
1232 for(j=0; j<tg->valcount;j++) {
1233 read_tag_value_as_int64(c, d, tg, j, &tmpoffset);
1234 de_dbg(c, "offset of %s: %d", tni->tagname, (int)tmpoffset);
1235 push_ifd(c, d, tmpoffset, ifdtype, 0);
1239 static void handler_xmp(deark *c, lctx *d, const struct taginfo *tg, const struct tagnuminfo *tni)
1241 dbuf_create_file_from_slice(c->infile, tg->val_offset, tg->total_size, "xmp", NULL, DE_CREATEFLAG_IS_AUX);
1244 static void handler_iptc(deark *c, lctx *d, const struct taginfo *tg, const struct tagnuminfo *tni)
1246 fmtutil_handle_iptc(c, c->infile, tg->val_offset, tg->total_size,
1247 d->is_deark_iptc?0x2:0x0);
1250 static void handler_photoshoprsrc(deark *c, lctx *d, const struct taginfo *tg, const struct tagnuminfo *tni)
1252 de_dbg(c, "Photoshop resources at %d, len=%d",
1253 (int)tg->val_offset, (int)tg->total_size);
1254 de_dbg_indent(c, 1);
1255 fmtutil_handle_photoshop_rsrc(c, c->infile, tg->val_offset, tg->total_size,
1256 d->is_deark_8bim?0x2:0x0);
1257 de_dbg_indent(c, -1);
1260 enum makernote_type {
1261 MAKERNOTE_UNKNOWN = 0,
1262 MAKERNOTE_NIKON,
1263 MAKERNOTE_APPLE_IOS,
1264 MAKERNOTE_FUJIFILM
1267 struct makernote_id_info {
1268 enum makernote_type mntype;
1269 char name[32];
1272 static void identify_makernote(deark *c, lctx *d, const struct taginfo *tg, struct makernote_id_info *mni)
1274 u8 buf[32];
1275 i64 amt_to_read;
1277 de_zeromem(buf, sizeof(buf));
1278 amt_to_read = sizeof(buf);
1279 if(amt_to_read > tg->total_size) amt_to_read = tg->total_size;
1280 de_read(buf, tg->val_offset, amt_to_read);
1282 if(!de_memcmp(buf, "Nikon\x00\x02", 7) &&
1283 (!de_memcmp(&buf[10], "\x4d\x4d\x00\x2a", 4) ||
1284 !de_memcmp(&buf[10], "\x49\x49\x2a\x00", 4)))
1286 // This is one Nikon MakerNote format. There are others.
1287 mni->mntype = MAKERNOTE_NIKON;
1288 de_strlcpy(mni->name, "Nikon type 3", sizeof(mni->name));
1289 goto done;
1291 else if(!de_memcmp(buf, "Apple iOS\x00\x00\x01\x4d\x4d", 14)) {
1292 mni->mntype = MAKERNOTE_APPLE_IOS;
1293 de_strlcpy(mni->name, "Apple iOS", sizeof(mni->name));
1294 goto done;
1296 else if(!de_memcmp(buf, "FUJIFILM", 8)) {
1297 mni->mntype = MAKERNOTE_FUJIFILM;
1298 de_strlcpy(mni->name, "FujiFilm", sizeof(mni->name));
1299 goto done;
1302 done:
1306 static void do_makernote_nikon(deark *c, lctx *d, i64 pos1, i64 len)
1308 i64 dpos;
1309 i64 dlen;
1310 unsigned int ver;
1312 if(len<10) return;
1313 ver = (unsigned int)de_getu16be(pos1+6);
1314 de_dbg(c, "version: 0x%04x", ver); // This is a guess
1316 dpos = pos1+10;
1317 dlen = len-10;
1318 if(dlen<8) return;
1319 de_dbg(c, "Nikon MakerNote tag data at %d, len=%d", (int)dpos, (int)dlen);
1320 de_dbg_indent(c, 1);
1321 de_run_module_by_id_on_slice2(c, "tiff", "N", c->infile, dpos, dlen);
1322 de_dbg_indent(c, -1);
1325 static void do_makernote_apple_ios(deark *c, lctx *d, i64 pos1, i64 len)
1327 unsigned int ver;
1329 if(len<12) return;
1330 ver = (unsigned int)de_getu16be(pos1+10);
1331 de_dbg(c, "version: 0x%04x", ver); // This is a guess
1332 if(ver!=1) return;
1333 if(len<20) return;
1335 // Apple iOS offsets are relative to the beginning of the "Apple iOS"
1336 // signature, so that's the data we'll pass to the submodule.
1337 de_dbg(c, "Apple MakerNote tag data at %"I64_FMT", len=%"I64_FMT, pos1, len);
1338 de_dbg_indent(c, 1);
1339 de_run_module_by_id_on_slice2(c, "tiff", "A", c->infile, pos1, len);
1340 de_dbg_indent(c, -1);
1343 static void do_makernote_fujifilm(deark *c, lctx *d, i64 pos1, i64 len)
1345 if(len<14) return;
1347 de_dbg(c, "FujiFilm MakerNote tag data at %"I64_FMT", len=%"I64_FMT, pos1, len);
1348 de_dbg_indent(c, 1);
1349 de_run_module_by_id_on_slice2(c, "tiff", "F", c->infile, pos1, len);
1350 de_dbg_indent(c, -1);
1353 static void handler_makernote(deark *c, lctx *d, const struct taginfo *tg, const struct tagnuminfo *tni)
1355 struct makernote_id_info *mni = NULL;
1357 mni = de_malloc(c, sizeof(struct makernote_id_info));
1358 identify_makernote(c, d, tg, mni);
1360 if(mni->mntype != 0) {
1361 de_dbg(c, "MakerNote identified as: %s", mni->name);
1364 if(mni->mntype==MAKERNOTE_NIKON) {
1365 do_makernote_nikon(c, d, tg->val_offset, tg->total_size);
1367 else if(mni->mntype==MAKERNOTE_APPLE_IOS) {
1368 do_makernote_apple_ios(c, d, tg->val_offset, tg->total_size);
1370 else if(mni->mntype==MAKERNOTE_FUJIFILM) {
1371 do_makernote_fujifilm(c, d, tg->val_offset, tg->total_size);
1373 else {
1374 handler_hexdump(c, d, tg, tni);
1377 de_free(c, mni);
1380 static void handler_usercomment(deark *c, lctx *d, const struct taginfo *tg, const struct tagnuminfo *tni)
1382 static u8 charcode[8];
1383 de_ucstring *s = NULL;
1384 de_encoding enc = DE_ENCODING_UNKNOWN;
1385 i64 bytes_per_char = 1;
1387 if(tg->datatype != DATATYPE_UNDEF) goto done;
1388 if(tg->total_size < 8) goto done;
1390 de_read(charcode, tg->val_offset, 8);
1392 if(!de_memcmp(charcode, "ASCII\0\0\0", 8)) {
1393 enc = DE_ENCODING_ASCII;
1395 else if(!de_memcmp(charcode, "UNICODE\0", 8)) {
1396 enc = d->is_le ? DE_ENCODING_UTF16LE : DE_ENCODING_UTF16BE;
1397 bytes_per_char = 2;
1400 if(enc == DE_ENCODING_UNKNOWN) goto done;
1402 s = ucstring_create(c);
1403 dbuf_read_to_ucstring_n(c->infile, tg->val_offset + 8, tg->total_size - 8,
1404 DE_TIFF_MAX_CHARS_TO_PRINT*bytes_per_char, s, 0, enc);
1406 // Should we truncate at NUL, or not? The Exif spec says "NULL termination
1407 // is not necessary", but it doesn't say whether it is *allowed*.
1408 // In practice, if we don't do this, we sometimes end up printing a lot of
1409 // garbage.
1410 ucstring_truncate_at_NUL(s);
1412 // FIXME: This is not quite right, though it's not important. We really
1413 // need to read the entire string, not just the first
1414 // DE_TIFF_MAX_CHARS_TO_PRINT bytes, in order to determine which characters
1415 // are trailing spaces.
1416 ucstring_strip_trailing_spaces(s);
1418 de_dbg(c, "%s: \"%s\"", tni->tagname, ucstring_getpsz(s));
1420 done:
1421 ucstring_destroy(s);
1424 static void handler_olepropset(deark *c, lctx *d, const struct taginfo *tg, const struct tagnuminfo *tni)
1426 de_dbg(c, "OLE property set storage dump at %"I64_FMT", len=%"I64_FMT,
1427 tg->val_offset, tg->total_size);
1428 de_dbg_indent(c, 1);
1429 de_run_module_by_id_on_slice2(c, "cfb", "T", c->infile, tg->val_offset, tg->total_size);
1430 de_dbg_indent(c, -1);
1433 // Photoshop "ImageSourceData"
1434 static void handler_37724(deark *c, lctx *d, const struct taginfo *tg, const struct tagnuminfo *tni)
1436 const char *codes;
1437 static const i64 siglen = 36;
1438 i64 dpos, dlen;
1439 int psdver = 0;
1441 if(tg->total_size<siglen) {
1444 else if(!dbuf_memcmp(c->infile, tg->val_offset, "Adobe Photoshop Document Data Block\0", (size_t)siglen)) {
1445 psdver = 1;
1447 else if(!dbuf_memcmp(c->infile, tg->val_offset, "Adobe Photoshop Document Data V0002\0", (size_t)siglen)) {
1448 psdver = 2;
1451 if(psdver==0) {
1452 detiff_warn(c, d, tg->pg, "Bad or unsupported ImageSourceData tag at %d", (int)tg->val_offset);
1453 goto done;
1456 de_dbg(c, "ImageSourceData signature at %d, PSD version=%d", (int)tg->val_offset, psdver);
1458 dpos = tg->val_offset + siglen;
1459 dlen = tg->total_size - siglen;
1460 de_dbg(c, "ImageSourceData blocks at %d, len=%d", (int)dpos, (int)dlen);
1462 codes = (psdver==2)? "B" : "T";
1463 de_dbg_indent(c, 1);
1464 de_run_module_by_id_on_slice2(c, "psd", codes, c->infile, dpos, dlen);
1465 de_dbg_indent(c, -1);
1466 done:
1470 static void handler_iccprofile(deark *c, lctx *d, const struct taginfo *tg, const struct tagnuminfo *tni)
1472 dbuf_create_file_from_slice(c->infile, tg->val_offset, tg->total_size, "icc", NULL, DE_CREATEFLAG_IS_AUX);
1475 static void handler_exifversion(deark *c, lctx *d, const struct taginfo *tg, const struct tagnuminfo *tni)
1477 // The only purpose of this handler is to possibly set d->exif_version_as_uint32,
1478 // for later use.
1479 if(tg->valcount!=4) return;
1480 if(tg->datatype!=DATATYPE_UNDEF) return;
1481 d->exif_version_as_uint32 = (u32)de_getu32be(tg->val_offset);
1484 struct mpfctx_struct {
1485 int warned;
1486 // per image:
1487 int is_thumb;
1488 i64 imgoffs_abs;
1489 i64 imgsize;
1492 static void try_to_extract_mpf_image(deark *c, lctx *d, struct page_ctx *pg,
1493 struct mpfctx_struct *mpfctx)
1495 dbuf *inf;
1497 de_dbg2(c, "[trying to extract image at %d, size=%d]", (int)mpfctx->imgoffs_abs,
1498 (int)mpfctx->imgsize);
1499 if(!d->in_params) goto done;
1500 if(!(d->in_params->flags&0x01)) goto done;
1501 if(!d->in_params->parent_dbuf) goto done;
1502 if(mpfctx->imgoffs_abs<1) goto done;
1503 inf = d->in_params->parent_dbuf;
1505 if(mpfctx->imgoffs_abs + mpfctx->imgsize > inf->len) {
1506 if(mpfctx->warned) goto done;
1507 mpfctx->warned = 1;
1508 detiff_warn(c, d, pg, "Invalid MPF multi-picture data. File size should be at "
1509 "least %"I64_FMT", is %"I64_FMT".",
1510 mpfctx->imgoffs_abs+mpfctx->imgsize, inf->len);
1511 goto done;
1514 if(dbuf_memcmp(inf, mpfctx->imgoffs_abs, "\xff\xd8\xff", 3)) {
1515 detiff_warn(c, d, pg, "Invalid or unsupported MPF multi-picture data. Expected image at "
1516 "%"I64_FMT" not found.", mpfctx->imgoffs_abs);
1517 goto done;
1520 dbuf_create_file_from_slice(inf, mpfctx->imgoffs_abs, mpfctx->imgsize,
1521 mpfctx->is_thumb?"mpfthumb.jpg":"mpf.jpg",
1522 NULL, DE_CREATEFLAG_IS_AUX);
1524 done:
1528 static void handler_mpentry(deark *c, lctx *d, const struct taginfo *tg, const struct tagnuminfo *tni)
1530 i64 num_entries;
1531 i64 k;
1532 i64 pos = tg->val_offset;
1533 de_ucstring *s = NULL;
1534 struct mpfctx_struct mpfctx;
1536 de_zeromem(&mpfctx, sizeof(struct mpfctx_struct));
1537 d->mpf_main_image_count = 0;
1538 // Length is supposed to be 16x{NumberOfImages; tag 45057}. We'll just assume
1539 // it's correct.
1540 num_entries = tg->total_size/16;
1542 s = ucstring_create(c);
1543 for(k=0; k<num_entries; k++) {
1544 i64 n;
1545 i64 imgoffs_rel, imgoffs_abs;
1546 i64 imgsize;
1547 u32 attrs;
1548 u32 dataformat;
1549 u32 typecode;
1550 char offset_descr[80];
1552 de_dbg(c, "entry #%d", (int)(k+1));
1553 de_dbg_indent(c, 1);
1555 attrs = (u32)dbuf_getu32x(c->infile, pos, d->is_le);
1556 dataformat = (attrs&0x07000000)>>24;
1557 typecode = attrs&0x00ffffff;
1558 ucstring_empty(s);
1559 if(attrs&0x80000000U) ucstring_append_flags_item(s, "dependent parent");
1560 if(attrs&0x40000000U) ucstring_append_flags_item(s, "dependent child");
1561 if(attrs&0x20000000U) ucstring_append_flags_item(s, "representative image");
1562 if(dataformat==0) ucstring_append_flags_item(s, "JPEG");
1563 if(typecode==0x030000U) ucstring_append_flags_item(s, "baseline MP primary image");
1564 if(typecode==0x010001U) ucstring_append_flags_item(s, "large thumbnail class 1");
1565 if(typecode==0x010002U) ucstring_append_flags_item(s, "large thumbnail class 2");
1566 if(typecode==0x020001U) ucstring_append_flags_item(s, "multi-frame image panorama");
1567 if(typecode==0x020002U) ucstring_append_flags_item(s, "multi-frame image disparity");
1568 if(typecode==0x020003U) ucstring_append_flags_item(s, "multi-frame image multi-angle");
1570 if(typecode==0x010001U || typecode==0x010002U) {
1571 mpfctx.is_thumb = 1;
1573 else {
1574 // Count that number of non-thumbnail images
1575 d->mpf_main_image_count++;
1576 mpfctx.is_thumb = 0;
1579 de_dbg(c, "image attribs: 0x%08x (%s)", (unsigned int)attrs,
1580 ucstring_getpsz(s));
1582 imgsize = dbuf_getu32x(c->infile, pos+4, d->is_le);
1583 de_dbg(c, "image size: %u", (unsigned int)imgsize);
1585 imgoffs_rel = dbuf_getu32x(c->infile, pos+8, d->is_le);
1586 // This is relative to beginning of the payload data (the TIFF header)
1587 // of the MPF segment, except that 0 is a special case.
1588 if(imgoffs_rel==0) {
1589 imgoffs_abs = 0;
1590 de_strlcpy(offset_descr, "refers to the first image", sizeof(offset_descr));
1592 else if(d->in_params && (d->in_params->flags&0x01)) {
1593 imgoffs_abs = d->in_params->offset_in_parent+imgoffs_rel;
1594 de_snprintf(offset_descr, sizeof(offset_descr), "absolute offset %"I64_FMT,
1595 imgoffs_abs);
1597 else {
1598 imgoffs_abs = imgoffs_rel;
1599 de_strlcpy(offset_descr, "?", sizeof(offset_descr));
1601 de_dbg(c, "image offset: %u (%s)", (unsigned int)imgoffs_rel, offset_descr);
1603 if(imgoffs_rel>0) {
1604 mpfctx.imgoffs_abs = imgoffs_abs;
1605 mpfctx.imgsize = imgsize;
1606 try_to_extract_mpf_image(c, d, tg->pg, &mpfctx);
1609 n = dbuf_getu16x(c->infile, pos+12, d->is_le);
1610 de_dbg(c, "dep. image #1 entry: %u", (unsigned int)n);
1611 n = dbuf_getu16x(c->infile, pos+14, d->is_le);
1612 de_dbg(c, "dep. image #2 entry: %u", (unsigned int)n);
1613 de_dbg_indent(c, -1);
1614 pos += 16;
1616 ucstring_destroy(s);
1619 static void handler_gpslatitude(deark *c, lctx *d, const struct taginfo *tg, const struct tagnuminfo *tni)
1621 // We look for this tag instead of GPS IFD or GPSVersionID, because we want
1622 // to know whether the file contains actual GPS coordinates. A lot of files
1623 // have a GPS IFD that contains nothing.
1624 d->has_exif_gps = 1;
1627 // This is for certain Microsoft tags that are apparently in UTF-16 format.
1628 // They use the BYTE data type (instead of the logical SHORT), and are always
1629 // little-endian, even in big-endian files.
1630 // They end with two 0 bytes. I don't know whether multiple strings can be stored
1631 // in one field (as in TIFF ASCII tags), but Microsoft appears to use semicolons
1632 // to separate multiple items, instead of U+0000 codes.
1633 static void handler_utf16(deark *c, lctx *d, const struct taginfo *tg, const struct tagnuminfo *tni)
1635 de_ucstring *s = NULL;
1637 if(tg->datatype!=DATATYPE_BYTE && tg->datatype!=DATATYPE_UNDEF) goto done;
1638 if(tg->total_size % 2) goto done; // Something's wrong if the byte count is odd.
1640 s = ucstring_create(c);
1641 dbuf_read_to_ucstring_n(c->infile, tg->val_offset, tg->total_size,
1642 DE_TIFF_MAX_CHARS_TO_PRINT*2, s, 0, DE_ENCODING_UTF16LE);
1643 ucstring_truncate_at_NUL(s);
1644 de_dbg(c, "UTF-16 string: \"%s\"", ucstring_getpsz(s));
1646 done:
1647 ucstring_destroy(s);
1648 return;
1651 static void handler_dngprivatedata(deark *c, lctx *d, const struct taginfo *tg, const struct tagnuminfo *tni)
1653 struct de_stringreaderdata *srd;
1654 i64 nbytes_to_scan;
1656 nbytes_to_scan = tg->total_size;
1657 if(nbytes_to_scan>128) nbytes_to_scan=128;
1659 srd = dbuf_read_string(c->infile, tg->val_offset, nbytes_to_scan, nbytes_to_scan,
1660 DE_CONVFLAG_STOP_AT_NUL, DE_ENCODING_ASCII);
1661 if(srd->found_nul) {
1662 de_dbg(c, "identifier: \"%s\"", ucstring_getpsz(srd->str));
1664 de_destroy_stringreaderdata(c, srd);
1667 static void handler_panasonicjpg(deark *c, lctx *d, const struct taginfo *tg, const struct tagnuminfo *tni)
1669 dbuf_create_file_from_slice(c->infile, tg->val_offset, tg->total_size,
1670 "thumb.jpg", NULL, DE_CREATEFLAG_IS_AUX);
1673 static void handler_leafdata(deark *c, lctx *d, const struct taginfo *tg, const struct tagnuminfo *tni)
1675 do_leaf_metadata(c, d, tg->val_offset, tg->total_size);
1678 static int alloc_striledata(deark *c, struct page_ctx *pg, i64 nstriles)
1680 if(nstriles<1) nstriles = 1;
1681 if(pg->strile_count >= nstriles) return 1;
1682 if(nstriles>DE_TIFF_MAX_STRILES) return 0;
1683 pg->strile_data = de_reallocarray(c, pg->strile_data, pg->strile_count, sizeof(struct strile_data_struct), nstriles);
1684 pg->strile_count = nstriles;
1685 return 1;
1688 static void handler_strileoffsets(deark *c, lctx *d, const struct taginfo *tg, const struct tagnuminfo *tni)
1690 struct page_ctx *pg = tg->pg;
1691 i64 i;
1693 if(tni->tagnum==TAG_TILEOFFSETS) {
1694 pg->have_tile_tags = 1;
1696 else {
1697 pg->have_strip_tags = 1;
1699 if(!alloc_striledata(c, pg, tg->valcount)) return;
1701 for(i=0; i<tg->valcount; i++) {
1702 read_tag_value_as_int64(c, d, tg, i, &pg->strile_data[i].pos);
1706 static void handler_strilebytecounts(deark *c, lctx *d, const struct taginfo *tg, const struct tagnuminfo *tni)
1708 struct page_ctx *pg = tg->pg;
1709 i64 i;
1711 if(tni->tagnum==TAG_TILEBYTECOUNTS) {
1712 pg->have_tile_tags = 1;
1714 else {
1715 pg->have_strip_tags = 1;
1717 if(!alloc_striledata(c, pg, tg->valcount)) return;
1719 for(i=0; i<tg->valcount; i++) {
1720 read_tag_value_as_int64(c, d, tg, i, &pg->strile_data[i].len);
1724 static void handler_bitspersample(deark *c, lctx *d, const struct taginfo *tg, const struct tagnuminfo *tni)
1726 i64 val;
1728 if(tg->valcount<1) return;
1730 // FIXME: This is a multi-valued field.
1731 read_tag_value_as_int64(c, d, tg, 0, &val);
1732 tg->pg->bits_per_sample = (u32)val;
1735 static void handler_extrasamples(deark *c, lctx *d, const struct taginfo *tg, const struct tagnuminfo *tni)
1737 struct page_ctx *pg = tg->pg;
1738 u8 i;
1740 pg->extrasamples_count = (u8)tg->valcount;
1741 if(pg->extrasamples_count>DE_TIFF_MAX_SAMPLES) {
1742 pg->extrasamples_count = DE_TIFF_MAX_SAMPLES;
1745 for(i=0; i<pg->extrasamples_count; i++) {
1746 i64 val;
1748 read_tag_value_as_int64(c, d, tg, 0, &val);
1749 pg->extrasample_type[(size_t)i] = (u8)val;
1753 static void handler_sampleformat(deark *c, lctx *d, const struct taginfo *tg, const struct tagnuminfo *tni)
1755 i64 val;
1757 if(tg->valcount<1) return;
1759 // FIXME: This is a multi-valued field.
1760 read_tag_value_as_int64(c, d, tg, 0, &val);
1761 tg->pg->sample_format = (u32)val;
1764 static void handler_resolution(deark *c, lctx *d, const struct taginfo *tg, const struct tagnuminfo *tni)
1766 struct numeric_value nv;
1768 if(tg->valcount<1) return;
1769 read_numeric_value(c, d, tg, 0, &nv, NULL);
1770 if(!nv.isvalid) return;
1771 tg->pg->have_density = 1;
1772 if(tg->tagnum==TAG_XRESOLUTION) {
1773 tg->pg->density_ImageWidth = nv.val_double;
1775 else if(tg->tagnum==TAG_YRESOLUTION) {
1776 tg->pg->density_ImageLength = nv.val_double;
1780 static i64 read_fixed_decimal(dbuf *f, i64 pos, size_t ndigits)
1782 i64 n;
1783 char buf[16];
1785 if(ndigits >= sizeof(buf)) return 0;
1786 dbuf_read(f, (u8*)buf, pos, ndigits);
1787 buf[ndigits] = '\0';
1788 n = de_atoi64(buf);
1789 return n;
1792 static void parse_tiff_datetime(deark *c, lctx *d, const struct taginfo *tg, struct de_timestamp *ts)
1794 i64 yr, mo, da;
1795 i64 hr, mi, se;
1797 if(tg->unit_size!=1) return;
1798 if(tg->valcount<19) return;
1799 // Format: "YYYY:MM:DD HH:MM:SS"
1800 yr = read_fixed_decimal(c->infile, tg->val_offset, 4);
1801 mo = read_fixed_decimal(c->infile, tg->val_offset+5, 2);
1802 da = read_fixed_decimal(c->infile, tg->val_offset+8, 2);
1803 hr = read_fixed_decimal(c->infile, tg->val_offset+11, 2);
1804 mi = read_fixed_decimal(c->infile, tg->val_offset+14, 2);
1805 se = read_fixed_decimal(c->infile, tg->val_offset+17, 2);
1806 de_make_timestamp(ts, yr, mo, da, hr, mi, se);
1807 if(ts->is_valid) {
1808 ts->tzcode = DE_TZCODE_UNKNOWN;
1809 ts->precision = DE_TSPREC_1SEC;
1813 static void handler_datetime(deark *c, lctx *d, const struct taginfo *tg, const struct tagnuminfo *tni)
1815 parse_tiff_datetime(c, d, tg, &tg->pg->internal_mod_time);
1818 // Handler for some tags expected to have a single integer value
1819 static void handler_various(deark *c, lctx *d, const struct taginfo *tg, const struct tagnuminfo *tni)
1821 struct page_ctx *pg = tg->pg;
1822 i64 val;
1824 if(tg->valcount<1) return;
1825 read_tag_value_as_int64(c, d, tg, 0, &val);
1827 switch(tg->tagnum) {
1828 case TAG_NEWSUBFILETYPE:
1829 if(val & 0x1) pg->is_thumb = 1;
1830 break;
1831 case TAG_OLDSUBFILETYPE:
1832 if(val==2) pg->is_thumb = 1;
1833 break;
1834 case TAG_IMAGEWIDTH:
1835 pg->have_imagewidth = 1;
1836 pg->imagewidth = val;
1837 break;
1838 case TAG_IMAGELENGTH:
1839 pg->imagelength = val;
1840 break;
1841 case TAG_COMPRESSION:
1842 pg->compression = (u32)val;
1843 break;
1844 case TAG_PHOTOMETRIC:
1845 pg->photometric = (u32)val;
1846 break;
1847 case TAG_FILLORDER:
1848 pg->fill_order = (u32)val;
1849 break;
1850 case TAG_SAMPLESPERPIXEL:
1851 pg->samples_per_pixel = (u32)val;
1852 break;
1853 case TAG_ROWSPERSTRIP:
1854 pg->have_strip_tags = 1;
1855 pg->rows_per_strip = val;
1856 break;
1857 case TAG_TILEWIDTH:
1858 pg->have_tile_tags = 1;
1859 pg->tile_width = val;
1860 break;
1861 case TAG_TILELENGTH:
1862 pg->have_tile_tags = 1;
1863 pg->tile_height = val;
1864 break;
1865 case TAG_ORIENTATION:
1866 if(val>=1 && val<=8) {
1867 pg->orientation = (u32)val;
1869 break;
1870 case TAG_PLANARCONFIG:
1871 pg->planarconfig = (u32)val;
1872 break;
1873 case TAG_T4OPTIONS:
1874 pg->t4options = (u32)val;
1875 break;
1876 case TAG_T6OPTIONS:
1877 pg->t6options = (u32)val;
1878 break;
1879 case TAG_RESOLUTIONUNIT:
1880 pg->resolution_unit = (u32)val;
1881 break;
1882 case TAG_PREDICTOR:
1883 pg->predictor = (u32)val;
1884 break;
1885 case TAG_JPEGINTERCHANGEFORMAT:
1886 pg->jpegoffset = val;
1887 break;
1888 case TAG_JPEGINTERCHANGEFORMATLENGTH:
1889 pg->have_jpeglength = 1;
1890 pg->jpeglength = val;
1891 break;
1892 case TAG_YCBCRPOSITIONING:
1893 pg->ycbcrpositioning = (u32)val;
1894 break;
1895 case TAG_JPEGTABLES:
1896 pg->have_jpegtables = 1;
1897 break;
1901 static const struct tagnuminfo tagnuminfo_arr[] = {
1902 { /* 254 */ TAG_NEWSUBFILETYPE, 0x00, "NewSubfileType", handler_various, valdec_newsubfiletype },
1903 { /* 255 */ TAG_OLDSUBFILETYPE, 0x00, "OldSubfileType", handler_various, valdec_oldsubfiletype },
1904 { /* 256 */ TAG_IMAGEWIDTH, 0x0000, "ImageWidth", handler_various, NULL },
1905 { /* 257 */ TAG_IMAGELENGTH, 0x0000, "ImageLength", handler_various, NULL },
1906 { /* 258 */ TAG_BITSPERSAMPLE, 0x00, "BitsPerSample", handler_bitspersample, NULL },
1907 { /* 259 */ TAG_COMPRESSION, 0x0000, "Compression", handler_various, valdec_compression },
1908 { /* 262 */ TAG_PHOTOMETRIC, 0x00, "PhotometricInterpretation", handler_various, valdec_photometric },
1909 { 263, 0x00, "Threshholding", NULL, valdec_threshholding },
1910 { 264, 0x00, "CellWidth", NULL, NULL },
1911 { 265, 0x00, "CellLength", NULL, NULL },
1912 { /* 266 */ TAG_FILLORDER, 0x00, "FillOrder", handler_various, valdec_fillorder },
1913 { 269, 0x0400, "DocumentName", NULL, NULL },
1914 { 270, 0x0400, "ImageDescription", NULL, NULL },
1915 { 271, 0x0400, "Make", NULL, NULL },
1916 { 272, 0x0400, "Model", NULL, NULL },
1917 { /* 273 */ TAG_STRIPOFFSETS, 0x00, "StripOffsets", handler_strileoffsets, NULL },
1918 { /* 274 */ TAG_ORIENTATION, 0x0000, "Orientation", handler_various, valdec_orientation },
1919 { /* 277 */ TAG_SAMPLESPERPIXEL, 0x00, "SamplesPerPixel", handler_various, NULL },
1920 { /* 278 */ TAG_ROWSPERSTRIP, 0x00, "RowsPerStrip", handler_various, NULL },
1921 { /* 279 */ TAG_STRIPBYTECOUNTS, 0x00, "StripByteCounts", handler_strilebytecounts, NULL },
1922 { 280, 0x00, "MinSampleValue", NULL, NULL },
1923 { 281, 0x00, "MaxSampleValue", NULL, NULL },
1924 { /* 282 */ TAG_XRESOLUTION, 0x00, "XResolution", handler_resolution, NULL },
1925 { /* 283 */ TAG_YRESOLUTION, 0x00, "YResolution", handler_resolution, NULL },
1926 { /* 284 */ TAG_PLANARCONFIG, 0x00, "PlanarConfiguration", handler_various, valdec_planarconfiguration },
1927 { 285, 0x0400, "PageName", NULL, NULL },
1928 { 286, 0x00, "XPosition", NULL, NULL },
1929 { 287, 0x00, "YPosition", NULL, NULL },
1930 { 288, 0x00, "FreeOffsets", NULL, NULL },
1931 { 289, 0x00, "FreeByteCounts", NULL, NULL },
1932 { 290, 0x00, "GrayResponseUnit", NULL, NULL },
1933 { 291, 0x00, "GrayResponseCurve", NULL, NULL },
1934 { /* 292 */ TAG_T4OPTIONS, 0x00, "T4Options", handler_various, valdec_t4options },
1935 { /* 293 */ TAG_T6OPTIONS, 0x00, "T6Options", handler_various, valdec_t6options },
1936 { /* 296 */ TAG_RESOLUTIONUNIT, 0x00, "ResolutionUnit", handler_various, valdec_resolutionunit },
1937 { 297, 0x0400, "PageNumber", NULL, valdec_pagenumber },
1938 { 300, 0x0000, "ColorResponseUnit", NULL, NULL },
1939 { 301, 0x00, "TransferFunction", NULL, NULL },
1940 { 305, 0x0400, "Software", NULL, NULL },
1941 { /* 306 */ TAG_DATETIME, 0x0400, "DateTime", handler_datetime, NULL },
1942 { 315, 0x0400, "Artist", NULL, NULL },
1943 { 316, 0x0400, "HostComputer", NULL, NULL },
1944 { /* 317 */ TAG_PREDICTOR, 0x00, "Predictor", handler_various, valdec_predictor },
1945 { 318, 0x00, "WhitePoint", NULL, NULL },
1946 { 319, 0x00, "PrimaryChromaticities", NULL, NULL },
1947 { 320, 0x08, "ColorMap", handler_colormap, NULL },
1948 { 321, 0x00, "HalftoneHints", NULL, NULL },
1949 { /* 322 */ TAG_TILEWIDTH, 0x00, "TileWidth", handler_various, NULL },
1950 { /* 323 */ TAG_TILELENGTH, 0x00, "TileLength", handler_various, NULL },
1951 { /* 324 */ TAG_TILEOFFSETS, 0x00, "TileOffsets", handler_strileoffsets, NULL },
1952 { /* 325 */ TAG_TILEBYTECOUNTS, 0x00, "TileByteCounts", handler_strilebytecounts, NULL },
1953 { 326, 0x00, "BadFaxLines", NULL, NULL },
1954 { 327, 0x00, "CleanFaxData", NULL, NULL },
1955 { 328, 0x00, "ConsecutiveBadFaxLines", NULL, NULL },
1956 { 330, 0x08, "SubIFD", handler_subifd, NULL },
1957 { 332, 0x0000, "InkSet", NULL, valdec_inkset },
1958 { 333, 0x0004, "InkNames", NULL, NULL },
1959 { 334, 0x00, "NumberOfInks", NULL, NULL },
1960 { 336, 0x00, "DotRange", NULL, NULL },
1961 { 337, 0x00, "TargetPrinter", NULL, NULL },
1962 { 338, 0x00, "ExtraSamples", handler_extrasamples, valdec_extrasamples },
1963 { /* 339 */ TAG_SAMPLEFORMAT, 0x00, "SampleFormat", handler_sampleformat, valdec_sampleformat },
1964 { 340, 0x00, "SMinSampleValue", NULL, NULL },
1965 { 341, 0x00, "SMaxSampleValue", NULL, NULL },
1966 { 342, 0x00, "TransferRange", NULL, NULL },
1967 { 343, 0x0000, "ClipPath", NULL, NULL },
1968 { 344, 0x0000, "XClipPathUnits", NULL, NULL },
1969 { 345, 0x0000, "YClipPathUnits", NULL, NULL },
1970 { 346, 0x0000, "Indexed", NULL, NULL },
1971 { /* 347 */ TAG_JPEGTABLES, 0x00, "JPEGTables", handler_various, NULL },
1972 { 351, 0x0000, "OPIProxy", NULL, NULL },
1973 { 400, 0x0008, "GlobalParametersIFD", handler_subifd, NULL },
1974 { 401, 0x0000, "ProfileType", NULL, NULL },
1975 { 402, 0x0000, "FaxProfile", NULL, NULL },
1976 { 403, 0x0000, "CodingMethods", NULL, NULL },
1977 { 404, 0x0000, "VersionYear", NULL, NULL },
1978 { 405, 0x0000, "ModeNumber", NULL, NULL },
1979 { 433, 0x0000, "Decode", NULL, NULL },
1980 { 434, 0x0000, "DefaultImageColor", NULL, NULL },
1981 { 435, 0x0000, "T82Options", NULL, NULL },
1982 { 512, 0x00, "JPEGProc", NULL, valdec_jpegproc },
1983 { /* 513 */ TAG_JPEGINTERCHANGEFORMAT, 0x0000, "JPEGInterchangeFormat", handler_various, NULL },
1984 { /* 514 */ TAG_JPEGINTERCHANGEFORMATLENGTH, 0x0000, "JPEGInterchangeFormatLength", handler_various, NULL },
1985 { 515, 0x00, "JPEGRestartInterval", NULL, NULL },
1986 { 517, 0x00, "JPEGLosslessPredictors", NULL, NULL },
1987 { 518, 0x00, "JPEGPointTransforms", NULL, NULL },
1988 { 519, 0x00, "JPEGQTables", NULL, NULL },
1989 { 520, 0x00, "JPEGDCTables", NULL, NULL },
1990 { 521, 0x00, "JPEGACTables", NULL, NULL },
1991 { 529, 0x00, "YCbCrCoefficients", NULL, NULL },
1992 { 530, 0x00, "YCbCrSubSampling", NULL, NULL },
1993 { /* 531 */ TAG_YCBCRPOSITIONING, 0x0000, "YCbCrPositioning", handler_various, valdec_ycbcrpositioning },
1994 { 532, 0x00, "ReferenceBlackWhite", NULL, NULL },
1995 { 559, 0x0000, "StripRowCounts", NULL, NULL },
1996 { 700, 0x0408, "XMP", handler_xmp, NULL },
1997 { 769, 0x0010, "PropertyTagGamma", NULL, NULL },
1998 { 770, 0x0010, "PropertyTagICCProfileDescriptor", NULL, NULL },
1999 { 771, 0x0010, "PropertyTagSRGBRenderingIntent", NULL, NULL },
2000 //{ 999, 0x0000, "USPTOMiscellaneous", NULL, NULL },
2001 { 18246, 0x0400, "RatingStars", NULL, NULL },
2002 { 18247, 0x0000, "XP_DIP_XML", NULL, NULL },
2003 { 18248, 0x0000, "StitchInfo", NULL, NULL },
2004 { 18249, 0x0400, "RatingValue", NULL, NULL },
2005 { 20752, 0x0010, "PropertyTagPixelUnit", NULL, NULL },
2006 { 20753, 0x0010, "PropertyTagPixelPerUnitX", NULL, NULL },
2007 { 20754, 0x0010, "PropertyTagPixelPerUnitY", NULL, NULL },
2008 //{ 28672, 0x0000, "SonyRawFileType", NULL, NULL },
2009 //{ 28725, 0x0000, "ChromaticAberrationCorrParams", NULL, NULL },
2010 //{ 28727, 0x0000, "DistortionCorrParams", NULL, NULL },
2011 { 32781, 0x0000, "ImageID", NULL, NULL },
2012 { 32932, 0x0000, "Wang Annotation", NULL, NULL },
2013 { 32934, 0x0000, "Wang PageControl", NULL, NULL },
2014 { 32953, 0x0000, "ImageReferencePoints", NULL, NULL },
2015 { 32954, 0x0000, "RegionXformTackPoint", NULL, NULL },
2016 { 32955, 0x0000, "RegionWarpCorners", NULL, NULL },
2017 { 32956, 0x0000, "RegionAffine", NULL, NULL },
2018 { 32995, 0x00, "Matteing(SGI)", NULL, NULL },
2019 { 32996, 0x00, "DataType(SGI)", NULL, NULL },
2020 { 32997, 0x00, "ImageDepth(SGI)", NULL, NULL },
2021 { 32998, 0x00, "TileDepth(SGI)", NULL, NULL },
2022 { 33300, 0x0000, "Pixar ImageFullWidth", NULL, NULL },
2023 { 33301, 0x0000, "Pixar ImageFullLength", NULL, NULL },
2024 { 33302, 0x0000, "Pixar TextureFormat", NULL, NULL },
2025 { 33303, 0x0000, "Pixar WrapModes", NULL, NULL },
2026 { 33304, 0x0000, "Pixar FOVCOT", NULL, NULL },
2027 { 33305, 0x0000, "Pixar MatrixWorldToScreen", NULL, NULL },
2028 { 33306, 0x0000, "Pixar MatrixWorldToCamera", NULL, NULL },
2029 { 33405, 0x0000, "Model2", NULL, NULL },
2030 { 33421, 0x0100, "CFARepeatPatternDim", NULL, NULL },
2031 { 33422, 0x0100, "CFAPattern", NULL, NULL },
2032 { 33423, 0x0100, "BatteryLevel", NULL, NULL },
2033 //{ 33424, 0x0000, "KodakIFD", NULL, NULL },
2034 { 33432, 0x0404, "Copyright", NULL, NULL },
2035 { 33434, 0x10, "ExposureTime", NULL, NULL },
2036 { 33437, 0x10, "FNumber", NULL, NULL },
2037 { 33445, 0x0000, "MD FileTag", NULL, NULL },
2038 { 33446, 0x0000, "MD ScalePixel", NULL, NULL },
2039 { 33447, 0x0000, "MD ColorTable", NULL, NULL },
2040 { 33448, 0x0000, "MD LabName", NULL, NULL },
2041 { 33449, 0x0000, "MD SampleInfo", NULL, NULL },
2042 { 33450, 0x0000, "MD PrepDate", NULL, NULL },
2043 { 33451, 0x0000, "MD PrepTime", NULL, NULL },
2044 { 33452, 0x0000, "MD FileUnits", NULL, NULL },
2045 { 33550, 0x0000, "ModelPixelScaleTag", NULL, NULL },
2046 { 33589, 0x0000, "AdventScale", NULL, NULL },
2047 { 33590, 0x0000, "AdventRevision", NULL, NULL },
2048 // 33628-33631: UICTags
2049 { 33723, 0x0408, "IPTC", handler_iptc, NULL },
2050 { 33918, 0x0000, "INGR Packet Data", NULL, NULL },
2051 { 33919, 0x0000, "INGR Flag Registers", NULL, NULL },
2052 { 33920, 0x0000, "IrasB Transformation Matrix", NULL, NULL },
2053 { 33922, 0x0000, "ModelTiepointTag", NULL, NULL },
2054 { 34016, 0x0200, "Site", NULL, NULL },
2055 { 34017, 0x0200, "ColorSequence", NULL, NULL },
2056 { 34018, 0x0200, "IT8Header", NULL, NULL },
2057 { 34019, 0x0200, "RasterPadding", NULL, NULL },
2058 { 34020, 0x0200, "BitsPerRunLength", NULL, NULL },
2059 { 34021, 0x0200, "BitsPerExtendedRunLength", NULL, NULL },
2060 { 34022, 0x0200, "ColorTable", NULL, NULL },
2061 { 34023, 0x0200, "ImageColorIndicator", NULL, NULL },
2062 { 34024, 0x0200, "BackgroundColorIndicator", NULL, NULL },
2063 { 34025, 0x0200, "ImageColorValue", NULL, NULL },
2064 { 34026, 0x0200, "BackgroundColorValue", NULL, NULL },
2065 { 34027, 0x0200, "PixelIntensityRange", NULL, NULL },
2066 { 34028, 0x0200, "TransparencyIndicator", NULL, NULL },
2067 { 34029, 0x0200, "ColorCharacterization", NULL, NULL },
2068 { 34030, 0x0200, "HCUsage", NULL, NULL },
2069 { 34031, 0x0200, "TrapIndicator", NULL, NULL },
2070 { 34032, 0x0200, "CMYKEquivalent", NULL, NULL },
2071 { 34118, 0x0000, "SEMInfo", NULL, NULL },
2072 { 34152, 0x0000, "AFCP_IPTC", NULL, NULL },
2073 // Contradictory info about 34232
2074 { 34232, 0x0000, "FrameCount or PixelMagicJBIGOptions", NULL, NULL },
2075 { 34263, 0x0000, "JPLCartoIFD", NULL, NULL },
2076 { 34264, 0x0000, "ModelTransformationTag", NULL, NULL },
2077 //{ 34306, 0x0000, "WB_GRGBLevels", NULL, NULL },
2078 { 34310, 0x0008, "LeafData", handler_leafdata, NULL },
2079 { 34377, 0x0408, "PhotoshopImageResources", handler_photoshoprsrc, NULL },
2080 { 34665, 0x0408, "Exif IFD", handler_subifd, NULL },
2081 { 34675, 0x0408, "ICC Profile", handler_iccprofile, NULL },
2082 //{ 34687, 0x0000, "TIFF_FXExtensions", NULL, NULL },
2083 //{ 34688, 0x0000, "MultiProfiles", NULL, NULL, NULL },
2084 //{ 34689, 0x0000, "SharedData", NULL, NULL, NULL },
2085 //{ 34690, 0x0000, "T88Options", NULL, NULL, NULL },
2086 { 34730, 0x0000, "Annotation Offsets", NULL, NULL },
2087 { 34731, 0x0008, "Mask SubIFDs", handler_subifd, NULL },
2088 { 34732, 0x0000, "ImageLayer", NULL, NULL },
2089 { 34735, 0x0000, "GeoKeyDirectoryTag", NULL, NULL },
2090 { 34736, 0x0000, "GeoDoubleParamsTag", NULL, NULL },
2091 { 34737, 0x0000, "GeoAsciiParamsTag", NULL, NULL },
2092 { 34750, 0x0000, "JBIGOptions", NULL, NULL },
2093 { 34850, 0x10, "ExposureProgram", NULL, valdec_exposureprogram },
2094 { 34852, 0x10, "SpectralSensitivity", NULL, NULL },
2095 { 34853, 0x0408, "GPS IFD", handler_subifd, NULL },
2096 { 34855, 0x10, "PhotographicSensitivity/ISOSpeedRatings", NULL, NULL },
2097 { 34856, 0x0018, "OECF", handler_hexdump, NULL },
2098 { 34857, 0x0100, "Interlace", NULL, NULL },
2099 { 34858, 0x0100, "TimeZoneOffset", NULL, NULL },
2100 { 34859, 0x0100, "SelfTimerMode", NULL, NULL },
2101 { 34864, 0x10, "SensitivityType", NULL, NULL },
2102 { 34865, 0x10, "StandardOutputSensitivity", NULL, NULL },
2103 { 34866, 0x10, "RecommendedExposureIndex", NULL, NULL },
2104 { 34867, 0x10, "ISOSpeed", NULL, NULL },
2105 { 34868, 0x10, "ISOSpeedLatitudeyyy", NULL, NULL },
2106 { 34869, 0x10, "ISOSpeedLatitudezzz", NULL, NULL },
2107 { 34908, 0x00, "FaxRecvParams", NULL, NULL },
2108 { 34909, 0x00, "FaxSubAddress", NULL, NULL },
2109 { 34910, 0x0000, "FaxRecvTime", NULL, NULL },
2110 { 34911, 0x0000, "FaxDCS", NULL, NULL },
2111 { 34929, 0x0000, "FEDEX_EDR", NULL, NULL },
2112 //{ 34954, 0x0000, "LeafSubIFD", NULL, NULL },
2113 { 36864, 0x10, "ExifVersion", handler_exifversion, NULL },
2114 { 36867, 0x10, "DateTimeOriginal", NULL, NULL },
2115 { 36868, 0x10, "DateTimeDigitized", NULL, NULL },
2116 { 36880, 0x0010, "OffsetTime", NULL, NULL },
2117 { 36881, 0x0010, "OffsetTimeOriginal", NULL, NULL },
2118 { 36882, 0x0010, "OffsetTimeDigitized", NULL, NULL },
2119 { 37121, 0x10, "ComponentsConfiguration", NULL, valdec_componentsconfiguration },
2120 { 37122, 0x10, "CompressedBitsPerPixel", NULL, NULL },
2121 { 37377, 0x10, "ShutterSpeedValue", NULL, NULL },
2122 { 37378, 0x10, "ApertureValue", NULL, NULL },
2123 { 37379, 0x10, "BrightnessValue", NULL, NULL },
2124 { 37380, 0x10, "ExposureBiasValue", NULL, NULL },
2125 { 37381, 0x10, "MaxApertureValue", NULL, NULL },
2126 { 37382, 0x10, "SubjectDistance", NULL, NULL },
2127 { 37383, 0x10, "MeteringMode", NULL, valdec_meteringmode },
2128 { 37384, 0x10, "LightSource", NULL, valdec_lightsource },
2129 { 37385, 0x10, "Flash", NULL, valdec_flash },
2130 { 37386, 0x10, "FocalLength", NULL, NULL },
2131 { 37387, 0x0100, "FlashEnergy", NULL, NULL },
2132 { 37388, 0x0100, "SpatialFrequencyResponse", NULL, NULL },
2133 { 37389, 0x0100, "Noise", NULL, NULL },
2134 { 37390, 0x0100, "FocalPlaneXResolution", NULL, NULL },
2135 { 37391, 0x0100, "FocalPlaneYResolution", NULL, NULL },
2136 { 37392, 0x0100, "FocalPlaneResolutionUnit", NULL, NULL },
2137 { 37393, 0x0100, "ImageNumber", NULL, NULL },
2138 { 37394, 0x0100, "SecurityClassification", NULL, NULL },
2139 { 37395, 0x0100, "ImageHistory", NULL, NULL },
2140 { 37396, 0x10, "SubjectArea", NULL, NULL },
2141 { 37397, 0x0100, "ExposureIndex", NULL, NULL },
2142 { 37398, 0x0100, "TIFF/EPStandardID", NULL, NULL },
2143 { 37399, 0x0100, "SensingMethod", NULL, NULL },
2144 { 37439, 0x00, "SToNits(SGI)", NULL, NULL },
2145 { 37500, 0x0018, "MakerNote", handler_makernote, NULL },
2146 { 37510, 0x10, "UserComment", handler_usercomment, NULL },
2147 { 37520, 0x10, "SubSec", NULL, NULL },
2148 { 37521, 0x10, "SubSecTimeOriginal", NULL, NULL },
2149 { 37522, 0x10, "SubsecTimeDigitized", NULL, NULL },
2150 { 37679, 0x0000, "OCR Text", NULL, NULL },
2151 { 37680, 0x0008, "OLE Property Set Storage", handler_olepropset, NULL },
2152 { 37681, 0x0000, "OCR Text Position Info", NULL, NULL },
2153 { 37724, 0x0008, "Photoshop ImageSourceData", handler_37724, NULL },
2154 { 37888, 0x0010, "Temperature", NULL, NULL },
2155 { 37889, 0x0010, "Humidity", NULL, NULL },
2156 { 37890, 0x0010, "Pressure", NULL, NULL },
2157 { 37891, 0x0010, "WaterDepth", NULL, NULL },
2158 { 37892, 0x0010, "Acceleration", NULL, NULL },
2159 { 37893, 0x0010, "CameraElevationAngle", NULL, NULL },
2160 { 40091, 0x0408, "XPTitle/Caption", handler_utf16, NULL },
2161 { 40092, 0x0008, "XPComment", handler_utf16, NULL },
2162 { 40093, 0x0008, "XPAuthor", handler_utf16, NULL },
2163 { 40094, 0x0008, "XPKeywords", handler_utf16, NULL },
2164 { 40095, 0x0008, "XPSubject", handler_utf16, NULL },
2165 { 40960, 0x10, "FlashPixVersion", NULL, NULL },
2166 { 40961, 0x0410, "ColorSpace", NULL, valdec_exifcolorspace },
2167 { 40962, 0x10, "PixelXDimension", NULL, NULL },
2168 { 40963, 0x10, "PixelYDimension", NULL, NULL },
2169 { 40964, 0x10, "RelatedSoundFile", NULL, NULL },
2170 { 40965, 0x0418, "Interoperability IFD", handler_subifd, NULL },
2171 { 41483, 0x10, "FlashEnergy", NULL, NULL },
2172 { 41484, 0x0018, "SpatialFrequencyResponse", handler_hexdump, NULL },
2173 { 41486, 0x10, "FocalPlaneXResolution", NULL, NULL },
2174 { 41487, 0x10, "FocalPlaneYResolution", NULL, NULL },
2175 { 41488, 0x10, "FocalPlaneResolutionUnit", NULL, valdec_resolutionunit },
2176 { 41492, 0x10, "SubjectLocation", NULL, NULL },
2177 { 41493, 0x10, "ExposureIndex", NULL, NULL },
2178 { 41495, 0x10, "SensingMethod", NULL, valdec_sensingmethod },
2179 { 41728, 0x10, "FileSource", NULL, valdec_filesource },
2180 { 41729, 0x10, "SceneType", NULL, valdec_scenetype },
2181 { 41730, 0x10, "CFAPattern", NULL, NULL },
2182 { 41985, 0x10, "CustomRendered", NULL, valdec_customrendered },
2183 { 41986, 0x10, "ExposureMode", NULL, valdec_exposuremode },
2184 { 41987, 0x10, "WhiteBalance", NULL, valdec_whitebalance },
2185 { 41988, 0x10, "DigitalZoomRatio", NULL, NULL },
2186 { 41989, 0x10, "FocalLengthIn35mmFilm", NULL, NULL },
2187 { 41990, 0x10, "SceneCaptureType", NULL, valdec_scenecapturetype },
2188 { 41991, 0x10, "GainControl", NULL, valdec_gaincontrol },
2189 { 41992, 0x10, "Contrast", NULL, valdec_contrast },
2190 { 41993, 0x10, "Saturation", NULL, valdec_saturation },
2191 { 41994, 0x10, "Sharpness", NULL, valdec_sharpness },
2192 { 41995, 0x0018, "DeviceSettingDescription", handler_hexdump, NULL },
2193 { 41996, 0x10, "SubjectDistanceRange", NULL, valdec_subjectdistancerange },
2194 { 42016, 0x10, "ImageUniqueID", NULL, NULL },
2195 { 42032, 0x10, "CameraOwnerName", NULL, NULL },
2196 { 42033, 0x10, "BodySerialNumber", NULL, NULL },
2197 { 42034, 0x10, "LensSpecification", NULL, NULL },
2198 { 42035, 0x10, "LensMake", NULL, NULL },
2199 { 42036, 0x10, "LensModel", NULL, NULL },
2200 { 42037, 0x10, "LensSerialNumber", NULL, NULL },
2201 { 42112, 0x0000, "GDAL_METADATA", NULL, NULL },
2202 { 42113, 0x0000, "GDAL_NODATA", NULL, NULL },
2203 { 42240, 0x10, "Gamma", NULL, NULL },
2204 { 45056, 0x0801, "MPFVersion", NULL, NULL },
2205 { 45057, 0x0801, "NumberOfImages", NULL, NULL },
2206 { 45058, 0x0809, "MPEntry", handler_mpentry, NULL },
2207 { 45059, 0x0801, "ImageUIDList", NULL, NULL },
2208 { 45060, 0x0801, "TotalFrames", NULL, NULL },
2209 { 45313, 0x0801, "MPIndividualNum", NULL, NULL },
2210 { 45569, 0x0801, "PanOrientation", NULL, NULL },
2211 { 45570, 0x0801, "PanOverlap_H", NULL, NULL },
2212 { 45571, 0x0801, "PanOverlap_V", NULL, NULL },
2213 { 45572, 0x0801, "BaseViewpointNum", NULL, NULL },
2214 { 45573, 0x0801, "ConvergenceAngle", NULL, NULL },
2215 { 45574, 0x0801, "BaselineLength", NULL, NULL },
2216 { 45575, 0x0801, "VerticalDivergence", NULL, NULL },
2217 { 45576, 0x0801, "AxisDistance_X", NULL, NULL },
2218 { 45577, 0x0801, "AxisDistance_Y", NULL, NULL },
2219 { 45578, 0x0801, "AxisDistance_Z", NULL, NULL },
2220 { 45579, 0x0801, "YawAngle", NULL, NULL },
2221 { 45580, 0x0801, "PitchAngle", NULL, NULL },
2222 { 45581, 0x0801, "RollAngle", NULL, NULL },
2223 { 48129, 0x0401, "PIXEL_FORMAT", NULL, NULL },
2224 { 48130, 0x0401, "SPATIAL_XFRM_PRIMARY", NULL, NULL },
2225 { 48131, 0x0401, "Uncompressed", NULL, NULL },
2226 { 48132, 0x0401, "IMAGE_TYPE", NULL, NULL },
2227 { 48133, 0x0401, "PTM_COLOR_INFO", NULL, NULL },
2228 { 48134, 0x0401, "PROFILE_LEVEL_CONTAINER", NULL, NULL },
2229 { 48256, 0x0401, "IMAGE_WIDTH", NULL, NULL },
2230 { 48257, 0x0401, "IMAGE_HEIGHT", NULL, NULL },
2231 { 48258, 0x0401, "WIDTH_RESOLUTION", NULL, NULL },
2232 { 48259, 0x0401, "HEIGHT_RESOLUTION", NULL, NULL },
2233 { 48320, 0x0401, "IMAGE_OFFSET", NULL, NULL },
2234 { 48321, 0x0401, "IMAGE_BYTE_COUNT", NULL, NULL },
2235 { 48322, 0x0401, "ALPHA_OFFSET", NULL, NULL },
2236 { 48323, 0x0401, "ALPHA_BYTE_COUNT", NULL, NULL },
2237 { 48324, 0x0401, "IMAGE_BAND_PRESENCE", NULL, NULL },
2238 { 48325, 0x0401, "ALPHA_BAND_PRESENCE", NULL, NULL },
2239 { 50215, 0x0000, "Oce Scanjob Description", NULL, NULL },
2240 { 50216, 0x0000, "Oce Application Selector", NULL, NULL },
2241 { 50217, 0x0000, "Oce Identification Number", NULL, NULL },
2242 { 50218, 0x0000, "Oce ImageLogic Characteristics", NULL, NULL },
2243 { 50341, 0x0008, "PrintImageMatching", handler_hexdump, NULL },
2244 { 50706, 0x80, "DNGVersion", NULL, NULL},
2245 { 50707, 0x80, "DNGBackwardVersion", NULL, NULL},
2246 { 50708, 0x80, "UniqueCameraModel", NULL, NULL},
2247 { 50709, 0x80, "LocalizedCameraModel", NULL, NULL},
2248 { 50710, 0x80, "CFAPlaneColor", NULL, NULL},
2249 { 50711, 0x80, "CFALayout", NULL, NULL},
2250 { 50712, 0x80, "LinearizationTable", NULL, NULL},
2251 { 50713, 0x80, "BlackLevelRepeatDim", NULL, NULL},
2252 { 50714, 0x80, "BlackLevel", NULL, NULL},
2253 { 50715, 0x80, "BlackLevelDeltaH", NULL, NULL},
2254 { 50716, 0x80, "BlackLevelDeltaV", NULL, NULL},
2255 { 50717, 0x80, "WhiteLevel", NULL, NULL},
2256 { 50718, 0x80, "DefaultScale", NULL, NULL},
2257 { 50719, 0x80, "DefaultCropOrigin", NULL, NULL},
2258 { 50720, 0x80, "DefaultCropSize", NULL, NULL},
2259 { 50721, 0x80, "ColorMatrix1", NULL, NULL},
2260 { 50722, 0x80, "ColorMatrix2", NULL, NULL},
2261 { 50723, 0x80, "CameraCalibration1", NULL, NULL},
2262 { 50724, 0x80, "CameraCalibration2", NULL, NULL},
2263 { 50725, 0x80, "ReductionMatrix1", NULL, NULL},
2264 { 50726, 0x80, "ReductionMatrix2", NULL, NULL},
2265 { 50727, 0x80, "AnalogBalance", NULL, NULL},
2266 { 50728, 0x80, "AsShotNeutral", NULL, NULL},
2267 { 50729, 0x80, "AsShotWhiteXY", NULL, NULL},
2268 { 50730, 0x80, "BaselineExposure", NULL, NULL},
2269 { 50731, 0x80, "BaselineNoise", NULL, NULL},
2270 { 50732, 0x80, "BaselineSharpness", NULL, NULL},
2271 { 50733, 0x80, "BayerGreenSplit", NULL, NULL},
2272 { 50734, 0x80, "LinearResponseLimit", NULL, NULL},
2273 { 50735, 0x80, "CameraSerialNumber", NULL, NULL},
2274 { 50736, 0x80, "LensInfo", NULL, NULL},
2275 { 50737, 0x80, "ChromaBlurRadius", NULL, NULL},
2276 { 50738, 0x80, "AntiAliasStrength", NULL, NULL},
2277 { 50739, 0x80, "ShadowScale", NULL, NULL},
2278 { 50740, 0x0080, "DNGPrivateData", handler_dngprivatedata, NULL},
2279 { 50741, 0x80, "MakerNoteSafety", NULL, NULL},
2280 { 50778, 0x80, "CalibrationIlluminant1", NULL, NULL},
2281 { 50779, 0x80, "CalibrationIlluminant2", NULL, NULL},
2282 { 50780, 0x80, "BestQualityScale", NULL, NULL},
2283 { 50781, 0x0088, "RawDataUniqueID", handler_hexdumpb, NULL},
2284 { 50784, 0x0000, "Alias Layer Metadata", NULL, NULL },
2285 { 50827, 0x80, "OriginalRawFileName", NULL, NULL},
2286 { 50828, 0x80, "OriginalRawFileData", NULL, NULL},
2287 { 50829, 0x80, "ActiveArea", NULL, NULL},
2288 { 50830, 0x80, "MaskedAreas", NULL, NULL},
2289 { 50831, 0x80, "AsShotICCProfile", NULL, NULL},
2290 { 50832, 0x80, "AsShotPreProfileMatrix", NULL, NULL},
2291 { 50833, 0x80, "CurrentICCProfile", NULL, NULL},
2292 { 50834, 0x80, "CurrentPreProfileMatrix", NULL, NULL},
2293 { 50879, 0x80, "ColorimetricReference", NULL, NULL},
2294 { 50931, 0x80, "CameraCalibrationSignature", NULL, NULL},
2295 { 50932, 0x80, "ProfileCalibrationSignature", NULL, NULL},
2296 { 50933, 0x80, "ExtraCameraProfiles", NULL, NULL},
2297 { 50934, 0x80, "AsShotProfileName", NULL, NULL},
2298 { 50935, 0x80, "NoiseReductionApplied", NULL, NULL},
2299 { 50936, 0x80, "ProfileName", NULL, NULL},
2300 { 50937, 0x80, "ProfileHueSatMapDims", NULL, NULL},
2301 { 50938, 0x80, "ProfileHueSatMapData1", NULL, NULL},
2302 { 50939, 0x80, "ProfileHueSatMapData2", NULL, NULL},
2303 { 50940, 0x80, "ProfileToneCurve", NULL, NULL},
2304 { 50941, 0x80, "ProfileEmbedPolicy", NULL, valdec_profileembedpolicy},
2305 { 50942, 0x80, "ProfileCopyright", NULL, NULL},
2306 { 50964, 0x80, "ForwardMatrix1", NULL, NULL},
2307 { 50965, 0x80, "ForwardMatrix2", NULL, NULL},
2308 { 50966, 0x80, "PreviewApplicationName", NULL, NULL},
2309 { 50967, 0x80, "PreviewApplicationVersion", NULL, NULL},
2310 { 50968, 0x80, "PreviewSettingsName", NULL, NULL},
2311 { 50969, 0x0088, "PreviewSettingsDigest", handler_hexdumpb, NULL},
2312 { 50970, 0x80, "PreviewColorSpace", NULL, valdec_dngcolorspace},
2313 { 50971, 0x80, "PreviewDateTime", NULL, NULL},
2314 { 50972, 0x0088, "RawImageDigest", handler_hexdumpb, NULL},
2315 { 50973, 0x0088, "OriginalRawFileDigest", handler_hexdumpb, NULL},
2316 { 50974, 0x80, "SubTileBlockSize", NULL, NULL},
2317 { 50975, 0x80, "RowInterleaveFactor", NULL, NULL},
2318 { 50981, 0x80, "ProfileLookTableDims", NULL, NULL},
2319 { 50982, 0x80, "ProfileLookTableData", NULL, NULL},
2320 { 51008, 0x80, "OpcodeList1", NULL, NULL},
2321 { 51009, 0x80, "OpcodeList2", NULL, NULL},
2322 { 51022, 0x80, "OpcodeList3", NULL, NULL},
2323 { 51041, 0x80, "NoiseProfile", NULL, NULL},
2324 { 51089, 0x80, "OriginalDefaultFinalSize", NULL, NULL},
2325 { 51090, 0x80, "OriginalBestQualityFinalSize", NULL, NULL},
2326 { 51091, 0x80, "OriginalDefaultCropSize", NULL, NULL},
2327 { 51107, 0x80, "ProfileHueSatMapEncoding", NULL, NULL},
2328 { 51108, 0x80, "ProfileLookTableEncoding", NULL, NULL},
2329 { 51109, 0x80, "BaselineExposureOffset", NULL, NULL},
2330 { 51110, 0x80, "DefaultBlackRender", NULL, NULL},
2331 { 51111, 0x0088, "NewRawImageDigest", handler_hexdumpb, NULL},
2332 { 51112, 0x80, "RawToPreviewGain", NULL, NULL},
2333 { 51113, 0x80, "CacheBlob", NULL, NULL},
2334 { 51114, 0x80, "CacheVersion", NULL, NULL},
2335 { 51125, 0x80, "DefaultUserCrop", NULL, NULL},
2336 { 59932, 0x0440, "PADDING_DATA", NULL, NULL },
2337 { 59933, 0x0010, "OffsetSchema", NULL, NULL },
2339 { 1, 0x0021, "InteroperabilityIndex", NULL, NULL },
2340 { 2, 0x0021, "InteroperabilityVersion", NULL, NULL },
2341 { 4096, 0x0020, "RelatedImageFileFormat", NULL, NULL },
2342 { 4097, 0x0020, "RelatedImageWidth", NULL, NULL },
2343 { 4098, 0x0020, "RelatedImageLength", NULL, NULL },
2345 { 0, 0x0041, "GPSVersionID", NULL, NULL },
2346 { 1, 0x0041, "GPSLatitudeRef", NULL, NULL },
2347 { 2, 0x0041, "GPSLatitude", handler_gpslatitude, NULL },
2348 { 3, 0x0041, "GPSLongitudeRef", NULL, NULL },
2349 { 4, 0x0041, "GPSLongitude", NULL, NULL },
2350 { 5, 0x0041, "GPSAltitudeRef", NULL, NULL },
2351 { 6, 0x0041, "GPSAltitude", NULL, NULL },
2352 { 7, 0x0041, "GPSTimeStamp", NULL, NULL },
2353 { 8, 0x0041, "GPSSatellites", NULL, NULL },
2354 { 9, 0x0041, "GPSStatus", NULL, NULL },
2355 { 10, 0x0041, "GPSMeasureMode", NULL, NULL },
2356 { 11, 0x0041, "GPSDOP", NULL, NULL },
2357 { 12, 0x0041, "GPSSpeedRef", NULL, NULL },
2358 { 13, 0x0041, "GPSSpeed", NULL, NULL },
2359 { 14, 0x0041, "GPSTrackRef", NULL, NULL },
2360 { 15, 0x0041, "GPSTrack", NULL, NULL },
2361 { 16, 0x0041, "GPSImgDirectionRef", NULL, NULL },
2362 { 17, 0x0041, "GPSImgDirection", NULL, NULL },
2363 { 18, 0x0041, "GPSMapDatum", NULL, NULL },
2364 { 19, 0x0041, "GPSLatitudeRef", NULL, NULL },
2365 { 20, 0x0041, "GPSLatitude", NULL, NULL },
2366 { 21, 0x0041, "GPSDestLongitudeRef", NULL, NULL },
2367 { 22, 0x0041, "GPSDestLongitude", NULL, NULL },
2368 { 23, 0x0041, "GPSDestBearingRef", NULL, NULL },
2369 { 24, 0x0041, "GPSDestBearing", NULL, NULL },
2370 { 25, 0x0041, "GPSDestDistanceRef", NULL, NULL },
2371 { 26, 0x0041, "GPSDestDistance", NULL, NULL },
2372 { 27, 0x0041, "GPSProcessingMethod", NULL, NULL },
2373 { 28, 0x0041, "GPSAreaInformation", NULL, NULL },
2374 { 29, 0x0041, "GPSDateStamp", NULL, NULL },
2375 { 30, 0x0041, "GPSDifferential", NULL, NULL },
2376 { 31, 0x0041, "GPSHPositioningError", NULL, NULL },
2378 { 1, 0x1001, "MakerNoteVersion", NULL, NULL },
2379 { 2, 0x1001, "ISOSpeed", NULL, NULL },
2380 { 3, 0x1001, "ColorMode", NULL, NULL },
2381 { 4, 0x1001, "Quality", NULL, NULL },
2382 { 5, 0x1001, "WhiteBalance", NULL, NULL },
2383 { 6, 0x1001, "Sharpness", NULL, NULL },
2384 { 7, 0x1001, "FocusMode", NULL, NULL },
2385 { 8, 0x1001, "FlashSetting", NULL, NULL },
2386 { 9, 0x1001, "FlashType", NULL, NULL },
2387 { 0xb, 0x1001, "WhiteBalanceFineTune", NULL, NULL },
2388 { 0xc, 0x1001, "WB_RBLevels", NULL, NULL },
2389 { 0xd, 0x1001, "ProgramShift", NULL, NULL },
2390 { 0xe, 0x1001, "ExposureDifference", NULL, NULL },
2391 { 0xf, 0x1001, "ISOSelection", NULL, NULL },
2392 { 0x10, 0x1001, "DataDump", NULL, NULL },
2393 { 0x11, 0x1001, "PreviewIFD", handler_subifd, NULL },
2394 { 0x12, 0x1001, "FlashExposureComp", NULL, NULL },
2395 { 0x13, 0x1001, "ISOSetting", NULL, NULL },
2396 { 0x16, 0x1001, "ImageBoundary", NULL, NULL },
2397 { 0x17, 0x1001, "ExternalFlashExposureComp", NULL, NULL },
2398 { 0x18, 0x1001, "FlashExposureBracketValue", NULL, NULL },
2399 { 0x19, 0x1001, "ExposureBracketValue", NULL, NULL },
2400 { 0x1a, 0x1001, "ImageProcessing", NULL, NULL },
2401 { 0x1b, 0x1001, "CropHiSpeed", NULL, NULL },
2402 { 0x1c, 0x1001, "ExposureTuning", NULL, NULL },
2403 { 0x1d, 0x1001, "SerialNumber", NULL, NULL },
2404 { 0x1e, 0x1001, "ColorSpace", NULL, NULL },
2405 { 0x1f, 0x1001, "VRInfo", NULL, NULL },
2406 { 0x20, 0x1001, "ImageAuthentication", NULL, NULL },
2407 { 0x21, 0x1001, "FaceDetect", NULL, NULL },
2408 { 0x22, 0x1001, "ActiveD-Lighting", NULL, NULL },
2409 { 0x23, 0x1001, "PictureControlData", NULL, NULL },
2410 { 0x24, 0x1001, "WorldTime", NULL, NULL },
2411 { 0x25, 0x1001, "ISOInfo", NULL, NULL },
2412 { 0x2a, 0x1001, "VignetteControl", NULL, NULL },
2413 { 0x2b, 0x1001, "DistortInfo", NULL, NULL },
2414 { 0x35, 0x1001, "HDRInfo", NULL, NULL },
2415 { 0x37, 0x1001, "MechanicalShutterCount", NULL, NULL },
2416 { 0x39, 0x1001, "LocationInfo", NULL, NULL },
2417 { 0x3d, 0x1001, "BlackLevel", NULL, NULL },
2418 { 0x4f, 0x1001, "ColorTemperatureAuto", NULL, NULL },
2419 { 0x80, 0x1001, "ImageAdjustment", NULL, NULL },
2420 { 0x81, 0x1001, "ToneComp", NULL, NULL },
2421 { 0x82, 0x1001, "AuxiliaryLens", NULL, NULL },
2422 { 0x83, 0x1001, "LensType", NULL, NULL },
2423 { 0x84, 0x1001, "Lens", NULL, NULL },
2424 { 0x85, 0x1001, "ManualFocusDistance", NULL, NULL },
2425 { 0x86, 0x1001, "DigitalZoom", NULL, NULL },
2426 { 0x87, 0x1001, "FlashMode", NULL, NULL },
2427 { 0x88, 0x1001, "AFFocusPosition", NULL, NULL },
2428 { 0x89, 0x1001, "ShootingMode", NULL, NULL },
2429 { 0x8b, 0x1001, "LensFStops", NULL, NULL },
2430 { 0x8c, 0x1001, "ContrastCurve", NULL, NULL },
2431 { 0x8d, 0x1001, "ColorHue", NULL, NULL },
2432 { 0x8f, 0x1001, "SceneMode", NULL, NULL },
2433 { 0x90, 0x1001, "LightSource", NULL, NULL },
2434 { 0x91, 0x1001, "ShotInfo", NULL, NULL },
2435 { 0x92, 0x1001, "HueAdjustment", NULL, NULL },
2436 { 0x93, 0x1001, "NEFCompression", NULL, NULL },
2437 { 0x94, 0x1001, "Saturation", NULL, NULL },
2438 { 0x95, 0x1001, "NoiseReduction", NULL, NULL },
2439 { 0x96, 0x1001, "NEFLinearizationTable", NULL, NULL },
2440 { 0x97, 0x1001, "ColorBalance", NULL, NULL },
2441 { 0x98, 0x1001, "LensData", NULL, NULL },
2442 { 0x99, 0x1001, "RawImageCenter", NULL, NULL },
2443 { 0x9a, 0x1001, "SensorPixelSize", NULL, NULL },
2444 { 0x9c, 0x1001, "SceneAssist", NULL, NULL },
2445 { 0x9e, 0x1001, "RetouchHistory", NULL, NULL },
2446 { 0xa0, 0x1001, "SerialNumber", NULL, NULL },
2447 { 0xa2, 0x1001, "ImageDataSize", NULL, NULL },
2448 { 0xa5, 0x1001, "ImageCount", NULL, NULL },
2449 { 0xa6, 0x1001, "DeletedImageCount", NULL, NULL },
2450 { 0xa7, 0x1001, "ShutterCount", NULL, NULL },
2451 { 0xa8, 0x1001, "FlashInfo", NULL, NULL },
2452 { 0xa9, 0x1001, "ImageOptimization", NULL, NULL },
2453 { 0xaa, 0x1001, "Saturation", NULL, NULL },
2454 { 0xab, 0x1001, "VariProgram", NULL, NULL },
2455 { 0xac, 0x1001, "ImageStabilization", NULL, NULL },
2456 { 0xad, 0x1001, "AFResponse", NULL, NULL },
2457 { 0xb0, 0x1001, "MultiExposure", NULL, NULL },
2458 { 0xb1, 0x1001, "HighISONoiseReduction", NULL, NULL },
2459 { 0xb3, 0x1001, "ToningEffect", NULL, NULL },
2460 { 0xb6, 0x1001, "PowerUpTime", NULL, NULL },
2461 { 0xb7, 0x1001, "AFInfo2", NULL, NULL },
2462 { 0xb8, 0x1001, "FileInfo", NULL, NULL },
2463 { 0xb9, 0x1001, "AFTune", NULL, NULL },
2464 { 0xbb, 0x1001, "RetouchInfo", NULL, NULL },
2465 { 0xbd, 0x1001, "PictureControlData", NULL, NULL },
2466 { 0xc3, 0x1001, "BarometerInfo", NULL, NULL },
2467 { 0xe00, 0x1001, "PrintIM", NULL, NULL },
2468 { 0xe01, 0x1001, "NikonCaptureData", NULL, NULL },
2469 { 0xe09, 0x1001, "NikonCaptureVersion", NULL, NULL },
2470 { 0xe0e, 0x1001, "NikonCaptureOffsets", NULL, NULL },
2471 { 0xe10, 0x1001, "NikonScanIFD", NULL, NULL },
2472 { 0xe13, 0x1001, "NikonCaptureEditVersions", NULL, NULL },
2473 { 0xe1d, 0x1001, "NikonICCProfile", NULL, NULL },
2474 { 0xe1e, 0x1001, "NikonCaptureOutput", NULL, NULL },
2475 { 0xe22, 0x1001, "NEFBitDepth", NULL, NULL },
2477 { 2, 0x2009, "?", handler_bplist, NULL },
2478 { 3, 0x2009, "RunTime", handler_bplist, NULL },
2479 { 8, 0x2001, "AccelerationVector", NULL, NULL },
2480 { 0xa, 0x2001, "HDRImageType", NULL, NULL },
2481 { 0xb, 0x2001, "BurstUUID", NULL, NULL },
2482 { 0xe, 0x2001, "Orientation?", NULL, NULL },
2483 { 0x11, 0x2001, "ContentIdentifier", NULL, NULL },
2484 { 0x15, 0x2001, "ImageUniqueID", NULL, NULL },
2486 { 0x1, 0x4001, "PanasonicRawVersion", NULL, NULL },
2487 { 0x2, 0x4001, "SensorWidth", NULL, NULL },
2488 { 0x3, 0x4001, "SensorHeight", NULL, NULL },
2489 { 0x4, 0x4001, "SensorTopBorder", NULL, NULL },
2490 { 0x5, 0x4001, "SensorLeftBorder", NULL, NULL },
2491 { 0x6, 0x4001, "SensorBottomBorder", NULL, NULL },
2492 { 0x7, 0x4001, "SensorRightBorder", NULL, NULL },
2493 { 0x8, 0x4001, "SamplesPerPixel", NULL, NULL },
2494 { 0x9, 0x4001, "CFAPattern", NULL, NULL },
2495 { 0xa, 0x4001, "BitsPerSample", NULL, NULL },
2496 { 0xb, 0x4001, "Compression", NULL, NULL },
2497 { 0xe, 0x4001, "LinearityLimitRed", NULL, NULL },
2498 { 0xf, 0x4001, "LinearityLimitGreen", NULL, NULL },
2499 { 0x10, 0x4001, "LinearityLimitBlue", NULL, NULL },
2500 { 0x11, 0x4001, "RedBalance", NULL, NULL },
2501 { 0x12, 0x4001, "BlueBalance", NULL, NULL },
2502 { 0x13, 0x4001, "WBInfo", NULL, NULL },
2503 { 0x17, 0x4001, "ISO", NULL, NULL },
2504 { 0x18, 0x4001, "HighISOMultiplierRed", NULL, NULL },
2505 { 0x19, 0x4001, "HighISOMultiplierGreen", NULL, NULL },
2506 { 0x1a, 0x4001, "HighISOMultiplierBlue", NULL, NULL },
2507 { 0x1b, 0x4001, "NoiseReductionParams", NULL, NULL },
2508 { 0x1c, 0x4001, "BlackLevelRed", NULL, NULL },
2509 { 0x1d, 0x4001, "BlackLevelGreen", NULL, NULL },
2510 { 0x1e, 0x4001, "BlackLevelBlue", NULL, NULL },
2511 { 0x24, 0x4001, "WBRedLevel", NULL, NULL },
2512 { 0x25, 0x4001, "WBGreenLevel", NULL, NULL },
2513 { 0x26, 0x4001, "WBBlueLevel", NULL, NULL },
2514 { 0x27, 0x4001, "WBInfo2", NULL, NULL },
2515 { 0x2d, 0x4001, "RawFormat", NULL, NULL },
2516 { 0x2e, 0x4009, "JpgFromRaw", handler_panasonicjpg, NULL },
2517 { 0x2f, 0x4001, "CropTop", NULL, NULL },
2518 { 0x30, 0x4001, "CropLeft", NULL, NULL },
2519 { 0x31, 0x4001, "CropBottom", NULL, NULL },
2520 { 0x32, 0x4001, "CropRight", NULL, NULL },
2522 { 0x0000, 0x8001, "Version", NULL, NULL},
2523 { 0x0010, 0x8001, "InternalSerialNumber", NULL, NULL},
2524 { 0x1000, 0x8001, "Quality", NULL, NULL},
2525 { 0x1001, 0x8001, "Sharpness", NULL, NULL},
2526 { 0x1002, 0x8001, "WhiteBalance", NULL, NULL},
2527 { 0x1003, 0x8001, "Saturation", NULL, NULL},
2528 { 0x1010, 0x8001, "FujiFlashMode", NULL, NULL},
2529 { 0x1011, 0x8001, "FlashExposureComp", NULL, NULL},
2530 { 0x1020, 0x8001, "Macro", NULL, NULL},
2531 { 0x1021, 0x8001, "FocusMode", NULL, NULL},
2532 { 0x1022, 0x8001, "AFMode", NULL, NULL},
2533 { 0x1023, 0x8001, "FocusPixel", NULL, NULL},
2534 { 0x1030, 0x8001, "SlowSync", NULL, NULL},
2535 { 0x1031, 0x8001, "PictureMode", NULL, NULL},
2536 { 0x1032, 0x8001, "ExposureCount", NULL, NULL},
2537 { 0x1100, 0x8001, "AutoBracketing", NULL, NULL},
2538 { 0x1101, 0x8001, "SequenceNumber", NULL, NULL},
2539 { 0x1201, 0x8001, "AdvancedFilter", NULL, NULL},
2540 { 0x1210, 0x8001, "ColorMode", NULL, NULL},
2541 { 0x1300, 0x8001, "BlurWarning", NULL, NULL},
2542 { 0x1301, 0x8001, "FocusWarning", NULL, NULL},
2543 { 0x1302, 0x8001, "ExposureWarning", NULL, NULL},
2544 { 0x1400, 0x8001, "DynamicRange", NULL, NULL},
2545 { 0x1422, 0x8001, "ImageStabilization", NULL, NULL},
2546 { 0x4100, 0x8001, "FacesDetected", NULL, NULL},
2547 { 0x4200, 0x8001, "NumFaceElements", NULL, NULL}
2550 static void do_dbg_print_numeric_values(deark *c, lctx *d, const struct taginfo *tg, const struct tagnuminfo *tni,
2551 de_ucstring *dbgline)
2553 i64 i;
2554 struct valdec_params vp;
2555 struct valdec_result vr;
2556 struct numeric_value nv;
2558 de_zeromem(&vr, sizeof(struct valdec_result));
2560 switch(tg->datatype) {
2561 case DATATYPE_BYTE: case DATATYPE_SBYTE:
2562 case DATATYPE_UNDEF: case DATATYPE_ASCII:
2563 case DATATYPE_UINT16: case DATATYPE_SINT16:
2564 case DATATYPE_UINT32: case DATATYPE_SINT32: case DATATYPE_IFD32:
2565 case DATATYPE_UINT64: case DATATYPE_SINT64: case DATATYPE_IFD64:
2566 case DATATYPE_RATIONAL: case DATATYPE_SRATIONAL:
2567 case DATATYPE_FLOAT32: case DATATYPE_FLOAT64:
2568 break;
2569 default:
2570 goto done; // Not a supported numeric datatype
2573 ucstring_append_sz(dbgline, " {", DE_ENCODING_LATIN1);
2575 // Populate the fields of vp/vr that don't change.
2576 vp.d = d;
2577 vp.tg = tg;
2578 vr.s = ucstring_create(c);
2580 for(i=0; i<tg->valcount && i<DE_TIFF_MAX_VALUES_TO_PRINT; i++) {
2581 read_numeric_value(c, d, tg, i, &nv, dbgline);
2583 // If possible, decode the value and print its name.
2584 if(nv.isvalid && tni->vdfn) {
2585 // Set the remaining fields of vp/vr.
2586 vp.idx = i;
2587 vp.n = nv.val_int64;
2588 ucstring_empty(vr.s);
2590 if(tni->vdfn(c, &vp, &vr)) {
2591 ucstring_append_sz(dbgline, "(=", DE_ENCODING_LATIN1);
2592 ucstring_append_ucstring(dbgline, vr.s);
2593 ucstring_append_sz(dbgline, ")", DE_ENCODING_LATIN1);
2597 if(i<tg->valcount-1) {
2598 ucstring_append_sz(dbgline, ",", DE_ENCODING_LATIN1);
2601 if(tg->valcount>DE_TIFF_MAX_VALUES_TO_PRINT) {
2602 ucstring_append_sz(dbgline, "...", DE_ENCODING_LATIN1);
2604 ucstring_append_sz(dbgline, "}", DE_ENCODING_LATIN1);
2605 done:
2606 if(vr.s) ucstring_destroy(vr.s);
2609 static void do_dbg_print_text_multi_values(deark *c, lctx *d, const struct taginfo *tg,
2610 const struct tagnuminfo *tni, de_ucstring *dbgline)
2612 int is_truncated = 0;
2613 int str_count = 0;
2614 i64 pos, endpos;
2615 i64 adj_totalsize;
2617 // An ASCII field is a sequence of NUL-terminated strings.
2618 // The spec does not say what to do if an ASCII field does not end in a NUL.
2619 // Our rule is that if the field does not end in a NUL byte (including the case
2620 // where it is 0 length), then treat it as if it has a NUL byte appended to it.
2621 // The other options would be to pretend the last byte is always NUL, or to
2622 // ignore everything after the last NUL byte.
2624 adj_totalsize = tg->total_size;
2625 if(adj_totalsize > DE_TIFF_MAX_CHARS_TO_PRINT) {
2626 adj_totalsize = DE_TIFF_MAX_CHARS_TO_PRINT;
2627 // FIXME: Suboptimal things might happen if we truncate exactly one byte
2628 is_truncated = 1;
2630 endpos = tg->val_offset + adj_totalsize;
2632 ucstring_append_sz(dbgline, " {", DE_ENCODING_LATIN1);
2634 pos = tg->val_offset;
2635 while(1) {
2636 struct de_stringreaderdata *srd;
2638 if(pos>=endpos && str_count>0) break;
2640 srd = dbuf_read_string(c->infile, pos, endpos-pos, endpos-pos,
2641 DE_CONVFLAG_STOP_AT_NUL, d->current_textfield_encoding);
2643 if(str_count>0) ucstring_append_sz(dbgline, ",", DE_ENCODING_LATIN1);
2644 ucstring_append_sz(dbgline, "\"", DE_ENCODING_LATIN1);
2645 ucstring_append_ucstring(dbgline, srd->str);
2646 ucstring_append_sz(dbgline, "\"", DE_ENCODING_LATIN1);
2647 str_count++;
2649 pos += srd->bytes_consumed;
2650 de_destroy_stringreaderdata(c, srd);
2653 if(is_truncated) {
2654 ucstring_append_sz(dbgline, "...", DE_ENCODING_LATIN1);
2656 ucstring_append_sz(dbgline, "}", DE_ENCODING_LATIN1);
2659 // Used for ASCII-type tag numbers that we expect to contain only a single
2660 // string (i.e. nearly all of them).
2661 static void do_dbg_print_text_single_value(deark *c, lctx *d, const struct taginfo *tg,
2662 const struct tagnuminfo *tni, de_ucstring *dbgline)
2664 struct de_stringreaderdata *srd = NULL;
2666 srd = dbuf_read_string(c->infile, tg->val_offset, tg->total_size,
2667 DE_TIFF_MAX_CHARS_TO_PRINT, DE_CONVFLAG_STOP_AT_NUL,
2668 d->current_textfield_encoding);
2670 ucstring_append_sz(dbgline, " {\"", DE_ENCODING_LATIN1);
2671 ucstring_append_ucstring(dbgline, srd->str);
2672 if(srd->was_truncated) {
2673 ucstring_append_sz(dbgline, "...", DE_ENCODING_LATIN1);
2675 ucstring_append_sz(dbgline, "\"}", DE_ENCODING_LATIN1);
2677 de_destroy_stringreaderdata(c, srd);
2680 static void do_dbg_print_values(deark *c, lctx *d, const struct taginfo *tg, const struct tagnuminfo *tni,
2681 de_ucstring *dbgline)
2683 if(c->debug_level<1) return;
2684 if(tni->flags&0x08) return; // Auto-display of values is suppressed for this tag.
2685 if(tg->valcount<1) return;
2687 if(tg->datatype==DATATYPE_ASCII) {
2688 if(tni->flags & 0x0004) {
2689 do_dbg_print_text_multi_values(c, d, tg, tni, dbgline);
2691 else {
2692 do_dbg_print_text_single_value(c, d, tg, tni, dbgline);
2695 else {
2696 do_dbg_print_numeric_values(c, d, tg, tni, dbgline);
2700 static const struct tagnuminfo *find_tagnuminfo(int tagnum, int filefmt, u8 ifdtype)
2702 size_t i;
2704 for(i=0; i<DE_ARRAYCOUNT(tagnuminfo_arr); i++) {
2705 if(tagnuminfo_arr[i].tagnum!=tagnum) {
2706 continue;
2709 if(ifdtype==IFDTYPE_EXIFINTEROP) {
2710 // For interoperability IFDs, allow only special tags
2711 if(!(tagnuminfo_arr[i].flags&0x20)) {
2712 continue;
2715 else if(ifdtype==IFDTYPE_GPS) {
2716 // For GPS IFDs, allow only special tags
2717 if(!(tagnuminfo_arr[i].flags&0x40)) {
2718 continue;
2721 else if(ifdtype==IFDTYPE_NIKONMN) {
2722 // For this IFD, allow only special tags
2723 if(!(tagnuminfo_arr[i].flags&0x1000)) {
2724 continue;
2727 else if(ifdtype==IFDTYPE_APPLEMN) {
2728 // For this IFD, allow only special tags
2729 if(!(tagnuminfo_arr[i].flags&0x2000)) {
2730 continue;
2733 else if(ifdtype==IFDTYPE_FUJIFILMMN) {
2734 // For this IFD, allow only special tags
2735 if(!(tagnuminfo_arr[i].flags&0x8000)) {
2736 continue;
2739 else if(tagnuminfo_arr[i].flags&0x01) {
2740 // A special tag not allowed above
2741 if(filefmt==DE_TIFFFMT_JPEGXR && (tagnuminfo_arr[i].flags&0x0400)) {
2742 // Allow all JPEG XR tags in normal JPEG XR IFDs.
2743 // Maybe we should disallow TIFF tags that are not known to be
2744 // allowed in JPEG XR files, but I suspect a lot of random TIFF
2745 // tags are occasionally used in JPEG XR, and I'm not aware of
2746 // any conflicts.
2749 else if(filefmt==DE_TIFFFMT_MPEXT && (tagnuminfo_arr[i].flags&0x0800)) {
2752 else if(filefmt==DE_TIFFFMT_NIKONMN && (tagnuminfo_arr[i].flags&0x1000)) {
2755 else if(filefmt==DE_TIFFFMT_PANASONIC && (tagnuminfo_arr[i].flags&0x4000) &&
2756 ifdtype==IFDTYPE_NORMAL)
2760 else {
2761 // Ignore this tag -- it's in the wrong "namespace".
2762 continue;
2766 return &tagnuminfo_arr[i];
2768 return NULL;
2771 struct decode_page_ctx {
2772 i64 width; // = ImageWidth + padding
2773 i64 height; // = ImageLength
2774 i64 strile_max_w, strile_max_h;
2775 i64 strile_max_rowspan;
2776 i64 striles_per_plane;
2777 u32 samples_per_pixel_per_plane;
2779 i64 strileset_idx;
2780 i64 strileset_xpos, strileset_ypos;
2781 i64 strileset_height;
2782 i64 strileset_width;
2783 i64 strileset_rowspan;
2784 i64 strile_idx;
2785 dbuf *unc_strile_dbuf[DE_TIFF_MAX_SAMPLES]; // Pointers to other dbufs; do not free
2787 UI num_planes_to_decode;
2788 UI samples_per_pixel_to_decode;
2789 UI base_samples_per_pixel;
2790 u8 is_tiled;
2791 u8 is_separated;
2792 u8 is_grayscale;
2793 u8 grayscale_reverse_polarity;
2794 u8 need_to_reverse_bits;
2795 u8 use_pal;
2796 u8 has_alpha;
2797 u8 is_assoc_alpha;
2798 UI alpha_sample_idx;
2800 struct de_dfilter_ctx *dfctx; // Decompressor that can be shared between striles
2802 struct de_dfilter_in_params dcmpri;
2803 struct de_dfilter_out_params dcmpro;
2804 struct de_dfilter_results dres;
2807 static void reverse_bits_in_membuf(dbuf *f)
2809 i64 len = f->len;
2810 i64 i;
2812 for(i=0; i<len; i++) {
2813 u8 b, b2;
2814 size_t k;
2816 b = dbuf_getbyte(f, i);
2817 if(b==0x00 || b==0xff) continue;
2818 b2 = 0;
2819 for(k=0; k<8; k++) {
2820 if(b & (1U<<k)) {
2821 b2 |= (1U<<(7-k));
2824 dbuf_writebyte_at(f, i, b2);
2828 static void decompress_strile_uncmpr(deark *c, lctx *d, struct page_ctx *pg,
2829 struct decode_page_ctx *dctx)
2831 fmtutil_decompress_uncompressed(c, &dctx->dcmpri, &dctx->dcmpro, &dctx->dres, 0);
2832 if(dctx->need_to_reverse_bits) {
2833 reverse_bits_in_membuf(dctx->dcmpro.f);
2837 // If old LZW version, sets pg->is_old_lzw.
2838 static void detect_lzw_version(deark *c, lctx *d, struct page_ctx *pg)
2840 u8 buf[2];
2842 if(pg->strile_count<1) return;
2843 // The first LZW code is supposed to be a clear code (=256; 9 bits). If it is
2844 // little-endian, presumably this is the old LZW version.
2845 // So old version should start: 00000000 xxxxxxx1
2846 // And new version: 10000000 0xxxxxxx
2847 de_read(buf, pg->strile_data[0].pos, 2);
2848 if(buf[0]==0x00 && (buf[1]&0x01)) {
2849 pg->is_old_lzw = 1;
2851 de_dbg(c, "lzw version: %s", pg->is_old_lzw?"old":"new");
2854 static void decompress_strile_lzw(deark *c, lctx *d, struct page_ctx *pg,
2855 struct decode_page_ctx *dctx)
2857 struct de_lzw_params delzwp;
2859 if(dctx->strile_idx==0) {
2860 detect_lzw_version(c, d, pg);
2863 if(dctx->dfctx) {
2864 de_dfilter_destroy(dctx->dfctx);
2865 dctx->dfctx = NULL;
2866 // TODO: Make the LZW decoder support DE_DFILTER_COMMAND_REINITIALIZE
2869 de_zeromem(&delzwp, sizeof(struct de_lzw_params));
2870 delzwp.fmt = DE_LZWFMT_TIFF;
2871 delzwp.max_code_size = 12;
2872 delzwp.tifflzw_oldversion = (pg->is_old_lzw)?1:0;
2874 dctx->dfctx = de_dfilter_create(c, dfilter_lzw_codec, (void*)&delzwp, &dctx->dcmpro, &dctx->dres);
2876 de_dfilter_addslice(dctx->dfctx, dctx->dcmpri.f, dctx->dcmpri.pos, dctx->dcmpri.len);
2877 de_dfilter_finish(dctx->dfctx);
2880 static void decompress_strile_packbits(deark *c, lctx *d, struct page_ctx *pg,
2881 struct decode_page_ctx *dctx)
2883 if(dctx->dfctx) {
2884 de_dfilter_command(dctx->dfctx, DE_DFILTER_COMMAND_REINITIALIZE, 0);
2886 else {
2887 dctx->dfctx = de_dfilter_create(c, dfilter_packbits_codec, NULL,
2888 &dctx->dcmpro, &dctx->dres);
2891 de_dfilter_addslice(dctx->dfctx, dctx->dcmpri.f, dctx->dcmpri.pos, dctx->dcmpri.len);
2892 de_dfilter_finish(dctx->dfctx);
2895 static void decompress_strile_deflate(deark *c, lctx *d, struct page_ctx *pg,
2896 struct decode_page_ctx *dctx)
2898 struct de_deflate_params inflparams;
2900 de_zeromem(&inflparams, sizeof(struct de_deflate_params));
2901 inflparams.flags = DE_DEFLATEFLAG_ISZLIB;
2902 fmtutil_decompress_deflate_ex(c, &dctx->dcmpri, &dctx->dcmpro, &dctx->dres,
2903 &inflparams);
2906 static void decompress_strile_fax34(deark *c, lctx *d, struct page_ctx *pg,
2907 struct decode_page_ctx *dctx)
2909 struct de_fax34_params fax34params;
2911 de_zeromem(&fax34params, sizeof(struct de_fax34_params));
2912 fax34params.image_width = dctx->strileset_width;
2913 fax34params.image_height = dctx->strileset_height;
2914 fax34params.tiff_cmpr_meth = (UI)pg->compression;
2915 fax34params.t4options = pg->t4options;
2916 fax34params.t6options = pg->t6options;
2917 fax34params.is_lsb = (pg->fill_order==2)?1:0;
2919 fmtutil_fax34_codectype1(c, &dctx->dcmpri, &dctx->dcmpro, &dctx->dres,
2920 (void*)&fax34params);
2923 static const struct cmpr_meth_info cmpr_meth_info_arr[] = {
2924 { CMPR_NONE, 0x0, "uncompressed", decompress_strile_uncmpr },
2925 { CMPR_CCITTRLE, 0x0, "CCITTRLE", decompress_strile_fax34 },
2926 { CMPR_FAX3, 0x0, "Fax3", decompress_strile_fax34 },
2927 { CMPR_FAX4, 0x0, "Fax4", decompress_strile_fax34 },
2928 { CMPR_LZW, 0x0, "LZW", decompress_strile_lzw },
2929 { CMPR_OLDJPEG, 0x0, "OldJPEG", NULL},
2930 { CMPR_NEWJPEG, 0x0, "NewJPEG", NULL},
2931 { CMPR_DEFLATE, 0x0, "DEFLATE", decompress_strile_deflate },
2932 { 9, 0x0, "T.85 JBIG", NULL},
2933 { 10, 0x0, "T.43 JBIG", NULL},
2934 { 32766, 0x0, "NeXT 2-bit RLE", NULL},
2935 { 32771, 0x0, "CCITTRLEW", NULL},
2936 { CMPR_PACKBITS, 0x0, "PackBits", decompress_strile_packbits },
2937 { 32809, 0x0, "ThunderScan", NULL},
2938 { 32895, 0x0, "IT8CTPAD", NULL},
2939 { 32896, 0x0, "IT8LW", NULL},
2940 { 32897, 0x0, "IT8MP/HC", NULL},
2941 { 32898, 0x0, "IT8BL", NULL},
2942 { 32908, 0x0, "PIXARFILM", NULL},
2943 { 32909, 0x0, "PIXARLOG", NULL},
2944 { CMPR_DEFLATE_ALT, 0x0, "DEFLATE", decompress_strile_deflate },
2945 { 32947, 0x0, "DCS", NULL},
2946 { 34661, 0x0, "ISO JBIG", NULL},
2947 { 34676, 0x0, "SGILOG", NULL},
2948 { 34677, 0x0, "SGILOG24", NULL},
2949 { 34712, 0x0, "JPEG2000", NULL},
2950 { 34715, 0x0, "JBIG2", NULL},
2951 { 34887, 0x0, "LERC", NULL},
2952 { 34892, 0x0, "Lossy JPEG(DNG)", NULL},
2953 { 34925, 0x0, "LZMA2", NULL},
2954 { 50000, 0x0, "Zstd", NULL},
2955 { 50001, 0x0, "WebP", NULL}
2958 static const struct cmpr_meth_info *find_cmpr_meth_info(u32 id)
2960 size_t k;
2962 for(k=0; k<DE_ARRAYCOUNT(cmpr_meth_info_arr); k++) {
2963 if(id == cmpr_meth_info_arr[k].id)
2964 return &cmpr_meth_info_arr[k];
2966 return NULL;
2969 static int decompress_strile(deark *c, lctx *d, struct page_ctx *pg,
2970 struct decode_page_ctx *dctx, UI plane_idx)
2972 int retval = 0;
2974 // TODO: Some of our decompressors have significant overhead. This can
2975 // be a performance issue with TIFF format, which likes to chop up an
2976 // image into lots of tiny pieces, each of which is compressed
2977 // independently.
2978 // We ought to have a way to efficiently reset a decompressor, without
2979 // having to recreate it entirely.
2981 dctx->dcmpri.pos = pg->strile_data[dctx->strile_idx].pos;
2982 dctx->dcmpri.len = pg->strile_data[dctx->strile_idx].len;
2983 if(dctx->dcmpri.pos + dctx->dcmpri.len > dctx->dcmpri.f->len) {
2984 dctx->dcmpri.len = dctx->dcmpri.f->len - dctx->dcmpri.pos;
2986 if(dctx->dcmpri.len<0) dctx->dcmpri.len = 0;
2987 dctx->dcmpro.f = dctx->unc_strile_dbuf[plane_idx];
2988 dctx->dcmpro.len_known = 1;
2989 dctx->dcmpro.expected_len = dctx->strileset_rowspan * dctx->strileset_height;
2990 de_dfilter_init_objects(c, NULL, NULL, &dctx->dres);
2992 if(pg->cmi && pg->cmi->decompressor) {
2993 pg->cmi->decompressor(c, d, pg, dctx);
2995 else {
2996 decompress_strile_uncmpr(c, d, pg, dctx);
2999 if(dctx->dres.errcode) {
3000 detiff_err(c, d, pg, "Decompression failed (strip@%d,%d): %s",
3001 (int)dctx->strileset_xpos, (int)dctx->strileset_ypos,
3002 de_dfilter_get_errmsg(c, &dctx->dres));
3003 // TODO?: Better handling of partial failure
3004 goto done;
3006 retval = 1;
3007 done:
3008 return retval;
3011 static int decompress_strileset(deark *c, lctx *d, struct page_ctx *pg,
3012 struct decode_page_ctx *dctx)
3014 UI sample_idx;
3015 int retval = 0;
3017 for(sample_idx=0; sample_idx<dctx->num_planes_to_decode; sample_idx++) {
3018 dctx->strile_idx = dctx->strileset_idx +(i64)sample_idx * dctx->striles_per_plane;
3019 retval = decompress_strile(c, d, pg, dctx, sample_idx);
3020 if(!retval) goto done;
3022 retval = 1;
3023 done:
3024 return retval;
3027 static de_colorsample unpremultiply_alpha1(de_colorsample cval, de_colorsample a)
3029 if(a==0xff) {
3030 return cval;
3032 if(a==0 || cval==0) {
3033 return 0;
3035 if(cval>=a) {
3036 return 0xff;
3038 return (de_colorsample)(0.5 + (double)cval / ((double)a/255.0));
3041 static de_color unpremultiply_alpha(de_color clr)
3043 de_colorsample r, g, b, a;
3045 r = DE_COLOR_R(clr);
3046 g = DE_COLOR_G(clr);
3047 b = DE_COLOR_B(clr);
3048 a = DE_COLOR_A(clr);
3049 r = unpremultiply_alpha1(r, a);
3050 g = unpremultiply_alpha1(g, a);
3051 b = unpremultiply_alpha1(b, a);
3052 return DE_MAKE_RGBA(r, g, b, a);
3055 static void paint_decompressed_strile_to_image(deark *c, lctx *d, struct page_ctx *pg,
3056 struct decode_page_ctx *dctx, de_bitmap *img)
3058 i64 i, j;
3059 u32 s_idx;
3060 u32 sample_mask;
3061 u32 sample_scalefactor;
3062 u32 prev_sample[DE_TIFF_MAX_SAMPLES];
3063 u32 sample[DE_TIFF_MAX_SAMPLES];
3065 de_zeromem(&prev_sample, sizeof(prev_sample));
3066 de_zeromem(&sample, sizeof(sample));
3068 sample_mask = (1U<<(u32)pg->bits_per_sample)-1U;
3069 sample_scalefactor = 255/sample_mask;
3071 for(j=0; j<dctx->strileset_height; j++) {
3073 for(s_idx=0; s_idx<dctx->samples_per_pixel_to_decode; s_idx++) {
3074 prev_sample[s_idx] = 0;
3077 for(i=0; i<dctx->strileset_width; i++) {
3078 de_color clr;
3080 for(s_idx=0; s_idx<dctx->samples_per_pixel_to_decode; s_idx++) {
3081 UI dbuf_idx;
3082 i64 sample_offset;
3084 if(dctx->is_separated) {
3085 dbuf_idx = s_idx;
3086 sample_offset = 0;
3088 else {
3089 dbuf_idx = 0;
3090 sample_offset = (i64)s_idx;
3093 switch(pg->bits_per_sample) {
3094 case 1: case 2: case 4:
3095 sample[s_idx] = de_get_bits_symbol(dctx->unc_strile_dbuf[dbuf_idx], (i64)pg->bits_per_sample,
3096 dctx->strileset_rowspan*j, i*(i64)dctx->samples_per_pixel_per_plane + sample_offset);
3097 break;
3098 case 8:
3099 sample[s_idx] = dbuf_getbyte(dctx->unc_strile_dbuf[dbuf_idx], dctx->strileset_rowspan*j +
3100 (i*(i64)dctx->samples_per_pixel_per_plane) + sample_offset);
3101 break;
3102 default:
3103 sample[s_idx] = 0;
3107 if(pg->predictor==2) {
3108 for(s_idx=0; s_idx<dctx->samples_per_pixel_to_decode; s_idx++) {
3109 sample[s_idx] = (sample[s_idx] + prev_sample[s_idx]) & sample_mask;
3110 prev_sample[s_idx] = sample[s_idx];
3114 if(!dctx->use_pal && sample_scalefactor>1) { // Scale samples to 255
3115 for(s_idx=0; s_idx<dctx->samples_per_pixel_to_decode; s_idx++) {
3116 sample[s_idx] *= sample_scalefactor;
3120 if(dctx->use_pal) {
3121 clr = pg->pal[sample[0] & 0xff];
3123 else if(dctx->is_grayscale) {
3124 if(dctx->grayscale_reverse_polarity) {
3125 sample[0] = 0xff - sample[0];
3127 clr = DE_MAKE_GRAY(sample[0]);
3129 else {
3130 clr = DE_MAKE_RGB(sample[0], sample[1], sample[2]);
3132 if(dctx->has_alpha) {
3133 clr = DE_SET_ALPHA(clr, sample[dctx->alpha_sample_idx]);
3134 if(dctx->is_assoc_alpha) {
3135 clr = unpremultiply_alpha(clr);
3139 de_bitmap_setpixel_rgba(img, dctx->strileset_xpos+i, dctx->strileset_ypos+j, clr);
3144 static void set_image_density(deark *c, lctx *d, struct page_ctx *pg, de_finfo *fi)
3146 if(!pg->have_density) return;
3148 if(pg->orientation>=5 && pg->orientation<=8) {
3149 // For some orientations, the x dimension is the ImageLength dimension.
3150 fi->density.xdens = pg->density_ImageLength;
3151 fi->density.ydens = pg->density_ImageWidth;
3153 else {
3154 fi->density.xdens = pg->density_ImageWidth;
3155 fi->density.ydens = pg->density_ImageLength;
3157 if(pg->resolution_unit==1) {
3158 fi->density.code = DE_DENSITY_UNK_UNITS;
3160 else if(pg->resolution_unit==2) {
3161 fi->density.code = DE_DENSITY_DPI;
3163 else if(pg->resolution_unit==3) { // pixels/cm
3164 fi->density.xdens *= 2.54;
3165 fi->density.ydens *= 2.54;
3166 fi->density.code = DE_DENSITY_DPI;
3170 // We can extract NewJPEG images if the following conditions are true:
3171 // - There is just one strile.
3172 // - The image does not use separate JPEG tables. Presumably this corresponds to the
3173 // absence of a JPEGTables tag.
3174 // (TODO: Reconstitute single-strile images that use separate tables.)
3175 static void do_newjpeg(deark *c, lctx *d, struct page_ctx *pg)
3177 if(pg->strile_count!=1) goto done;
3178 if(pg->strile_data[0].pos + pg->strile_data[0].len > c->infile->len) goto done;
3179 // TODO: Tiled images might include extra pixels for padding, which we ought to warn
3180 // about. But we would have to scan the JPEG data to know for sure.
3182 dbuf_create_file_from_slice(c->infile, pg->strile_data[0].pos, pg->strile_data[0].len,
3183 "jpg", NULL, 0);
3185 done:
3189 static void do_process_ifd_image(deark *c, lctx *d, struct page_ctx *pg)
3191 de_bitmap *img = NULL;
3192 struct decode_page_ctx *dctx = NULL;
3193 de_finfo *fi = NULL;
3194 int need_errmsg = 0;
3195 int saved_indent_level;
3196 int saved_indent_level2;
3197 i64 i;
3198 i64 striles_across;
3199 int output_bypp;
3200 int ok_bps = 0;
3201 int can_optimize_uncompressed = 0;
3202 UI createflags = 0;
3203 // (Multiple dbufs are needed for PlanarConfig=separated.)
3204 dbuf *tmp_membuf[DE_TIFF_MAX_SAMPLES];
3205 dbuf *tmp_subfile[DE_TIFF_MAX_SAMPLES];
3207 de_dbg_indent_save(c, &saved_indent_level);
3208 dctx = de_malloc(c, sizeof(struct decode_page_ctx));
3209 de_zeromem(tmp_membuf, sizeof(tmp_membuf));
3210 de_zeromem(tmp_subfile, sizeof(tmp_subfile));
3212 // TODO: Should we check pg->compression?
3213 if(pg->jpegoffset>0) {
3214 do_oldjpeg(c, d, pg);
3215 goto done;
3218 if(pg->compression==CMPR_NEWJPEG && pg->strile_count==1 && !pg->have_jpegtables) {
3219 // FIXME: This should really happen *after* some of the processing below,
3220 // but it's complicated.
3221 do_newjpeg(c, d, pg);
3222 goto done;
3225 // Decent TIFF decoding support is planned eventually, but for now this is
3226 // just a testbed for some things.
3227 if(!d->opt_decode) goto done;
3229 if(!pg->have_imagewidth || pg->imagewidth<1 || pg->imagelength<1) {
3230 de_dbg(c, "[non-image IFD]");
3231 goto done;
3234 de_dbg(c, "decoding ifd image");
3235 de_dbg_indent(c, 1);
3237 if(pg->compression<1) {
3238 pg->compression = CMPR_NONE;
3240 pg->cmi = find_cmpr_meth_info(pg->compression);
3242 if(pg->samples_per_pixel<1) {
3243 pg->samples_per_pixel = 1;
3245 if(pg->bits_per_sample<1) {
3246 pg->bits_per_sample = 1;
3248 if(pg->predictor<1) {
3249 pg->predictor = 1;
3251 if(pg->sample_format<1) {
3252 pg->sample_format = 1;
3254 if(pg->resolution_unit<1) {
3255 pg->resolution_unit = 2;
3257 if(pg->rows_per_strip<1 || pg->rows_per_strip>pg->imagelength) {
3258 pg->rows_per_strip = pg->imagelength;
3261 if(pg->planarconfig<=1 || pg->samples_per_pixel==1) {
3262 dctx->is_separated = 0;
3264 else if(pg->planarconfig==2) {
3265 dctx->is_separated = 1;
3267 else {
3268 need_errmsg = 1; goto done;
3271 dctx->width = pg->imagewidth; // tentative dimensions
3272 dctx->height = pg->imagelength;
3273 if(!de_good_image_dimensions(c, dctx->width, dctx->height)) goto done;
3275 if(!pg->cmi || !pg->cmi->decompressor) {
3276 detiff_err(c, d, pg, "Unsupported compression method: %d (%s)", (int)pg->compression,
3277 ((pg->cmi && pg->cmi->name)?pg->cmi->name:"?"));
3278 goto done;
3281 if(pg->have_tile_tags) {
3282 if(pg->have_strip_tags) {
3283 detiff_warn(c, d, pg, "Image seems to have both strips and tiles");
3285 dctx->is_tiled = 1;
3288 if(pg->strile_count<1) {
3289 detiff_err(c, d, pg, "No image data found");
3290 goto done;
3292 if(pg->strile_count==1 && pg->strile_data[0].len==0) {
3293 // Tolerate missing StripByteCounts tag in some cases
3294 pg->strile_data[0].len = c->infile->len - pg->strile_data[0].pos;
3297 if(pg->sample_format!=1) {
3298 detiff_err(c, d, pg, "Unsupported sample format (%d)", (int)pg->sample_format);
3299 goto done;
3302 if(pg->photometric==0 || pg->photometric==1) {
3303 dctx->is_grayscale = 1;
3304 dctx->grayscale_reverse_polarity = (pg->photometric==0);
3305 dctx->base_samples_per_pixel = 1;
3306 if(pg->bits_per_sample==1 || pg->bits_per_sample==2 || pg->bits_per_sample==4 ||
3307 pg->bits_per_sample==8)
3309 ok_bps = 1;
3312 else if(pg->photometric==2) { // RGB
3313 dctx->base_samples_per_pixel = 3;
3314 if(pg->bits_per_sample==8) {
3315 ok_bps = 1;
3318 else if(pg->photometric==3) { // paletted
3319 dctx->base_samples_per_pixel = 1;
3320 dctx->use_pal = 1;
3321 if(pg->bits_per_sample==1 || pg->bits_per_sample==2 || pg->bits_per_sample==4 ||
3322 pg->bits_per_sample==8)
3324 ok_bps = 1;
3327 else {
3328 detiff_err(c, d, pg, "Unsupported color type: %d (%s)", (int)pg->photometric,
3329 lookup_str(photometric_name_map, DE_ARRAYCOUNT(photometric_name_map), (i64)pg->photometric));
3330 goto done;
3333 if(!ok_bps) {
3334 detiff_err(c, d, pg, "Unsupported bits/sample (%d) for this color type", (int)pg->bits_per_sample);
3335 goto done;
3338 if(pg->samples_per_pixel<1) {
3339 pg->samples_per_pixel = dctx->base_samples_per_pixel;
3341 if(pg->samples_per_pixel < dctx->base_samples_per_pixel) {
3342 detiff_err(c, d, pg, "Bad samples/pixel (%d) for this color type", (int)pg->samples_per_pixel);
3343 goto done;
3345 dctx->samples_per_pixel_to_decode = pg->samples_per_pixel;
3346 if(dctx->samples_per_pixel_to_decode>DE_TIFF_MAX_SAMPLES) {
3347 detiff_warn(c, d, pg, "Large number of SamplesPerPixel (%d). Some samples ignored.",
3348 (int)pg->samples_per_pixel);
3349 dctx->samples_per_pixel_to_decode = DE_TIFF_MAX_SAMPLES;
3352 if(pg->predictor!=1 && pg->predictor!=2) {
3353 detiff_err(c, d, pg, "Unsupported prediction method (%d)", (int)pg->predictor);
3354 goto done;
3357 if(pg->fill_order==2) {
3358 // FillOrder=LSB is ambiguous in general, but we allow it in some special cases.
3359 if(pg->compression==CMPR_NONE && pg->samples_per_pixel==1 && pg->bits_per_sample==1) {
3360 dctx->need_to_reverse_bits = 1;
3362 else if(pg->compression>=2 && pg->compression<=5) {
3365 else {
3366 detiff_warn(c, d, pg, "Unexpected FillOrder for this image type. Ignoring.");
3370 // TODO: Support -padpix in more situations
3371 if(c->padpix && !dctx->is_tiled && !dctx->is_separated && pg->compression==CMPR_NONE) {
3372 if(pg->samples_per_pixel==1 && pg->bits_per_sample<8) {
3373 dctx->width = de_pad_to_n(dctx->width * pg->samples_per_pixel * pg->bits_per_sample, 8) /
3374 ((i64)pg->samples_per_pixel * pg->bits_per_sample);
3378 // Look for an alpha sample
3379 for(i=0; i<(i64)pg->extrasamples_count; i++) {
3380 if((i64)dctx->base_samples_per_pixel + i >= (i64)dctx->samples_per_pixel_to_decode) break;
3381 if(pg->extrasample_type[i]==1) { // Assoc. alpha
3382 dctx->has_alpha = 1;
3383 dctx->is_assoc_alpha = 1;
3384 dctx->alpha_sample_idx = (UI)dctx->base_samples_per_pixel + (UI)i;
3385 break;
3387 else if(pg->extrasample_type[i]==2) { // Unassoc. alpha
3388 dctx->has_alpha = 1;
3389 dctx->is_assoc_alpha = 0;
3390 dctx->alpha_sample_idx = (UI)dctx->base_samples_per_pixel + (UI)i;
3391 break;
3395 if(dctx->has_alpha) {
3396 dctx->samples_per_pixel_to_decode = (UI)dctx->alpha_sample_idx+1;
3398 else {
3399 dctx->samples_per_pixel_to_decode = dctx->base_samples_per_pixel;
3402 if(dctx->is_separated) {
3403 dctx->striles_per_plane = pg->strile_count / pg->samples_per_pixel;
3404 dctx->num_planes_to_decode = dctx->samples_per_pixel_to_decode;
3405 dctx->samples_per_pixel_per_plane = 1;
3407 else {
3408 dctx->striles_per_plane = pg->strile_count;
3409 dctx->num_planes_to_decode = 1;
3410 dctx->samples_per_pixel_per_plane = pg->samples_per_pixel;
3413 if(dctx->is_tiled) {
3414 i64 striles_down;
3416 if(pg->tile_width<1 || pg->tile_height<1 || pg->tile_width>c->max_image_dimension ||
3417 pg->tile_height>c->max_image_dimension)
3419 need_errmsg = 1; goto done;
3421 dctx->strile_max_w = pg->tile_width;
3422 dctx->strile_max_h = pg->tile_height;
3423 striles_across = (dctx->width + pg->tile_width - 1) / pg->tile_width;
3424 striles_down = (dctx->height + pg->tile_height - 1) / pg->tile_height;
3426 if(c->padpix) {
3427 dctx->width = striles_across * pg->tile_width;
3428 dctx->height = striles_down * pg->tile_height;
3431 else {
3432 dctx->strile_max_w = dctx->width;
3433 dctx->strile_max_h = pg->rows_per_strip;
3434 striles_across = 1;
3436 dctx->strile_max_rowspan = (dctx->strile_max_w * (i64)dctx->samples_per_pixel_per_plane *
3437 pg->bits_per_sample + 7)/8;
3439 de_dfilter_init_objects(c, &dctx->dcmpri, &dctx->dcmpro, NULL);
3440 dctx->dcmpri.f = c->infile;
3442 if(pg->compression==CMPR_NONE && !dctx->need_to_reverse_bits && !dctx->is_separated) {
3443 can_optimize_uncompressed = 1;
3446 if(dctx->is_grayscale) output_bypp = 1;
3447 else output_bypp = 3;
3448 if(dctx->has_alpha) output_bypp++;
3449 img = de_bitmap_create(c, dctx->width, dctx->height, output_bypp);
3451 de_dbg_indent_save(c, &saved_indent_level2);
3453 for(dctx->strileset_idx=0; dctx->strileset_idx<dctx->striles_per_plane; dctx->strileset_idx++) {
3454 int ret;
3455 i64 first_strile_idx;
3457 first_strile_idx = dctx->strileset_idx;
3458 dctx->strileset_xpos = (dctx->strileset_idx % striles_across) * dctx->strile_max_w;
3459 dctx->strileset_ypos = (dctx->strileset_idx / striles_across) * dctx->strile_max_h;
3460 if(dctx->strileset_ypos >= dctx->height) goto after_paint;
3462 de_dbg2(c, "strip #%d (%d,%d) at %"I64_FMT"%s, dlen=%"I64_FMT,
3463 (int)dctx->strileset_idx, (int)dctx->strileset_xpos, (int)dctx->strileset_ypos,
3464 pg->strile_data[first_strile_idx].pos, (dctx->is_separated?"...":""),
3465 pg->strile_data[first_strile_idx].len);
3467 dctx->strileset_width = dctx->strile_max_w;
3468 if(dctx->is_tiled) { // Tiles are all the same width and height.
3469 dctx->strileset_height = dctx->strile_max_h;
3471 else { // The last strip may have a smaller height.
3472 dctx->strileset_height = de_min_int(dctx->strile_max_h, dctx->height - dctx->strileset_ypos);
3474 dctx->strileset_rowspan = (dctx->strileset_width * (i64)dctx->samples_per_pixel_per_plane *
3475 pg->bits_per_sample + 7)/8;
3476 if(dctx->strileset_height<1) goto after_paint;
3478 if(can_optimize_uncompressed) {
3479 if(tmp_subfile[0]) {
3480 dbuf_close(tmp_subfile[0]);
3482 tmp_subfile[0] = dbuf_open_input_subfile(c->infile, pg->strile_data[first_strile_idx].pos,
3483 pg->strile_data[first_strile_idx].len);
3484 dctx->unc_strile_dbuf[0] = tmp_subfile[0];
3486 else {
3487 UI k;
3489 for(k=0; k<dctx->num_planes_to_decode; k++) {
3490 if(tmp_membuf[k]) {
3491 dbuf_empty(tmp_membuf[k]);
3493 else {
3494 tmp_membuf[k] = dbuf_create_membuf(c, 0, 0);
3495 dbuf_set_length_limit(tmp_membuf[k], dctx->strile_max_h * dctx->strile_max_rowspan);
3497 dctx->unc_strile_dbuf[k] = tmp_membuf[k];
3500 ret = decompress_strileset(c, d, pg, dctx);
3501 if(!ret) {
3502 // TODO?: Better handling of partial failure
3503 if(dctx->strileset_idx>0) goto after_paint;
3504 goto done;
3508 paint_decompressed_strile_to_image(c, d, pg, dctx, img);
3511 after_paint:
3512 de_dbg_indent_restore(c, saved_indent_level2);
3513 fi = de_finfo_create(c);
3515 if(pg->orientation>=5 && pg->orientation<=8) {
3516 de_bitmap_transpose(img);
3518 if(pg->orientation==2 || pg->orientation==3 || pg->orientation==6 || pg->orientation==7) {
3519 de_bitmap_mirror(img);
3521 if(pg->orientation==3 || pg->orientation==4 || pg->orientation==7 || pg->orientation==8) {
3522 // More efficient than de_bitmap_flip(). We can do this if flipping is the last step.
3523 createflags |= DE_CREATEFLAG_FLIP_IMAGE;
3526 if(pg->is_thumb) {
3527 createflags |= DE_CREATEFLAG_IS_AUX;
3528 de_finfo_set_name_from_sz(c, fi, "thumb", 0, DE_ENCODING_LATIN1);
3531 set_image_density(c, d, pg, fi);
3532 fi->internal_mod_time = pg->internal_mod_time;
3534 de_bitmap_write_to_file_finfo(img, fi, createflags);
3536 done:
3537 for(i=0; i<DE_TIFF_MAX_SAMPLES; i++) {
3538 if(tmp_membuf[i]) dbuf_close(tmp_membuf[i]);
3539 if(tmp_subfile[i]) dbuf_close(tmp_subfile[i]);
3541 de_bitmap_destroy(img);
3542 de_finfo_destroy(c, fi);
3543 if(need_errmsg) {
3544 detiff_err(c, d, pg, "Unsupported image type or bad image");
3546 if(dctx) {
3547 if(dctx->dfctx) de_dfilter_destroy(dctx->dfctx);
3548 de_free(c, dctx);
3550 de_dbg_indent_restore(c, saved_indent_level);
3553 static void process_ifd(deark *c, lctx *d, int ifd_idx1, i64 ifdpos1, u8 ifdtype1,
3554 u8 is_in_main_ifd_list)
3556 struct page_ctx *pg = NULL;
3557 int num_tags;
3558 int i;
3559 i64 tmpoffset;
3560 de_ucstring *dbgline = NULL;
3561 struct taginfo tg;
3562 const char *name;
3563 static const struct tagnuminfo default_tni = { 0, 0x00, "?", NULL, NULL };
3565 pg = de_malloc(c, sizeof(struct page_ctx));
3566 pg->density_ImageWidth = 0.0;
3567 pg->density_ImageLength = 0.0;
3568 pg->ifd_idx = ifd_idx1;
3569 pg->ifdpos = ifdpos1;
3570 pg->ifdtype = ifdtype1;
3571 if(is_in_main_ifd_list) {
3572 pg->ifd_idx_in_main_list = d->num_main_ifds_processed++;
3573 de_snprintf(pg->errmsgtoken_ifd, sizeof(pg->errmsgtoken_ifd),
3574 "IFD#%d@%"I64_FMT, pg->ifd_idx_in_main_list+1, pg->ifdpos);
3576 else {
3577 pg->ifd_idx_in_main_list = -1;
3578 de_snprintf(pg->errmsgtoken_ifd, sizeof(pg->errmsgtoken_ifd),
3579 "IFD#n/a@%"I64_FMT, pg->ifdpos);
3582 // NOTE: Some TIFF apps (e.g. Windows Photo Viewer) have been observed to encode
3583 // ASCII fields (e.g. ImageDescription) in UTF-8, in violation of the TIFF spec.
3584 // It might be better to give up trying to obey the various specifications, and
3585 // just try to autodetect the encoding, based on whether it is valid UTF-8, etc.
3587 if(pg->ifdtype==DE_TIFFFMT_JPEGXR)
3588 d->current_textfield_encoding = DE_ENCODING_UTF8; // Might be overridden below
3589 else
3590 d->current_textfield_encoding = DE_ENCODING_ASCII;
3592 switch(pg->ifdtype) {
3593 case IFDTYPE_SUBIFD:
3594 name=" (SubIFD)";
3595 break;
3596 case IFDTYPE_GLOBALPARAMS:
3597 name=" (Global Parameters IFD)";
3598 break;
3599 case IFDTYPE_EXIF:
3600 name=" (Exif IFD)";
3601 d->current_textfield_encoding = DE_ENCODING_ASCII;
3602 break;
3603 case IFDTYPE_EXIFINTEROP:
3604 name=" (Exif Interoperability IFD)";
3605 d->current_textfield_encoding = DE_ENCODING_ASCII;
3606 break;
3607 case IFDTYPE_GPS:
3608 name=" (GPS IFD)";
3609 d->current_textfield_encoding = DE_ENCODING_ASCII;
3610 break;
3611 case IFDTYPE_NIKONPREVIEW:
3612 name=" (Nikon Preview)";
3613 break;
3614 case IFDTYPE_MASKSUBIFD:
3615 name=" (Mask SubIFD)";
3616 break;
3617 default:
3618 name="";
3621 de_dbg(c, "IFD at %"I64_FMT"%s", pg->ifdpos, name);
3622 de_dbg_indent(c, 1);
3624 de_dbg2(c, "ifd id: \"%s\"", pg->errmsgtoken_ifd);
3626 if(pg->ifdpos >= c->infile->len || pg->ifdpos<8) {
3627 detiff_warn(c, d, NULL, "Invalid IFD offset: %"I64_FMT, pg->ifdpos);
3628 goto done;
3631 if(d->is_bigtiff) {
3632 num_tags = (int)dbuf_geti64x(c->infile, pg->ifdpos, d->is_le);
3634 else {
3635 num_tags = (int)dbuf_getu16x(c->infile, pg->ifdpos, d->is_le);
3638 de_dbg(c, "number of tags: %d", num_tags);
3639 if(num_tags>200) {
3640 detiff_warn(c, d, pg, "Invalid or excessive number of TIFF tags (%d)", num_tags);
3641 goto done;
3644 // Record the next IFD in the main list.
3645 tmpoffset = getfpos(c, d, pg->ifdpos+d->ifdhdrsize+num_tags*d->ifditemsize);
3646 de_dbg(c, "offset of next IFD: %"I64_FMT"%s", tmpoffset, tmpoffset==0?" (none)":"");
3647 push_ifd(c, d, tmpoffset, IFDTYPE_NORMAL, 1);
3649 dbgline = ucstring_create(c);
3651 for(i=0; i<num_tags; i++) {
3652 const struct tagnuminfo *tni;
3654 de_zeromem(&tg, sizeof(struct taginfo));
3655 tg.pg = pg;
3657 tg.tagnum = (int)dbuf_getu16x(c->infile, pg->ifdpos+d->ifdhdrsize+i*d->ifditemsize, d->is_le);
3658 tg.datatype = (int)dbuf_getu16x(c->infile, pg->ifdpos+d->ifdhdrsize+i*d->ifditemsize+2, d->is_le);
3659 // Not a file pos, but getfpos() does the right thing.
3660 tg.valcount = getfpos(c, d, pg->ifdpos+d->ifdhdrsize+i*d->ifditemsize+4);
3662 tg.unit_size = size_of_data_type(tg.datatype);
3663 tg.total_size = tg.unit_size * tg.valcount;
3664 if(tg.total_size <= d->offsetsize) {
3665 tg.val_offset = pg->ifdpos+d->ifdhdrsize+i*d->ifditemsize+d->offsetoffset;
3667 else {
3668 tg.val_offset = getfpos(c, d, pg->ifdpos+d->ifdhdrsize+i*d->ifditemsize+d->offsetoffset);
3671 tni = find_tagnuminfo(tg.tagnum, d->fmt, pg->ifdtype);
3672 if(tni) {
3673 tg.tag_known = 1;
3675 else {
3676 tni = &default_tni; // Make sure tni is not NULL.
3679 ucstring_empty(dbgline);
3680 ucstring_printf(dbgline, DE_ENCODING_UTF8,
3681 "tag %d (%s) ty=%d #=%d offs=%" I64_FMT,
3682 tg.tagnum, tni->tagname,
3683 tg.datatype, (int)tg.valcount,
3684 tg.val_offset);
3686 do_dbg_print_values(c, d, &tg, tni, dbgline);
3688 // do_dbg_print_values() already tried to limit the line length.
3689 // The "500+" in the next line is an emergency brake.
3690 de_dbg(c, "%s", ucstring_getpsz_n(dbgline, 500+DE_DBG_MAX_STRLEN));
3691 de_dbg_indent(c, 1);
3693 if(tni->hfn) {
3694 tni->hfn(c, d, &tg, tni);
3697 de_dbg_indent(c, -1);
3700 if(pg->ifd_idx==0) {
3701 d->first_ifd_orientation = pg->orientation;
3702 d->first_ifd_cosited = (pg->ycbcrpositioning==2);
3705 do_process_ifd_image(c, d, pg);
3707 done:
3708 de_dbg_indent(c, -1);
3709 ucstring_destroy(dbgline);
3710 if(pg) {
3711 de_free(c, pg->strile_data);
3712 de_free(c, pg);
3716 static void do_tiff(deark *c, lctx *d)
3718 i64 pos;
3719 i64 ifdoffs;
3720 int ifd_idx;
3721 int need_to_read_header = 1;
3723 pos = 0;
3725 if(d->fmt==DE_TIFFFMT_APPLEMN) {
3726 push_ifd(c, d, 14, IFDTYPE_APPLEMN, 1);
3727 need_to_read_header = 0;
3729 else if(d->fmt==DE_TIFFFMT_FUJIFILMMN) {
3730 ifdoffs = getfpos(c, d, 8);
3731 push_ifd(c, d, ifdoffs, IFDTYPE_FUJIFILMMN, 1);
3732 need_to_read_header = 0;
3735 if(need_to_read_header) {
3736 de_dbg(c, "TIFF%s file header at %"I64_FMT,
3737 (d->is_exif_submodule?"/Exif":""), pos);
3738 de_dbg_indent(c, 1);
3740 de_dbg(c, "byte order: %s-endian", d->is_le?"little":"big");
3742 // Skip over the signature
3743 if(d->is_bigtiff) {
3744 pos += 8;
3746 else {
3747 pos += 4;
3750 // Read the first IFD offset
3751 ifdoffs = getfpos(c, d, pos);
3752 de_dbg(c, "offset of first IFD: %d", (int)ifdoffs);
3753 if(d->fmt==DE_TIFFFMT_NIKONMN) {
3754 push_ifd(c, d, ifdoffs, IFDTYPE_NIKONMN, 1);
3756 else {
3757 push_ifd(c, d, ifdoffs, IFDTYPE_NORMAL, 1);
3760 de_dbg_indent(c, -1);
3763 // Process IFDs until we run out of them.
3764 // ifd_idx tracks how many IFDs we have finished processing, but it's not
3765 // really meaningful except when it's 0.
3766 ifd_idx = 0;
3767 while(1) {
3768 u8 ifdtype = IFDTYPE_NORMAL;
3769 u8 is_in_main_ifd_list = 0;
3771 ifdoffs = pop_ifd(c, d, &ifdtype, &is_in_main_ifd_list);
3772 if(ifdoffs==0) break;
3773 process_ifd(c, d, ifd_idx, ifdoffs, ifdtype, is_in_main_ifd_list);
3774 ifd_idx++;
3777 de_dbg(c, "number of IFDs: %d (%d in main list)", d->ifd_count, d->num_main_ifds_processed);
3780 static int de_identify_tiff_internal(deark *c, int *is_le)
3782 i64 byte_order_sig;
3783 i64 magic;
3784 int fmt = 0;
3786 byte_order_sig = de_getu16be(0);
3787 *is_le = (byte_order_sig == 0x4d4d) ? 0 : 1;
3789 if(*is_le)
3790 magic = de_getu16le(2);
3791 else
3792 magic = de_getu16be(2);
3794 if(byte_order_sig==0x4550 && magic==0x002a) {
3795 fmt = DE_TIFFFMT_MDI;
3797 else if(byte_order_sig==0x4d4d || byte_order_sig==0x4949) {
3799 switch(magic) {
3800 case 0x002a: // Standard TIFF
3801 fmt = DE_TIFFFMT_TIFF;
3802 break;
3803 case 0x002b:
3804 fmt = DE_TIFFFMT_BIGTIFF;
3805 break;
3806 case 0x0055:
3807 fmt = DE_TIFFFMT_PANASONIC;
3808 break;
3810 case 0x01bc: // JPEG-XR
3811 fmt = DE_TIFFFMT_JPEGXR;
3812 break;
3814 //case 0x314e: // NIFF
3816 case 0x4352:
3817 fmt = DE_TIFFFMT_DCP;
3818 break;
3819 case 0x4f52:
3820 case 0x5352:
3821 fmt = DE_TIFFFMT_ORF;
3822 break;
3826 return fmt;
3829 static void identify_more_formats(deark *c, lctx *d)
3831 u8 buf[20];
3833 de_read(buf, 8, sizeof(buf));
3835 // Deark TIFF container formats. See de_fmtutil_handle_iptc() for example.
3836 if(!de_memcmp(buf, "Deark extracted ", 16)) {
3837 if(!de_memcmp(&buf[16], "IPTC", 4)) {
3838 d->is_deark_iptc = 1;
3839 return;
3841 if(!de_memcmp(&buf[16], "8BIM", 4)) {
3842 d->is_deark_8bim = 1;
3843 return;
3847 if(!de_memcmp(buf, "XEROX DIFF", 10)) {
3848 de_dbg(c, "XIFF/XEROX DIFF format detected");
3849 d->is_xiff = 1;
3850 return;
3852 if(!de_memcmp(buf, " eXtended ", 10)) {
3853 de_dbg(c, "XIFF/eXtended format detected");
3854 d->is_xiff = 1;
3858 static void de_run_tiff(deark *c, de_module_params *mparams)
3860 lctx *d = NULL;
3862 d = de_malloc(c, sizeof(lctx));
3864 if(mparams) {
3865 d->in_params = &mparams->in_params;
3868 d->opt_decode = (u8)de_get_ext_option_bool(c, "tiff:decode", 1);
3870 if(de_havemodcode(c, mparams, 'A')) {
3871 d->fmt = DE_TIFFFMT_APPLEMN;
3872 d->is_le = 0;
3873 de_strlcpy(d->errmsgtoken_module, "Apple MakerNote", sizeof(d->errmsgtoken_module));
3875 else if(de_havemodcode(c, mparams, 'F')) {
3876 d->fmt = DE_TIFFFMT_FUJIFILMMN;
3877 d->is_le = 1;
3878 de_strlcpy(d->errmsgtoken_module, "FujiFilm MakerNote", sizeof(d->errmsgtoken_module));
3880 else {
3881 d->fmt = de_identify_tiff_internal(c, &d->is_le);
3884 if(de_havemodcode(c, mparams, 'N')) {
3885 de_strlcpy(d->errmsgtoken_module, "Nikon MakerNote", sizeof(d->errmsgtoken_module));
3886 d->fmt = DE_TIFFFMT_NIKONMN;
3889 if(de_havemodcode(c, mparams, 'M') && (d->fmt==DE_TIFFFMT_TIFF)) {
3890 de_strlcpy(d->errmsgtoken_module, "MPF", sizeof(d->errmsgtoken_module));
3891 d->fmt = DE_TIFFFMT_MPEXT;
3894 if(de_havemodcode(c, mparams, 'E')) {
3895 d->is_exif_submodule = 1;
3896 de_strlcpy(d->errmsgtoken_module, "Exif", sizeof(d->errmsgtoken_module));
3899 if(d->fmt==DE_TIFFFMT_TIFF) {
3900 identify_more_formats(c, d);
3903 switch(d->fmt) {
3904 case DE_TIFFFMT_TIFF:
3905 if(d->is_xiff)
3906 de_declare_fmt(c, "XIFF");
3907 else
3908 de_declare_fmt(c, "TIFF");
3909 break;
3910 case DE_TIFFFMT_BIGTIFF:
3911 de_declare_fmt(c, "BigTIFF");
3912 d->is_bigtiff = 1;
3913 break;
3914 case DE_TIFFFMT_PANASONIC:
3915 de_declare_fmt(c, "Panasonic RAW/RW2");
3916 break;
3917 case DE_TIFFFMT_ORF:
3918 de_declare_fmt(c, "Olympus RAW");
3919 break;
3920 case DE_TIFFFMT_DCP:
3921 de_declare_fmt(c, "DNG Camera Profile");
3922 break;
3923 case DE_TIFFFMT_MDI:
3924 de_declare_fmt(c, "MDI");
3925 break;
3926 case DE_TIFFFMT_JPEGXR:
3927 de_declare_fmt(c, "JPEG XR");
3928 break;
3931 if(d->fmt==0) {
3932 detiff_warn(c, d, NULL, "This is not a known/supported TIFF or TIFF-like format.");
3935 if(d->is_bigtiff) {
3936 d->ifdhdrsize = 8;
3937 d->ifditemsize = 20;
3938 d->offsetoffset = 12;
3939 d->offsetsize = 8;
3941 else {
3942 d->ifdhdrsize = 2;
3943 d->ifditemsize = 12;
3944 d->offsetoffset = 8;
3945 d->offsetsize = 4;
3948 d->current_textfield_encoding = DE_ENCODING_ASCII;
3950 do_tiff(c, d);
3952 if(mparams) {
3953 // .out_params.flags:
3954 // 0x08: has_exif_gps
3955 // 0x10: first IFD has subsampling=cosited
3956 // 0x20: uint1 = first IFD's orientation
3957 // 0x40: uint2 = Exif version
3958 // 0x80: uint3 = main image count
3959 if(d->has_exif_gps) {
3960 mparams->out_params.flags |= 0x08;
3962 if(d->first_ifd_cosited) {
3963 mparams->out_params.flags |= 0x10;
3965 if(d->first_ifd_orientation>0) {
3966 mparams->out_params.flags |= 0x20;
3967 mparams->out_params.uint1 = d->first_ifd_orientation;
3969 if(d->exif_version_as_uint32>0) {
3970 mparams->out_params.flags |= 0x40;
3971 mparams->out_params.uint2 = d->exif_version_as_uint32;
3973 if(d->fmt==DE_TIFFFMT_MPEXT) {
3974 mparams->out_params.flags |= 0x80;
3975 mparams->out_params.uint3 = d->mpf_main_image_count;
3979 if(d) {
3980 de_free(c, d->ifdstack);
3981 de_inthashtable_destroy(c, d->ifds_seen);
3982 de_free(c, d);
3986 static int de_identify_tiff(deark *c)
3988 int fmt;
3989 int is_le;
3991 fmt = de_identify_tiff_internal(c, &is_le);
3992 if(fmt!=0) return 100;
3993 return 0;
3996 static void de_help_tiff(deark *c)
3998 de_msg(c, "-opt tiff:decode=<0|1> : Don't/Do attempt to decode images");
4001 void de_module_tiff(deark *c, struct deark_module_info *mi)
4003 mi->id = "tiff";
4004 mi->desc = "TIFF image";
4005 mi->run_fn = de_run_tiff;
4006 mi->identify_fn = de_identify_tiff;
4007 mi->help_fn = de_help_tiff;