1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
//! TIFF 6.0 tag numbers, field-type ids, compression scheme ids,
//! photometric interpretations, and friends. Pure data, no logic.
//!
//! All numbers come from the *TIFF Revision 6.0* spec (Aldus, June
//! 1992): tags from Section 8 (Baseline Field Reference Guide), field
//! types from Section 2 (TIFF Structure / Types), compression from
//! Section 3 (Bilevel Images / Compression), photometric from
//! Section 3 (Bilevel Images / PhotometricInterpretation) plus
//! extensions in Sections 4..6.
// --- Byte-order header ---------------------------------------------------
pub const BYTE_ORDER_LE: u16 = 0x4949; // "II"
pub const BYTE_ORDER_BE: u16 = 0x4D4D; // "MM"
pub const TIFF_MAGIC: u16 = 42;
pub const BIGTIFF_MAGIC: u16 = 43;
// --- Field types (Section 2) --------------------------------------------
pub const TYPE_BYTE: u16 = 1;
pub const TYPE_ASCII: u16 = 2;
pub const TYPE_SHORT: u16 = 3;
pub const TYPE_LONG: u16 = 4;
pub const TYPE_RATIONAL: u16 = 5;
pub const TYPE_SBYTE: u16 = 6;
pub const TYPE_UNDEFINED: u16 = 7;
pub const TYPE_SSHORT: u16 = 8;
pub const TYPE_SLONG: u16 = 9;
pub const TYPE_SRATIONAL: u16 = 10;
pub const TYPE_FLOAT: u16 = 11;
pub const TYPE_DOUBLE: u16 = 12;
// BigTIFF additions (Adobe Pagemaker 6.0 → BigTIFF spec):
pub const TYPE_LONG8: u16 = 16;
pub const TYPE_SLONG8: u16 = 17;
pub const TYPE_IFD8: u16 = 18;
/// Size in bytes of a single value of the given field type. `0` for
/// unknown types (per spec, readers must skip those gracefully).
// --- Baseline tags (Section 8) ------------------------------------------
pub const TAG_NEW_SUBFILE_TYPE: u16 = 254;
pub const TAG_IMAGE_WIDTH: u16 = 256;
pub const TAG_IMAGE_LENGTH: u16 = 257;
pub const TAG_BITS_PER_SAMPLE: u16 = 258;
pub const TAG_COMPRESSION: u16 = 259;
pub const TAG_PHOTOMETRIC_INTERPRETATION: u16 = 262;
pub const TAG_FILL_ORDER: u16 = 266;
pub const TAG_STRIP_OFFSETS: u16 = 273;
pub const TAG_ORIENTATION: u16 = 274;
pub const TAG_SAMPLES_PER_PIXEL: u16 = 277;
pub const TAG_ROWS_PER_STRIP: u16 = 278;
pub const TAG_STRIP_BYTE_COUNTS: u16 = 279;
pub const TAG_X_RESOLUTION: u16 = 282;
pub const TAG_Y_RESOLUTION: u16 = 283;
pub const TAG_PLANAR_CONFIGURATION: u16 = 284;
pub const TAG_RESOLUTION_UNIT: u16 = 296;
pub const TAG_SOFTWARE: u16 = 305;
pub const TAG_DATE_TIME: u16 = 306;
pub const TAG_PREDICTOR: u16 = 317;
pub const TAG_COLOR_MAP: u16 = 320;
pub const TAG_EXTRA_SAMPLES: u16 = 338;
pub const TAG_SAMPLE_FORMAT: u16 = 339;
// --- CMYK / separated-image tags (Section 16) ---------------------------
// TIFF 6.0 §16 "CMYK Images" page 70/71:
// InkSet (tag 332, SHORT, N = 1, default 1 / CMYK)
// NumberOfInks (tag 334, SHORT, N = 1, default 4)
// `InkSet = 1` is the only writer-side value this encoder emits — the
// canonical 4-ink CMYK ordering (cyan, magenta, yellow, black). Higher-
// fidelity "more than 4 inks" separations (§16 motivation paragraph)
// would carry `InkSet = 2` plus `InkNames` (tag 333); both are out of
// scope here.
pub const TAG_INK_SET: u16 = 332;
pub const TAG_NUMBER_OF_INKS: u16 = 334;
pub const INK_SET_CMYK: u16 = 1;
// --- Tile tags (Section 15) ---------------------------------------------
pub const TAG_TILE_WIDTH: u16 = 322;
pub const TAG_TILE_LENGTH: u16 = 323;
pub const TAG_TILE_OFFSETS: u16 = 324;
pub const TAG_TILE_BYTE_COUNTS: u16 = 325;
// --- CCITT tags (Section 11) --------------------------------------------
pub const TAG_T4_OPTIONS: u16 = 292;
pub const TAG_T6_OPTIONS: u16 = 293;
// --- JPEG-in-TIFF tag (TIFF Tech Note 2 §"JPEGTables field") ------------
//
// Tag 347, type UNDEFINED. Optional. When present, holds a JPEG
// "abbreviated table specification" datastream (SOI + DQT/DHT/DRI
// markers + EOI) whose tables apply by reference to every image
// segment (strip or tile) in the IFD. Each segment is itself a
// complete JPEG datastream (SOI..EOI), so the decoder synthesises a
// per-segment input by splicing the table bytes (between the tables
// stream's SOI and EOI) in front of the segment's image bytes
// (between the segment's SOI and EOI) and prepending one SOI + one
// EOI around the merged result.
pub const TAG_JPEG_TABLES: u16 = 347;
// T4Options bits (Section 11):
pub const T4OPT_2D_CODING: u32 = 1 << 0;
pub const T4OPT_UNCOMPRESSED: u32 = 1 << 1;
pub const T4OPT_EOL_BYTE_ALIGNED: u32 = 1 << 2;
// T6Options bits (Section 11). Only bit 1 ("uncompressed mode
// allowed") is defined; bit 0 is reserved.
pub const T6OPT_UNCOMPRESSED: u32 = 1 << 1;
// --- YCbCr tags (Section 21) --------------------------------------------
pub const TAG_YCBCR_COEFFICIENTS: u16 = 529;
pub const TAG_YCBCR_SUBSAMPLING: u16 = 530;
pub const TAG_YCBCR_POSITIONING: u16 = 531;
pub const TAG_REFERENCE_BLACK_WHITE: u16 = 532;
// --- Compression schemes (Section 3 + Section 13) -----------------------
pub const COMPRESSION_NONE: u16 = 1;
pub const COMPRESSION_CCITT_HUFFMAN: u16 = 2;
pub const COMPRESSION_CCITT_T4: u16 = 3;
pub const COMPRESSION_CCITT_T6: u16 = 4;
pub const COMPRESSION_LZW: u16 = 5;
pub const COMPRESSION_JPEG_OLD: u16 = 6;
pub const COMPRESSION_JPEG_NEW: u16 = 7;
pub const COMPRESSION_DEFLATE_ADOBE: u16 = 8;
pub const COMPRESSION_PACKBITS: u16 = 32773;
/// Zstandard (RFC 8478). De-facto registry extension value — there is
/// no Adobe technical note for it; see the OxideAV trace doc
/// `docs/image/tiff/tiff-zstd-compression-50000.md`. Structurally it
/// follows the Compression=8 Deflate template: each strip / tile is
/// one self-contained Zstandard frame (magic `0x28 0xB5 0x2F 0xFD`)
/// over the post-predictor sample bytes, independent of photometric,
/// planar configuration, and bit depth. The encoder compression level
/// is an out-of-band runtime parameter, never stored in the file.
pub const COMPRESSION_ZSTD: u16 = 50000;
// --- Photometric interpretations (Section 3..6) -------------------------
pub const PHOTO_WHITE_IS_ZERO: u16 = 0;
pub const PHOTO_BLACK_IS_ZERO: u16 = 1;
pub const PHOTO_RGB: u16 = 2;
pub const PHOTO_PALETTE: u16 = 3;
pub const PHOTO_TRANSPARENCY_MASK: u16 = 4;
pub const PHOTO_CMYK: u16 = 5;
pub const PHOTO_YCBCR: u16 = 6;
pub const PHOTO_CIELAB: u16 = 8;
// --- Predictor (Section 14) ---------------------------------------------
pub const PREDICTOR_NONE: u16 = 1;
pub const PREDICTOR_HORIZONTAL: u16 = 2;
// --- SampleFormat (TIFF 6.0 §SampleFormat, tag 339 page 80) -------------
//
// TIFF 6.0 lists four sample interpretations:
//
// 1 = unsigned integer data (default; what every Baseline TIFF carries)
// 2 = two's-complement signed integer data
// 3 = IEEE floating-point data
// 4 = undefined data format (writer disclaims a known interpretation;
// readers may treat as unsigned)
//
// The §SampleFormat description ends with: "If the SampleFormat field is
// present and the value is not 1, a Baseline TIFF reader that cannot
// handle the SampleFormat value must terminate the import process
// gracefully." This decoder supports only the unsigned-integer
// interpretation, so values 2 and 3 are rejected with a precise error
// rather than silently re-interpreting signed / floating-point samples as
// unsigned bytes / words (which would produce garbage pixels). Value 4 is
// folded into 1 per the §SampleFormat note: "A reader would typically
// treat an image with 'undefined' data as if the field were not present
// (i.e. as unsigned integer data)."
pub const SAMPLE_FORMAT_UINT: u16 = 1;
pub const SAMPLE_FORMAT_SINT: u16 = 2;
pub const SAMPLE_FORMAT_IEEE_FP: u16 = 3;
pub const SAMPLE_FORMAT_UNDEFINED: u16 = 4;
// --- ExtraSamples (TIFF 6.0 §ExtraSamples, tag 338 pages 31-32) ----------
//
// "Specifies that each pixel has m extra components whose interpretation
// is defined by one of the values listed below. When this field is used,
// the SamplesPerPixel field has a value greater than the
// PhotometricInterpretation field suggests." SHORT, N = m (one value per
// extra sample). The three defined interpretations:
//
// 0 = Unspecified data
// 1 = Associated alpha data (with pre-multiplied color)
// 2 = Unassociated alpha data
//
// "By convention, extra components that are present must be stored as
// the 'last components' in each pixel," and "the size of such components
// is defined by the value of the BitsPerSample field." "The default is
// no extra samples. This field must be present if there are extra
// samples."
pub const EXTRA_SAMPLE_UNSPECIFIED: u16 = 0;
pub const EXTRA_SAMPLE_ASSOCIATED_ALPHA: u16 = 1;
pub const EXTRA_SAMPLE_UNASSOCIATED_ALPHA: u16 = 2;
// --- Planar config (Section 7) ------------------------------------------
pub const PLANAR_CHUNKY: u16 = 1;
pub const PLANAR_SEPARATE: u16 = 2;
// --- ResolutionUnit (Section 8 / "Physical Dimensions" page 18) ---------
//
// TIFF 6.0 §ResolutionUnit (tag 296, SHORT, N = 1) defines the unit of
// measurement that `XResolution` (tag 282) and `YResolution` (tag 283)
// are denominated in:
//
// 1 = No absolute unit of measurement. Used for images that may have a
// non-square aspect ratio but no meaningful absolute dimensions.
// 2 = Inch.
// 3 = Centimeter.
//
// "Default = 2 (inch)." The decoder only inspects the value for spec
// conformance — the on-disk pixel bytes are unaffected by the resolution
// metadata — so the field is treated as a passive integrity check rather
// than a feature the decoder dispatches on.
pub const RESOLUTION_UNIT_NONE: u16 = 1;
pub const RESOLUTION_UNIT_INCH: u16 = 2;
pub const RESOLUTION_UNIT_CENTIMETER: u16 = 3;