gistools/readers/geotiff/
constants.rs

1#![cfg_attr(feature = "nightly", coverage(off))]
2use alloc::{collections::BTreeMap, string::String, vec::Vec};
3
4/// TIFF Photometric Interpretations
5#[derive(Debug, Clone, Copy, PartialEq)]
6pub enum PhotometricInterpretations {
7    /// White is zero
8    WhiteIsZero = 0,
9    /// Black is zero
10    BlackIsZero = 1,
11    /// RGB
12    RGB = 2,
13    /// Palette
14    Palette = 3,
15    /// Transparency mask
16    TransparencyMask = 4,
17    /// CMYK
18    CMYK = 5,
19    /// YCbCr
20    YCbCr = 6,
21
22    /// CIELab
23    CIELab = 8,
24    /// ICCLab
25    ICCLab = 9,
26    /// ITULab
27    ITULab = 10,
28}
29impl From<i16> for PhotometricInterpretations {
30    fn from(value: i16) -> Self {
31        match value {
32            0 => PhotometricInterpretations::WhiteIsZero,
33            1 => PhotometricInterpretations::BlackIsZero,
34            2 => PhotometricInterpretations::RGB,
35            3 => PhotometricInterpretations::Palette,
36            4 => PhotometricInterpretations::TransparencyMask,
37            5 => PhotometricInterpretations::CMYK,
38            6 => PhotometricInterpretations::YCbCr,
39            8 => PhotometricInterpretations::CIELab,
40            9 => PhotometricInterpretations::ICCLab,
41            10 => PhotometricInterpretations::ITULab,
42            _ => unreachable!(),
43        }
44    }
45}
46
47/// TIFF Extra Samples
48#[derive(Debug, Clone, Copy, PartialEq)]
49pub enum ExtraSamplesValues {
50    /// Unspecified
51    Unspecified = 0,
52    /// Associated alpha
53    Assocalpha = 1,
54    /// Unassociated alpha
55    Unassalpha = 2,
56}
57impl From<u16> for ExtraSamplesValues {
58    fn from(value: u16) -> Self {
59        match value {
60            1 => ExtraSamplesValues::Assocalpha,
61            2 => ExtraSamplesValues::Unassalpha,
62            _ => ExtraSamplesValues::Unspecified,
63        }
64    }
65}
66
67/// LERC Parameters
68#[derive(Debug, Clone, Copy, PartialEq)]
69pub enum LercParameters {
70    /// LERC version
71    Version = 0,
72    /// Add compression
73    AddCompression = 1,
74}
75
76/// LERC Add Compression
77#[derive(Debug, Clone, Copy, PartialEq)]
78pub enum LercAddCompression {
79    /// No compression
80    None = 0,
81    /// Deflate
82    Deflate = 1,
83    /// Zstandard
84    Zstandard = 2,
85}
86
87/// TIFF Array Fields
88pub const ARRAY_FIELDS: [u16; 9] = [
89    FieldTagNames::BitsPerSample as u16,
90    FieldTagNames::ExtraSamples as u16,
91    FieldTagNames::SampleFormat as u16,
92    FieldTagNames::StripByteCounts as u16,
93    FieldTagNames::StripOffsets as u16,
94    FieldTagNames::StripRowCounts as u16,
95    FieldTagNames::TileByteCounts as u16,
96    FieldTagNames::TileOffsets as u16,
97    FieldTagNames::SubIFDs as u16,
98];
99
100/// All GeoTIFF keys and their u16 representations
101///
102/// Geo Key Directory:
103/// - <https://docs.ogc.org/is/19-008r4/19-008r4.html#_map_projection_methods>
104/// - <https://docs.ogc.org/is/19-008r4/19-008r4.html#_map_projection_parameters>
105/// - <https://docs.ogc.org/is/19-008r4/19-008r4.html#section-D-3>
106/// - <https://docs.ogc.org/is/19-008r4/19-008r4.html#_summary_of_geokey_ids_and_names>
107#[derive(Debug, Copy, Clone, PartialEq)]
108#[repr(u16)]
109pub enum GeoKeyDirectoryKeys {
110    /// GeoTIFF model type
111    GTModelTypeGeoKey = 1024, // SHORT (1024)
112    /// GeoTIFF raster type
113    GTRasterTypeGeoKey = 1025, // SHORT (1025)
114    /// GeoTIFF citation
115    GTCitationGeoKey = 1026, // ASCII (1026)
116    /// Geographical type
117    GeographicTypeGeoKey = 2048, // SHORT (2048)
118    /// Geographical citation
119    GeogCitationGeoKey = 2049, // ASCII (2049)
120    /// Geographical datum
121    GeogGeodeticDatumGeoKey = 2050, // SHORT (2050)
122    /// Geographical prime meridian
123    GeogPrimeMeridianGeoKey = 2051, // SHORT (2051)
124    /// Geographical linear units
125    GeogLinearUnitsGeoKey = 2052, // SHORT (2052)
126    /// Geographical linear unit size
127    GeogLinearUnitSizeGeoKey = 2053, // DOUBLE (2053)
128    /// Geographical angular units
129    GeogAngularUnitsGeoKey = 2054, // SHORT (2054)
130    /// Geographical angular unit size
131    GeogAngularUnitSizeGeoKey = 2055, // DOUBLE (2055)
132    /// Geographical ellipsoid
133    GeogEllipsoidGeoKey = 2056, // SHORT (2056)
134    /// Geographical semi-major axis
135    GeogSemiMajorAxisGeoKey = 2057, // DOUBLE (2057)
136    /// Geographical semi-minor axis
137    GeogSemiMinorAxisGeoKey = 2058, // DOUBLE (2058)
138    /// Geographical inverse flattening
139    GeogInvFlatteningGeoKey = 2059, // DOUBLE (2059)
140    /// Geographical azimuth
141    GeogAzimuthUnitsGeoKey = 2060, // SHORT (2060)
142    /// Geographical prime meridian
143    GeogPrimeMeridianLongGeoKey = 2061, // DOUBLE (2061)
144    /// Geographical TOWGS84
145    GeogTOWGS84GeoKey = 2062, // DOUBLE (2062)
146    /// Projected type
147    ProjectedCSTypeGeoKey = 3072, // SHORT (3072)
148    /// Projected citation
149    PCSCitationGeoKey = 3073, // ASCII (3073)
150    /// Projection
151    ProjectionGeoKey = 3074, // SHORT (3074)
152    /// Projection coordinate transformation
153    ProjCoordTransGeoKey = 3075, // SHORT (3075)
154    /// Projection linear units
155    ProjLinearUnitsGeoKey = 3076, // SHORT (3076)
156    /// Projection linear unit size
157    ProjLinearUnitSizeGeoKey = 3077, // DOUBLE (3077)
158    /// Projection standard parallel
159    ProjStdParallel1GeoKey = 3078, // DOUBLE (3078)
160    /// Projection standard parallel
161    ProjStdParallel2GeoKey = 3079, // DOUBLE (3079)
162    /// Projection natural origin
163    ProjNatOriginLongGeoKey = 3080, // DOUBLE (3080)
164    /// Projection natural origin
165    ProjNatOriginLatGeoKey = 3081, // DOUBLE (3081)
166    /// Projection false easting
167    ProjFalseEastingGeoKey = 3082, // DOUBLE (3082)
168    /// Projection false northing
169    ProjFalseNorthingGeoKey = 3083, // DOUBLE (3083)
170    /// Projection false origin
171    ProjFalseOriginLongGeoKey = 3084, // DOUBLE (3084)
172    /// Projection false origin
173    ProjFalseOriginLatGeoKey = 3085, // DOUBLE (3085)
174    /// Projection false origin
175    ProjFalseOriginEastingGeoKey = 3086, // DOUBLE (3086)
176    /// Projection false origin
177    ProjFalseOriginNorthingGeoKey = 3087, // DOUBLE (3087)
178    /// Projection center lon
179    ProjCenterLongGeoKey = 3088, // DOUBLE (3088)
180    /// Projection center lat
181    ProjCenterLatGeoKey = 3089, // DOUBLE (3089)
182    /// Projection center easting
183    ProjCenterEastingGeoKey = 3090, // DOUBLE (3090)
184    /// Projection center northing
185    ProjCenterNorthingGeoKey = 3091, // DOUBLE (3091)
186    /// Projection scale at natural origin
187    ProjScaleAtNatOriginGeoKey = 3092, // DOUBLE (3092)
188    /// Projection scale at center
189    ProjScaleAtCenterGeoKey = 3093, // DOUBLE (3093)
190    /// Projection azimuth angle
191    ProjAzimuthAngleGeoKey = 3094, // DOUBLE (3094)
192    /// Projection straight vertical pole
193    ProjStraightVertPoleLongGeoKey = 3095, // DOUBLE (3095)
194    /// Rectified grid angle
195    ProjRectifiedGridAngleGeoKey = 3096, // DOUBLE (3096)
196    /// Projection CS type
197    VerticalCSTypeGeoKey = 4096, // SHORT (4096)
198    /// Vertical citation
199    VerticalCitationGeoKey = 4097, // ASCII (4097)
200    /// Vertical datum
201    VerticalDatumGeoKey = 4098, // SHORT (4098)
202    /// Vertical units
203    VerticalUnitsGeoKey = 4099, // SHORT (4099)
204}
205impl GeoKeyDirectoryKeys {
206    /// Convert a key to a TIFF type
207    pub fn to_type(key: GeoKeyDirectoryKeys) -> GeoTIFFTypes {
208        match key {
209            GeoKeyDirectoryKeys::GTModelTypeGeoKey
210            | GeoKeyDirectoryKeys::GTRasterTypeGeoKey
211            | GeoKeyDirectoryKeys::GeographicTypeGeoKey
212            | GeoKeyDirectoryKeys::GeogGeodeticDatumGeoKey
213            | GeoKeyDirectoryKeys::GeogPrimeMeridianGeoKey
214            | GeoKeyDirectoryKeys::GeogLinearUnitsGeoKey
215            | GeoKeyDirectoryKeys::GeogAngularUnitsGeoKey
216            | GeoKeyDirectoryKeys::GeogEllipsoidGeoKey
217            | GeoKeyDirectoryKeys::GeogAzimuthUnitsGeoKey
218            | GeoKeyDirectoryKeys::ProjectedCSTypeGeoKey
219            | GeoKeyDirectoryKeys::ProjectionGeoKey
220            | GeoKeyDirectoryKeys::ProjCoordTransGeoKey
221            | GeoKeyDirectoryKeys::ProjLinearUnitsGeoKey
222            | GeoKeyDirectoryKeys::VerticalCSTypeGeoKey
223            | GeoKeyDirectoryKeys::VerticalDatumGeoKey
224            | GeoKeyDirectoryKeys::VerticalUnitsGeoKey => GeoTIFFTypes::SHORT,
225            GeoKeyDirectoryKeys::GTCitationGeoKey
226            | GeoKeyDirectoryKeys::GeogCitationGeoKey
227            | GeoKeyDirectoryKeys::PCSCitationGeoKey
228            | GeoKeyDirectoryKeys::VerticalCitationGeoKey => GeoTIFFTypes::ASCII,
229            _ => GeoTIFFTypes::DOUBLE,
230        }
231    }
232}
233
234/// TIFF Field Types
235#[derive(Debug, Default, Clone, Copy, PartialEq)]
236pub enum GeoTIFFTypes {
237    /// Byte
238    #[default]
239    BYTE = 0x0001,
240    /// ASCII
241    ASCII = 0x0002,
242    /// Short
243    SHORT = 0x0003,
244    /// Long
245    LONG = 0x0004,
246    /// Rational
247    RATIONAL = 0x0005,
248    /// Signed byte
249    SBYTE = 0x0006,
250    /// Undefined
251    UNDEFINED = 0x0007,
252    /// Signed short
253    SSHORT = 0x0008,
254    /// Signed long
255    SLONG = 0x0009,
256    /// Signed rational
257    SRATIONAL = 0x000a,
258    /// Float
259    FLOAT = 0x000b,
260    /// Double
261    DOUBLE = 0x000c,
262    /// IFD offset, suggested by <https://owl.phy.queensu.ca/~phil/exiftool/standards.html>
263    IFD = 0x000d,
264    // introduced by BigTIFF
265    /// Long
266    LONG8 = 0x0010,
267    /// Signed long
268    SLONG8 = 0x0011,
269    /// IFD offset
270    IFD8 = 0x0012,
271}
272impl GeoTIFFTypes {
273    /// Return the size of the type
274    pub fn to_size(&self) -> usize {
275        match self {
276            GeoTIFFTypes::BYTE
277            | GeoTIFFTypes::ASCII
278            | GeoTIFFTypes::SBYTE
279            | GeoTIFFTypes::UNDEFINED => 1,
280            GeoTIFFTypes::SHORT | GeoTIFFTypes::SSHORT => 2,
281            GeoTIFFTypes::LONG | GeoTIFFTypes::SLONG | GeoTIFFTypes::FLOAT | GeoTIFFTypes::IFD => 4,
282            GeoTIFFTypes::RATIONAL
283            | GeoTIFFTypes::SRATIONAL
284            | GeoTIFFTypes::DOUBLE
285            | GeoTIFFTypes::LONG8
286            | GeoTIFFTypes::SLONG8
287            | GeoTIFFTypes::IFD8 => 8,
288        }
289    }
290}
291impl From<u16> for GeoTIFFTypes {
292    fn from(value: u16) -> Self {
293        match value {
294            0x0001 => GeoTIFFTypes::BYTE,
295            0x0002 => GeoTIFFTypes::ASCII,
296            0x0003 => GeoTIFFTypes::SHORT,
297            0x0004 => GeoTIFFTypes::LONG,
298            0x0005 => GeoTIFFTypes::RATIONAL,
299            0x0006 => GeoTIFFTypes::SBYTE,
300            0x0007 => GeoTIFFTypes::UNDEFINED,
301            0x0008 => GeoTIFFTypes::SSHORT,
302            0x0009 => GeoTIFFTypes::SLONG,
303            0x000a => GeoTIFFTypes::SRATIONAL,
304            0x000b => GeoTIFFTypes::FLOAT,
305            0x000c => GeoTIFFTypes::DOUBLE,
306            0x000d => GeoTIFFTypes::IFD,
307            0x0010 => GeoTIFFTypes::LONG8,
308            0x0011 => GeoTIFFTypes::SLONG8,
309            0x0012 => GeoTIFFTypes::IFD8,
310            _ => GeoTIFFTypes::UNDEFINED,
311        }
312    }
313}
314
315/// A GeoTIFF store system
316#[derive(Debug, Clone, Default, PartialEq)]
317pub struct GeoStore {
318    /// Internal data
319    pub data: BTreeMap<u16, (Vec<u8>, GeoTIFFTypes)>,
320}
321impl GeoStore {
322    /// len
323    pub fn len(&self) -> usize {
324        self.data.len()
325    }
326    /// empty
327    pub fn is_empty(&self) -> bool {
328        self.len() == 0
329    }
330    /// has key
331    pub fn has(&self, key: u16) -> bool {
332        self.data.contains_key(&key)
333    }
334    /// Common function name
335    pub fn insert(&mut self, key: u16, value: Vec<u8>, field_type: GeoTIFFTypes) {
336        self.data.insert(key, (value, field_type));
337    }
338    /// Set a value
339    pub fn set(&mut self, key: u16, value: Vec<u8>, field_type: GeoTIFFTypes) {
340        self.data.insert(key, (value, field_type));
341    }
342    /// Get a value
343    pub fn get(&self, key: u16) -> Option<(Vec<u8>, GeoTIFFTypes)> {
344        self.data.get(&key).cloned()
345    }
346    /// Set a short
347    pub fn set_short(&mut self, key: u16, value: i16) {
348        self.set(key, value.to_le_bytes().to_vec(), GeoTIFFTypes::SHORT);
349    }
350    /// Get a short
351    pub fn get_short(&self, key: u16) -> Option<i16> {
352        // self.get(key).map(|(v, _)| i16::from_le_bytes(v.try_into().unwrap()))
353        self.get(key).map(|(v, r#type)| match r#type {
354            GeoTIFFTypes::BYTE => v[0] as i16,
355            GeoTIFFTypes::SHORT => i16::from_le_bytes(v.try_into().unwrap()),
356            GeoTIFFTypes::SBYTE => v[0] as i16,
357            GeoTIFFTypes::SSHORT => i16::from_le_bytes(v.try_into().unwrap()),
358            _ => panic!("Invalid type"),
359        })
360    }
361    /// Set a string
362    pub fn set_string(&mut self, key: u16, value: String) {
363        self.set(key, value.as_bytes().to_vec(), GeoTIFFTypes::ASCII);
364    }
365    /// Get a string
366    pub fn get_string(&self, key: u16) -> Option<String> {
367        self.get(key).map(|(v, _)| String::from_utf8_lossy(&v[..v.len().saturating_sub(1)]).into())
368    }
369    /// Set a double
370    pub fn set_double(&mut self, key: u16, value: f64) {
371        self.set(key, value.to_le_bytes().to_vec(), GeoTIFFTypes::DOUBLE);
372    }
373    /// Get a double
374    pub fn get_double(&self, key: u16) -> Option<f64> {
375        // // TODO: This is cool because we can fix this
376        // self.get(key).map(|(v, r#type)| {
377        //     if v.len() == 1 {
378        //         v[0] as f64
379        //     } else {
380        //         f64::from_le_bytes(v.try_into().unwrap_or([0; 8]))
381        //     }
382        // })
383        self.get(key).map(|(v, r#type)| match r#type {
384            GeoTIFFTypes::BYTE => v[0] as f64,
385            GeoTIFFTypes::SHORT => u16::from_le_bytes(v.try_into().unwrap_or([0; 2])) as f64,
386            GeoTIFFTypes::LONG | GeoTIFFTypes::RATIONAL => {
387                u32::from_le_bytes(v.try_into().unwrap_or([0; 4])) as f64
388            }
389            GeoTIFFTypes::SBYTE => v[0] as i8 as f64,
390            GeoTIFFTypes::SSHORT => i16::from_le_bytes(v.try_into().unwrap_or([0; 2])) as f64,
391            GeoTIFFTypes::SLONG | GeoTIFFTypes::SRATIONAL => {
392                i32::from_le_bytes(v.try_into().unwrap_or([0; 4])) as f64
393            }
394            GeoTIFFTypes::FLOAT => f32::from_le_bytes(v.try_into().unwrap_or([0; 4])) as f64,
395            GeoTIFFTypes::DOUBLE => f64::from_le_bytes(v.try_into().unwrap_or([0; 8])),
396            _ => panic!("Invalid type"),
397        })
398    }
399
400    /// get u16 array
401    pub fn get_u16s(&self, key: u16) -> Option<Vec<u16>> {
402        self.get(key).map(|(v, r#type)| match r#type {
403            GeoTIFFTypes::BYTE => v.iter().map(|chunk| *chunk as u16).collect(),
404            GeoTIFFTypes::SHORT => {
405                v.chunks(2).map(|chunk| u16::from_le_bytes(chunk.try_into().unwrap())).collect()
406            }
407            _ => panic!("Invalid type"),
408        })
409    }
410    /// get u32 array
411    pub fn get_u32s(&self, key: u16) -> Option<Vec<u32>> {
412        self.get(key).map(|(v, r#type)| match r#type {
413            GeoTIFFTypes::BYTE => v.iter().map(|chunk| *chunk as u32).collect(),
414            GeoTIFFTypes::SHORT => v
415                .chunks(2)
416                .map(|chunk| u16::from_le_bytes(chunk.try_into().unwrap()) as u32)
417                .collect(),
418            GeoTIFFTypes::LONG | GeoTIFFTypes::RATIONAL => {
419                v.chunks(4).map(|chunk| u32::from_le_bytes(chunk.try_into().unwrap())).collect()
420            }
421            GeoTIFFTypes::LONG8 => v
422                .chunks(8)
423                .map(|chunk| u64::from_le_bytes(chunk.try_into().unwrap()) as u32)
424                .collect(),
425            _ => panic!("Invalid type: {:?}", r#type),
426        })
427    }
428    /// get u64 array
429    pub fn get_u64s(&self, key: u16) -> Option<Vec<u64>> {
430        self.get(key).map(|(v, r#type)| match r#type {
431            GeoTIFFTypes::BYTE => v.iter().map(|chunk| *chunk as u64).collect(),
432            GeoTIFFTypes::SHORT => v
433                .chunks(2)
434                .map(|chunk| u16::from_le_bytes(chunk.try_into().unwrap()) as u64)
435                .collect(),
436            GeoTIFFTypes::LONG | GeoTIFFTypes::RATIONAL => v
437                .chunks(4)
438                .map(|chunk| u32::from_le_bytes(chunk.try_into().unwrap()) as u64)
439                .collect(),
440            GeoTIFFTypes::LONG8 => {
441                v.chunks(8).map(|chunk| u64::from_le_bytes(chunk.try_into().unwrap())).collect()
442            }
443            _ => panic!("Invalid type: {:?}", r#type),
444        })
445    }
446    /// get i16 array
447    pub fn geti16s(&self, key: u16) -> Option<Vec<i16>> {
448        self.get(key).map(|(v, r#type)| match r#type {
449            GeoTIFFTypes::SBYTE => v.iter().map(|chunk| *chunk as i16).collect(),
450            GeoTIFFTypes::SSHORT => {
451                v.chunks(2).map(|chunk| i16::from_le_bytes(chunk.try_into().unwrap())).collect()
452            }
453            _ => panic!("Invalid type"),
454        })
455    }
456    /// get i32 array
457    pub fn geti32s(&self, key: u16) -> Option<Vec<i32>> {
458        self.get(key).map(|(v, r#type)| match r#type {
459            GeoTIFFTypes::SBYTE => v.iter().map(|chunk| *chunk as i32).collect(),
460            GeoTIFFTypes::SSHORT => v
461                .chunks(2)
462                .map(|chunk| i16::from_le_bytes(chunk.try_into().unwrap()) as i32)
463                .collect(),
464            GeoTIFFTypes::SLONG | GeoTIFFTypes::SRATIONAL => {
465                v.chunks(4).map(|chunk| i32::from_le_bytes(chunk.try_into().unwrap())).collect()
466            }
467            _ => panic!("Invalid type: {:?}", r#type),
468        })
469    }
470    /// get i64 array
471    pub fn geti64s(&self, key: u16) -> Option<Vec<i64>> {
472        self.get(key).map(|(v, r#type)| match r#type {
473            GeoTIFFTypes::SBYTE => v.iter().map(|chunk| *chunk as i64).collect(),
474            GeoTIFFTypes::SSHORT => v
475                .chunks(2)
476                .map(|chunk| i16::from_le_bytes(chunk.try_into().unwrap()) as i64)
477                .collect(),
478            GeoTIFFTypes::SLONG | GeoTIFFTypes::SRATIONAL => v
479                .chunks(4)
480                .map(|chunk| i32::from_le_bytes(chunk.try_into().unwrap()) as i64)
481                .collect(),
482            GeoTIFFTypes::SLONG8 => {
483                v.chunks(8).map(|chunk| i64::from_le_bytes(chunk.try_into().unwrap())).collect()
484            }
485            _ => panic!("Invalid type: {:?}", r#type),
486        })
487    }
488    /// get f32 array
489    pub fn getf32s(&self, key: u16) -> Option<Vec<f32>> {
490        self.get(key).map(|(v, r#type)| match r#type {
491            GeoTIFFTypes::BYTE => v.iter().map(|chunk| *chunk as f32).collect(),
492            GeoTIFFTypes::SHORT => v
493                .chunks(2)
494                .map(|chunk| u16::from_le_bytes(chunk.try_into().unwrap()) as f32)
495                .collect(),
496            GeoTIFFTypes::LONG | GeoTIFFTypes::RATIONAL => v
497                .chunks(4)
498                .map(|chunk| u32::from_le_bytes(chunk.try_into().unwrap()) as f32)
499                .collect(),
500            GeoTIFFTypes::SBYTE => v.iter().map(|chunk| *chunk as f32).collect(),
501            GeoTIFFTypes::SSHORT => v
502                .chunks(2)
503                .map(|chunk| i16::from_le_bytes(chunk.try_into().unwrap()) as f32)
504                .collect(),
505            GeoTIFFTypes::SLONG | GeoTIFFTypes::SRATIONAL => v
506                .chunks(4)
507                .map(|chunk| i32::from_le_bytes(chunk.try_into().unwrap()) as f32)
508                .collect(),
509            GeoTIFFTypes::FLOAT => {
510                v.chunks(4).map(|chunk| f32::from_le_bytes(chunk.try_into().unwrap())).collect()
511            }
512            _ => panic!("Invalid type: {:?}", r#type),
513        })
514    }
515    /// get f64 array
516    pub fn getf64s(&self, key: u16) -> Option<Vec<f64>> {
517        self.get(key).map(|(v, r#type)| match r#type {
518            GeoTIFFTypes::BYTE => v.iter().map(|chunk| *chunk as f64).collect(),
519            GeoTIFFTypes::SHORT => v
520                .chunks(2)
521                .map(|chunk| u16::from_le_bytes(chunk.try_into().unwrap()) as f64)
522                .collect(),
523            GeoTIFFTypes::LONG | GeoTIFFTypes::RATIONAL => v
524                .chunks(4)
525                .map(|chunk| u32::from_le_bytes(chunk.try_into().unwrap()) as f64)
526                .collect(),
527            GeoTIFFTypes::SBYTE => v.iter().map(|chunk| *chunk as f64).collect(),
528            GeoTIFFTypes::SSHORT => v
529                .chunks(2)
530                .map(|chunk| i16::from_le_bytes(chunk.try_into().unwrap()) as f64)
531                .collect(),
532            GeoTIFFTypes::SLONG | GeoTIFFTypes::SRATIONAL => v
533                .chunks(4)
534                .map(|chunk| i32::from_le_bytes(chunk.try_into().unwrap()) as f64)
535                .collect(),
536            GeoTIFFTypes::FLOAT => v
537                .chunks(4)
538                .map(|chunk| f32::from_le_bytes(chunk.try_into().unwrap()) as f64)
539                .collect(),
540            GeoTIFFTypes::DOUBLE => {
541                v.chunks(8).map(|chunk| f64::from_le_bytes(chunk.try_into().unwrap())).collect()
542            }
543            _ => panic!("Invalid type: {:?}", r#type),
544        })
545    }
546}
547
548/// List of Tag Names
549#[allow(non_snake_case)]
550#[derive(Debug, Clone, Copy, PartialEq)]
551#[repr(u16)]
552pub enum FieldTagNames {
553    // TIFF Baseline
554    /// Artist
555    Artist = 0x013b,
556    /// BitsPerSample (u16 array)
557    BitsPerSample = 0x0102,
558    /// CellLength
559    CellLength = 0x0109,
560    /// CellWidth
561    CellWidth = 0x0108,
562    /// ColorMap
563    ColorMap = 0x0140,
564    /// Compression (short)
565    Compression = 0x0103,
566    /// Copyright
567    Copyright = 0x8298,
568    /// DateTime
569    DateTime = 0x0132,
570    /// ExtraSamples
571    ExtraSamples = 0x0152,
572    /// FillOrder
573    FillOrder = 0x010a,
574    /// FreeByteCounts
575    FreeByteCounts = 0x0121,
576    /// FreeOffsets
577    FreeOffsets = 0x0120,
578    /// GrayResponseCurve
579    GrayResponseCurve = 0x0123,
580    /// GrayResponseUnit
581    GrayResponseUnit = 0x0122,
582    /// HostComputer
583    HostComputer = 0x013c,
584    /// ImageDescription (ascii)
585    ImageDescription = 0x010e,
586    /// ImageLength (short)
587    ImageLength = 0x0101,
588    /// ImageWidth (short)
589    ImageWidth = 0x0100,
590    /// Make
591    Make = 0x010f,
592    /// MaxSampleValue
593    MaxSampleValue = 0x0119,
594    /// MinSampleValue
595    MinSampleValue = 0x0118,
596    /// Model
597    Model = 0x0110,
598    /// NewSubfileType
599    NewSubfileType = 0x00fe,
600    /// Orientation
601    Orientation = 0x0112,
602    /// PhotometricInterpretation (short)
603    PhotometricInterpretation = 0x0106,
604    /// PlanarConfiguration
605    PlanarConfiguration = 0x011c,
606    /// ResolutionUnit (short)
607    ResolutionUnit = 0x0128,
608    /// RowsPerStrip (short)
609    RowsPerStrip = 0x0116,
610    /// SamplesPerPixel (short)
611    SamplesPerPixel = 0x0115,
612    /// Software
613    Software = 0x0131,
614    /// StripByteCounts (U32 array)
615    StripByteCounts = 0x0117,
616    /// StripOffsets (U32 array)
617    StripOffsets = 0x0111,
618    /// SubfileType
619    SubfileType = 0x00ff,
620    /// Threshholding
621    Threshholding = 0x0107,
622    /// XResolution ([u32, u32]) - u32s array
623    XResolution = 0x011a,
624    /// YResolution ([u32, u32]) - u32s array
625    YResolution = 0x011b,
626
627    // TIFF Extended
628    /// BadFaxLines
629    BadFaxLines = 0x0146,
630    /// CleanFaxData
631    CleanFaxData = 0x0147,
632    /// ClipPath
633    ClipPath = 0x0157,
634    /// ConsecutiveBadFaxLines
635    ConsecutiveBadFaxLines = 0x0148,
636    /// Decode
637    Decode = 0x01b1,
638    /// DefaultImageColor
639    DefaultImageColor = 0x01b2,
640    /// DocumentName
641    DocumentName = 0x010d,
642    /// DotRange
643    DotRange = 0x0150,
644    /// HalftoneHints
645    HalftoneHints = 0x0141,
646    /// Indexed
647    Indexed = 0x015a,
648    /// JPEGTables
649    JPEGTables = 0x015b,
650    /// PageName
651    PageName = 0x011d,
652    /// PageNumber
653    PageNumber = 0x0129,
654    /// Predictor (short)
655    Predictor = 0x013d,
656    /// PrimaryChromaticities
657    PrimaryChromaticities = 0x013f,
658    /// ReferenceBlackWhite
659    ReferenceBlackWhite = 0x0214,
660    /// SampleFormat
661    SampleFormat = 0x0153,
662    /// SMinSampleValue
663    SMinSampleValue = 0x0154,
664    /// SMaxSampleValue
665    SMaxSampleValue = 0x0155,
666    /// StripRowCounts
667    StripRowCounts = 0x022f,
668    /// SubIFDs
669    SubIFDs = 0x014a,
670    /// T4Options
671    T4Options = 0x0124,
672    /// T6Options
673    T6Options = 0x0125,
674    /// TileByteCounts
675    TileByteCounts = 0x0145,
676    /// TileLength
677    TileLength = 0x0143,
678    /// TileOffsets
679    TileOffsets = 0x0144,
680    /// TileWidth
681    TileWidth = 0x0142,
682    /// TransferFunction
683    TransferFunction = 0x012d,
684    /// WhitePoint
685    WhitePoint = 0x013e,
686    /// XClipPathUnits
687    XClipPathUnits = 0x0158,
688    /// XPosition
689    XPosition = 0x011e,
690    /// YCbCrCoefficients
691    YCbCrCoefficients = 0x0211,
692    /// YCbCrPositioning
693    YCbCrPositioning = 0x0213,
694    /// YCbCrSubSampling
695    YCbCrSubSampling = 0x0212,
696    /// YClipPathUnits
697    YClipPathUnits = 0x0159,
698    /// YPosition
699    YPosition = 0x011f,
700
701    // EXIF
702    /// ApertureValue
703    ApertureValue = 0x9202,
704    /// ColorSpace
705    ColorSpace = 0xa001,
706    /// DateTimeDigitized
707    DateTimeDigitized = 0x9004,
708    /// DateTimeOriginal
709    DateTimeOriginal = 0x9003,
710    /// Exif IFD
711    ExifIFD = 0x8769,
712    /// ExifVersion
713    ExifVersion = 0x9000,
714    /// ExposureTime
715    ExposureTime = 0x829a,
716    /// FileSource
717    FileSource = 0xa300,
718    /// Flash
719    Flash = 0x9209,
720    /// FlashpixVersion
721    FlashpixVersion = 0xa000,
722    /// FNumber
723    FNumber = 0x829d,
724    /// ImageUniqueID
725    ImageUniqueID = 0xa420,
726    /// LightSource
727    LightSource = 0x9208,
728    /// MakerNote
729    MakerNote = 0x927c,
730    /// ShutterSpeedValue
731    ShutterSpeedValue = 0x9201,
732    /// UserComment
733    UserComment = 0x9286,
734
735    // IPTC
736    /// IPTC
737    IPTC = 0x83bb,
738
739    // ICC
740    /// ICC Profile
741    ICC = 0x8773,
742
743    // XMP
744    /// XMP
745    XMP = 0x02bc,
746
747    // GDAL
748    /// GDAL_METADATA
749    GdalMetadata = 0xa480,
750    /// GDAL_NODATA
751    GdalNodata = 0xa481,
752
753    // Photoshop
754    /// Photoshop
755    Photoshop = 0x8649,
756
757    // GeoTiff
758    /// ModelPixelScale
759    ModelPixelScale = 0x830e,
760    /// ModelTiepoint
761    ModelTiepoint = 0x8482,
762    /// ModelTransformation
763    ModelTransformation = 0x85d8,
764    /// GeoKeyDirectory
765    GeoKeyDirectory = 0x87af,
766    /// GeoDoubleParams
767    GeoDoubleParams = 0x87b0,
768    /// GeoAsciiParams
769    GeoAsciiParams = 0x87b1,
770
771    // LERC
772    /// LercParameters
773    LercParameters = 0xc5f2,
774}