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
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
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
93 #define CMPR_CCITTRLE 2
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
104 struct decode_page_ctx
;
105 struct localctx_struct
;
106 typedef struct localctx_struct lctx
;
110 struct ifdstack_item
{
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
{
121 const struct taginfo
*tg
;
125 struct valdec_result
{
126 // Value decoders will be called with a valid, empty ucstring 's'.
130 typedef int (*val_decoder_fn_type
)(deark
*c
, const struct valdec_params
*vp
, struct valdec_result
*vr
);
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
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
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
{
164 decompressor_fn decompressor
;
167 struct strile_data_struct
{
175 int ifd_idx_in_main_list
; // -1 if not in main list
182 u8 have_strip_tags
, have_tile_tags
;
187 u32 ycbcrpositioning
;
189 u32 samples_per_pixel
;
196 u32 t4options
, t6options
;
197 double density_ImageWidth
, density_ImageLength
;
198 i64 imagewidth
, imagelength
; // Raw tag values, before considering Orientation
202 i64 tile_width
, tile_height
;
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
;
209 struct strile_data_struct
*strile_data
; // array[strile_count]
210 struct de_timestamp internal_mod_time
;
212 char errmsgtoken_ifd
[40];
215 // Data associated with an actual tag in an IFD in the file
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
230 struct localctx_struct
{
235 int is_exif_submodule
;
237 int can_decode_fltpt
;
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
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
;
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
, ...)
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
);
286 de_vsnprintf(buf
, sizeof(buf
), fmt
, ap
);
287 de_err(c
, "[%s] %s", pg
->errmsgtoken_ifd
, buf
);
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
, ...)
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
);
313 de_vsnprintf(buf
, sizeof(buf
), fmt
, ap
);
314 de_warn(c
, "[%s] %s", pg
->errmsgtoken_ifd
, buf
);
317 de_vwarn(c
, fmt
, 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
)
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
--;
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
);
344 // Append to the IFD list (of all IFDs). This is only used for loop detection.
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");
352 if(!de_inthashtable_add_item(c
, d
->ifds_seen
, ifdpos
, NULL
)) {
353 detiff_err(c
, d
, NULL
, "IFD loop detected");
358 // Add to the IFD stack (of unprocessed IFDs).
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");
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
)
377 case DATATYPE_BYTE
: case DATATYPE_SBYTE
:
381 case DATATYPE_UINT16
: case DATATYPE_SINT16
:
383 case DATATYPE_UINT32
: case DATATYPE_SINT32
:
384 case DATATYPE_FLOAT32
:
387 case DATATYPE_RATIONAL
: case DATATYPE_SRATIONAL
:
388 case DATATYPE_FLOAT64
:
389 case DATATYPE_UINT64
: case DATATYPE_SINT64
:
396 static int read_rational_as_double(deark
*c
, lctx
*d
, i64 pos
, double *n
)
401 num
= dbuf_getu32x(c
->infile
, pos
, d
->is_le
);
402 den
= dbuf_getu32x(c
->infile
, pos
+4, d
->is_le
);
404 *n
= (double)num
/(double)den
;
408 static int read_srational_as_double(deark
*c
, lctx
*d
, i64 pos
, double *n
)
413 num
= dbuf_geti32x(c
->infile
, pos
, d
->is_le
);
414 den
= dbuf_geti32x(c
->infile
, pos
+4, d
->is_le
);
416 *n
= (double)num
/(double)den
;
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
)
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
);
440 case DATATYPE_FLOAT64
:
441 if(!d
->can_decode_fltpt
) return 0;
442 *n
= dbuf_getfloat64x(c
->infile
, offs
, d
->is_le
);
445 // There should be no need to support other data types (like UINT32).
450 static int read_tag_value_as_int64(deark
*c
, lctx
*d
, const struct taginfo
*tg
,
451 i64 value_index
, i64
*n
)
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
);
464 case DATATYPE_UINT32
:
466 *n
= dbuf_getu32x(c
->infile
, offs
, d
->is_le
);
471 *n
= (i64
)de_getbyte(offs
);
473 case DATATYPE_UINT64
:
475 // TODO: Somehow support unsigned 64-bit ints that don't fit into
477 *n
= dbuf_geti64x(c
->infile
, offs
, d
->is_le
);
480 case DATATYPE_SINT16
:
481 *n
= dbuf_geti16x(c
->infile
, offs
, d
->is_le
);
483 case DATATYPE_SINT32
:
484 *n
= dbuf_geti32x(c
->infile
, offs
, d
->is_le
);
486 case DATATYPE_SINT64
:
487 *n
= dbuf_geti64x(c
->infile
, offs
, d
->is_le
);
490 *n
= dbuf_geti8(c
->infile
, offs
);
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
)) {
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
{
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
)
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
) {
537 case DATATYPE_UINT16
:
538 case DATATYPE_SINT16
:
539 case DATATYPE_UINT32
:
540 case DATATYPE_SINT32
:
542 case DATATYPE_UINT64
:
543 case DATATYPE_SINT64
:
545 ret
= read_tag_value_as_int64(c
, d
, tg
, value_index
, &nv
->val_int64
);
546 nv
->val_double
= (double)nv
->val_int64
;
550 ucstring_printf(dbgline
, DE_ENCODING_LATIN1
, "%" I64_FMT
, nv
->val_int64
);
552 ucstring_append_sz(dbgline
, "?", DE_ENCODING_LATIN1
);
556 case DATATYPE_RATIONAL
:
557 case DATATYPE_SRATIONAL
:
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
);
566 num
= dbuf_getu32x(c
->infile
, offs
, d
->is_le
);
567 den
= dbuf_getu32x(c
->infile
, offs
+4, d
->is_le
);
572 nv
->val_double
= 0.0;
575 ucstring_printf(dbgline
, DE_ENCODING_LATIN1
, "%" I64_FMT
"/%" I64_FMT
, num
, den
);
581 nv
->val_double
= (double)num
/(double)den
;
582 nv
->val_int64
= (i64
)nv
->val_double
;
584 format_double(dbgline
, nv
->val_double
);
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
);
596 nv
->val_double
= dbuf_getfloat32x(c
->infile
, offs
, d
->is_le
);
598 nv
->val_int64
= (i64
)nv
->val_double
;
601 format_double(dbgline
, nv
->val_double
);
607 ucstring_append_sz(dbgline
, "?", DE_ENCODING_LATIN1
);
612 static i64
getfpos(deark
*c
, lctx
*d
, i64 pos
)
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
630 jpeglength
= c
->infile
->len
- pg
->jpegoffset
;
632 if(jpeglength
<1 || jpeglength
>DE_MAX_SANE_OBJECT_SIZE
) {
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
);
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
);
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
;
658 // TODO: Should createflags be set to DE_CREATEFLAG_IS_AUX in some cases?
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
)
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
679 while(pos
< pos1
+len
) {
680 de_read(buf
, pos
, 4);
681 if(de_memcmp(buf
, "PKTS", 4)) {
686 pos
+=4; // Don't know what these 4 bytes are for.
688 de_read(segtype
, pos
, 40);
691 // TODO: Is this always big-endian?
692 data_len
= de_getu32be(pos
);
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
);
708 static const char *lookup_str(const struct int_and_str
*items
, size_t num_items
, i64 n
)
712 for(i
=0; i
<(i64
)num_items
; i
++) {
713 if(items
[i
].n
==n
&& items
[i
].s
!=NULL
) {
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
)
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
)
736 ucstring_append_flags_item(vr
->s
, "reduced-res");
740 ucstring_append_flags_item(vr
->s
, "one-page-of-many");
744 ucstring_append_flags_item(vr
->s
, "mask");
748 ucstring_append_flags_item(vr
->s
, "MRC-related");
752 ucstring_append_flags_itemf(vr
->s
, "0x%x", (unsigned int)n
);
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
);
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
);
779 ucstring_append_sz(vr
->s
, "?", DE_ENCODING_LATIN1
);
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"},
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
);
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
);
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
);
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
);
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
);
830 static int valdec_t4options(deark
*c
, const struct valdec_params
*vp
, struct valdec_result
*vr
)
832 if(vp
->n
<1) return 0;
835 ucstring_append_flags_item(vr
->s
, "2-d encoding");
838 ucstring_append_flags_item(vr
->s
, "uncompressed mode allowed");
841 ucstring_append_flags_item(vr
->s
, "has fill bits");
843 if((vp
->n
& ~0x7)!=0) {
844 ucstring_append_flags_item(vr
->s
, "?");
850 static int valdec_t6options(deark
*c
, const struct valdec_params
*vp
, struct valdec_result
*vr
)
852 if(vp
->n
<1) return 0;
855 ucstring_append_flags_item(vr
->s
, "uncompressed mode allowed");
857 if((vp
->n
& ~0x2)!=0) {
858 ucstring_append_flags_item(vr
->s
, "?");
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
);
873 static int valdec_pagenumber(deark
*c
, const struct valdec_params
*vp
, struct valdec_result
*vr
)
876 ucstring_printf(vr
->s
, DE_ENCODING_LATIN1
, "page %d", (int)(vp
->n
+1));
881 ucstring_append_sz(vr
->s
, "of an unknown number", DE_ENCODING_LATIN1
);
884 ucstring_printf(vr
->s
, DE_ENCODING_LATIN1
, "of %d", (int)vp
->n
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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"},
973 lookup_str_and_append_to_ucstring(name_map
, ITEMS_IN_ARRAY(name_map
), vp
->n
, vr
->s
);
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"},
988 lookup_str_and_append_to_ucstring(name_map
, ITEMS_IN_ARRAY(name_map
), vp
->n
, vr
->s
);
992 static int valdec_flash(deark
*c
, const struct valdec_params
*vp
, struct valdec_result
*vr
)
996 ucstring_append_flags_item(vr
->s
, (vp
->n
&0x01)?"flash fired":"flash did not fire");
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
, "?");
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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"},
1155 lookup_str_and_append_to_ucstring(name_map
, ITEMS_IN_ARRAY(name_map
), vp
->n
, vr
->s
);
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);
1181 handler_hexdump(c
, d
, tg
, tni
);
1185 static void handler_colormap(deark
*c
, lctx
*d
, const struct taginfo
*tg
, const struct tagnuminfo
*tni
)
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
++) {
1196 de_colorsample r2
, g2
, b2
;
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
);
1218 static void handler_subifd(deark
*c
, lctx
*d
, const struct taginfo
*tg
, const struct tagnuminfo
*tni
)
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,
1263 MAKERNOTE_APPLE_IOS
,
1267 struct makernote_id_info
{
1268 enum makernote_type mntype
;
1272 static void identify_makernote(deark
*c
, lctx
*d
, const struct taginfo
*tg
, struct makernote_id_info
*mni
)
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
));
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
));
1296 else if(!de_memcmp(buf
, "FUJIFILM", 8)) {
1297 mni
->mntype
= MAKERNOTE_FUJIFILM
;
1298 de_strlcpy(mni
->name
, "FujiFilm", sizeof(mni
->name
));
1306 static void do_makernote_nikon(deark
*c
, lctx
*d
, i64 pos1
, i64 len
)
1313 ver
= (unsigned int)de_getu16be(pos1
+6);
1314 de_dbg(c
, "version: 0x%04x", ver
); // This is a guess
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
)
1330 ver
= (unsigned int)de_getu16be(pos1
+10);
1331 de_dbg(c
, "version: 0x%04x", ver
); // This is a guess
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
)
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
);
1374 handler_hexdump(c
, d
, tg
, tni
);
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
;
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
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
));
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
)
1437 static const i64 siglen
= 36;
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
)) {
1447 else if(!dbuf_memcmp(c
->infile
, tg
->val_offset
, "Adobe Photoshop Document Data V0002\0", (size_t)siglen
)) {
1452 detiff_warn(c
, d
, tg
->pg
, "Bad or unsupported ImageSourceData tag at %d", (int)tg
->val_offset
);
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);
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,
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
{
1492 static void try_to_extract_mpf_image(deark
*c
, lctx
*d
, struct page_ctx
*pg
,
1493 struct mpfctx_struct
*mpfctx
)
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
;
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
);
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
);
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
);
1528 static void handler_mpentry(deark
*c
, lctx
*d
, const struct taginfo
*tg
, const struct tagnuminfo
*tni
)
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
1540 num_entries
= tg
->total_size
/16;
1542 s
= ucstring_create(c
);
1543 for(k
=0; k
<num_entries
; k
++) {
1545 i64 imgoffs_rel
, imgoffs_abs
;
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;
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;
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) {
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
,
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
);
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);
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
));
1647 ucstring_destroy(s
);
1651 static void handler_dngprivatedata(deark
*c
, lctx
*d
, const struct taginfo
*tg
, const struct tagnuminfo
*tni
)
1653 struct de_stringreaderdata
*srd
;
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
;
1688 static void handler_strileoffsets(deark
*c
, lctx
*d
, const struct taginfo
*tg
, const struct tagnuminfo
*tni
)
1690 struct page_ctx
*pg
= tg
->pg
;
1693 if(tni
->tagnum
==TAG_TILEOFFSETS
) {
1694 pg
->have_tile_tags
= 1;
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
;
1711 if(tni
->tagnum
==TAG_TILEBYTECOUNTS
) {
1712 pg
->have_tile_tags
= 1;
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
)
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
;
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
++) {
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
)
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
)
1785 if(ndigits
>= sizeof(buf
)) return 0;
1786 dbuf_read(f
, (u8
*)buf
, pos
, ndigits
);
1787 buf
[ndigits
] = '\0';
1792 static void parse_tiff_datetime(deark
*c
, lctx
*d
, const struct taginfo
*tg
, struct de_timestamp
*ts
)
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
);
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
;
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;
1831 case TAG_OLDSUBFILETYPE
:
1832 if(val
==2) pg
->is_thumb
= 1;
1834 case TAG_IMAGEWIDTH
:
1835 pg
->have_imagewidth
= 1;
1836 pg
->imagewidth
= val
;
1838 case TAG_IMAGELENGTH
:
1839 pg
->imagelength
= val
;
1841 case TAG_COMPRESSION
:
1842 pg
->compression
= (u32
)val
;
1844 case TAG_PHOTOMETRIC
:
1845 pg
->photometric
= (u32
)val
;
1848 pg
->fill_order
= (u32
)val
;
1850 case TAG_SAMPLESPERPIXEL
:
1851 pg
->samples_per_pixel
= (u32
)val
;
1853 case TAG_ROWSPERSTRIP
:
1854 pg
->have_strip_tags
= 1;
1855 pg
->rows_per_strip
= val
;
1858 pg
->have_tile_tags
= 1;
1859 pg
->tile_width
= val
;
1861 case TAG_TILELENGTH
:
1862 pg
->have_tile_tags
= 1;
1863 pg
->tile_height
= val
;
1865 case TAG_ORIENTATION
:
1866 if(val
>=1 && val
<=8) {
1867 pg
->orientation
= (u32
)val
;
1870 case TAG_PLANARCONFIG
:
1871 pg
->planarconfig
= (u32
)val
;
1874 pg
->t4options
= (u32
)val
;
1877 pg
->t6options
= (u32
)val
;
1879 case TAG_RESOLUTIONUNIT
:
1880 pg
->resolution_unit
= (u32
)val
;
1883 pg
->predictor
= (u32
)val
;
1885 case TAG_JPEGINTERCHANGEFORMAT
:
1886 pg
->jpegoffset
= val
;
1888 case TAG_JPEGINTERCHANGEFORMATLENGTH
:
1889 pg
->have_jpeglength
= 1;
1890 pg
->jpeglength
= val
;
1892 case TAG_YCBCRPOSITIONING
:
1893 pg
->ycbcrpositioning
= (u32
)val
;
1895 case TAG_JPEGTABLES
:
1896 pg
->have_jpegtables
= 1;
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
)
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
:
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.
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.
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
);
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;
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
2630 endpos
= tg
->val_offset
+ adj_totalsize
;
2632 ucstring_append_sz(dbgline
, " {", DE_ENCODING_LATIN1
);
2634 pos
= tg
->val_offset
;
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
);
2649 pos
+= srd
->bytes_consumed
;
2650 de_destroy_stringreaderdata(c
, srd
);
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
);
2692 do_dbg_print_text_single_value(c
, d
, tg
, tni
, dbgline
);
2696 do_dbg_print_numeric_values(c
, d
, tg
, tni
, dbgline
);
2700 static const struct tagnuminfo
*find_tagnuminfo(int tagnum
, int filefmt
, u8 ifdtype
)
2704 for(i
=0; i
<DE_ARRAYCOUNT(tagnuminfo_arr
); i
++) {
2705 if(tagnuminfo_arr
[i
].tagnum
!=tagnum
) {
2709 if(ifdtype
==IFDTYPE_EXIFINTEROP
) {
2710 // For interoperability IFDs, allow only special tags
2711 if(!(tagnuminfo_arr
[i
].flags
&0x20)) {
2715 else if(ifdtype
==IFDTYPE_GPS
) {
2716 // For GPS IFDs, allow only special tags
2717 if(!(tagnuminfo_arr
[i
].flags
&0x40)) {
2721 else if(ifdtype
==IFDTYPE_NIKONMN
) {
2722 // For this IFD, allow only special tags
2723 if(!(tagnuminfo_arr
[i
].flags
&0x1000)) {
2727 else if(ifdtype
==IFDTYPE_APPLEMN
) {
2728 // For this IFD, allow only special tags
2729 if(!(tagnuminfo_arr
[i
].flags
&0x2000)) {
2733 else if(ifdtype
==IFDTYPE_FUJIFILMMN
) {
2734 // For this IFD, allow only special tags
2735 if(!(tagnuminfo_arr
[i
].flags
&0x8000)) {
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
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
)
2761 // Ignore this tag -- it's in the wrong "namespace".
2766 return &tagnuminfo_arr
[i
];
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
;
2780 i64 strileset_xpos
, strileset_ypos
;
2781 i64 strileset_height
;
2782 i64 strileset_width
;
2783 i64 strileset_rowspan
;
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
;
2793 u8 grayscale_reverse_polarity
;
2794 u8 need_to_reverse_bits
;
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
)
2812 for(i
=0; i
<len
; i
++) {
2816 b
= dbuf_getbyte(f
, i
);
2817 if(b
==0x00 || b
==0xff) continue;
2819 for(k
=0; k
<8; 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
)
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)) {
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
);
2864 de_dfilter_destroy(dctx
->dfctx
);
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
)
2884 de_dfilter_command(dctx
->dfctx
, DE_DFILTER_COMMAND_REINITIALIZE
, 0);
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
,
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
)
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
];
2969 static int decompress_strile(deark
*c
, lctx
*d
, struct page_ctx
*pg
,
2970 struct decode_page_ctx
*dctx
, UI plane_idx
)
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
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
);
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
3011 static int decompress_strileset(deark
*c
, lctx
*d
, struct page_ctx
*pg
,
3012 struct decode_page_ctx
*dctx
)
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
;
3027 static de_colorsample
unpremultiply_alpha1(de_colorsample cval
, de_colorsample a
)
3032 if(a
==0 || cval
==0) {
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
)
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
++) {
3080 for(s_idx
=0; s_idx
<dctx
->samples_per_pixel_to_decode
; s_idx
++) {
3084 if(dctx
->is_separated
) {
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
);
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
);
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
;
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]);
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
;
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
,
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
;
3201 int can_optimize_uncompressed
= 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
);
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
);
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]");
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) {
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;
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
:"?"));
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");
3288 if(pg
->strile_count
<1) {
3289 detiff_err(c
, d
, pg
, "No image data found");
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
);
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)
3312 else if(pg
->photometric
==2) { // RGB
3313 dctx
->base_samples_per_pixel
= 3;
3314 if(pg
->bits_per_sample
==8) {
3318 else if(pg
->photometric
==3) { // paletted
3319 dctx
->base_samples_per_pixel
= 1;
3321 if(pg
->bits_per_sample
==1 || pg
->bits_per_sample
==2 || pg
->bits_per_sample
==4 ||
3322 pg
->bits_per_sample
==8)
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
));
3334 detiff_err(c
, d
, pg
, "Unsupported bits/sample (%d) for this color type", (int)pg
->bits_per_sample
);
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
);
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
);
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) {
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
;
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
;
3395 if(dctx
->has_alpha
) {
3396 dctx
->samples_per_pixel_to_decode
= (UI
)dctx
->alpha_sample_idx
+1;
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;
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
) {
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
;
3427 dctx
->width
= striles_across
* pg
->tile_width
;
3428 dctx
->height
= striles_down
* pg
->tile_height
;
3432 dctx
->strile_max_w
= dctx
->width
;
3433 dctx
->strile_max_h
= pg
->rows_per_strip
;
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
++) {
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];
3489 for(k
=0; k
<dctx
->num_planes_to_decode
; k
++) {
3491 dbuf_empty(tmp_membuf
[k
]);
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
);
3502 // TODO?: Better handling of partial failure
3503 if(dctx
->strileset_idx
>0) goto after_paint
;
3508 paint_decompressed_strile_to_image(c
, d
, pg
, dctx
, img
);
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
;
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
);
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
);
3544 detiff_err(c
, d
, pg
, "Unsupported image type or bad image");
3547 if(dctx
->dfctx
) de_dfilter_destroy(dctx
->dfctx
);
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
;
3560 de_ucstring
*dbgline
= NULL
;
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
);
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
3590 d
->current_textfield_encoding
= DE_ENCODING_ASCII
;
3592 switch(pg
->ifdtype
) {
3593 case IFDTYPE_SUBIFD
:
3596 case IFDTYPE_GLOBALPARAMS
:
3597 name
=" (Global Parameters IFD)";
3601 d
->current_textfield_encoding
= DE_ENCODING_ASCII
;
3603 case IFDTYPE_EXIFINTEROP
:
3604 name
=" (Exif Interoperability IFD)";
3605 d
->current_textfield_encoding
= DE_ENCODING_ASCII
;
3609 d
->current_textfield_encoding
= DE_ENCODING_ASCII
;
3611 case IFDTYPE_NIKONPREVIEW
:
3612 name
=" (Nikon Preview)";
3614 case IFDTYPE_MASKSUBIFD
:
3615 name
=" (Mask SubIFD)";
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
);
3632 num_tags
= (int)dbuf_geti64x(c
->infile
, pg
->ifdpos
, d
->is_le
);
3635 num_tags
= (int)dbuf_getu16x(c
->infile
, pg
->ifdpos
, d
->is_le
);
3638 de_dbg(c
, "number of tags: %d", num_tags
);
3640 detiff_warn(c
, d
, pg
, "Invalid or excessive number of TIFF tags (%d)", num_tags
);
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
));
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
;
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
);
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
,
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);
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
);
3708 de_dbg_indent(c
, -1);
3709 ucstring_destroy(dbgline
);
3711 de_free(c
, pg
->strile_data
);
3716 static void do_tiff(deark
*c
, lctx
*d
)
3721 int need_to_read_header
= 1;
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
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);
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.
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
);
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
)
3786 byte_order_sig
= de_getu16be(0);
3787 *is_le
= (byte_order_sig
== 0x4d4d) ? 0 : 1;
3790 magic
= de_getu16le(2);
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) {
3800 case 0x002a: // Standard TIFF
3801 fmt
= DE_TIFFFMT_TIFF
;
3804 fmt
= DE_TIFFFMT_BIGTIFF
;
3807 fmt
= DE_TIFFFMT_PANASONIC
;
3810 case 0x01bc: // JPEG-XR
3811 fmt
= DE_TIFFFMT_JPEGXR
;
3814 //case 0x314e: // NIFF
3817 fmt
= DE_TIFFFMT_DCP
;
3821 fmt
= DE_TIFFFMT_ORF
;
3829 static void identify_more_formats(deark
*c
, lctx
*d
)
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;
3841 if(!de_memcmp(&buf
[16], "8BIM", 4)) {
3842 d
->is_deark_8bim
= 1;
3847 if(!de_memcmp(buf
, "XEROX DIFF", 10)) {
3848 de_dbg(c
, "XIFF/XEROX DIFF format detected");
3852 if(!de_memcmp(buf
, " eXtended ", 10)) {
3853 de_dbg(c
, "XIFF/eXtended format detected");
3858 static void de_run_tiff(deark
*c
, de_module_params
*mparams
)
3862 d
= de_malloc(c
, sizeof(lctx
));
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
;
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
;
3878 de_strlcpy(d
->errmsgtoken_module
, "FujiFilm MakerNote", sizeof(d
->errmsgtoken_module
));
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
);
3904 case DE_TIFFFMT_TIFF
:
3906 de_declare_fmt(c
, "XIFF");
3908 de_declare_fmt(c
, "TIFF");
3910 case DE_TIFFFMT_BIGTIFF
:
3911 de_declare_fmt(c
, "BigTIFF");
3914 case DE_TIFFFMT_PANASONIC
:
3915 de_declare_fmt(c
, "Panasonic RAW/RW2");
3917 case DE_TIFFFMT_ORF
:
3918 de_declare_fmt(c
, "Olympus RAW");
3920 case DE_TIFFFMT_DCP
:
3921 de_declare_fmt(c
, "DNG Camera Profile");
3923 case DE_TIFFFMT_MDI
:
3924 de_declare_fmt(c
, "MDI");
3926 case DE_TIFFFMT_JPEGXR
:
3927 de_declare_fmt(c
, "JPEG XR");
3932 detiff_warn(c
, d
, NULL
, "This is not a known/supported TIFF or TIFF-like format.");
3937 d
->ifditemsize
= 20;
3938 d
->offsetoffset
= 12;
3943 d
->ifditemsize
= 12;
3944 d
->offsetoffset
= 8;
3948 d
->current_textfield_encoding
= DE_ENCODING_ASCII
;
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
;
3980 de_free(c
, d
->ifdstack
);
3981 de_inthashtable_destroy(c
, d
->ifds_seen
);
3986 static int de_identify_tiff(deark
*c
)
3991 fmt
= de_identify_tiff_internal(c
, &is_le
);
3992 if(fmt
!=0) return 100;
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
)
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
;