raster/geotiff/tiff_format.h
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /// @file | ||
| 2 | /// @brief TIFF and GeoTIFF numbers shared by the GeoTIFF reader and writer. | ||
| 3 | #pragma once | ||
| 4 | |||
| 5 | #include "terraingen/raster/geo_transform.h" | ||
| 6 | #include "terraingen/raster/geotiff/geotiff.h" | ||
| 7 | |||
| 8 | #include <bit> | ||
| 9 | #include <cstddef> | ||
| 10 | #include <cstdint> | ||
| 11 | #include <optional> | ||
| 12 | #include <vector> | ||
| 13 | |||
| 14 | namespace terraingen::detail { | ||
| 15 | |||
| 16 | static_assert(std::endian::native == std::endian::little, | ||
| 17 | "The GeoTIFF reader and writer assume a little-endian host"); | ||
| 18 | |||
| 19 | /// TIFF tags read or written. | ||
| 20 | enum Tag : std::uint16_t { | ||
| 21 | kImageWidth = 256, | ||
| 22 | kImageLength = 257, | ||
| 23 | kBitsPerSample = 258, | ||
| 24 | kCompression = 259, | ||
| 25 | kPhotometric = 262, | ||
| 26 | kStripOffsets = 273, | ||
| 27 | kSamplesPerPixel = 277, | ||
| 28 | kRowsPerStrip = 278, | ||
| 29 | kStripByteCounts = 279, | ||
| 30 | kPlanarConfiguration = 284, | ||
| 31 | kPredictor = 317, | ||
| 32 | kTileWidth = 322, | ||
| 33 | kTileLength = 323, | ||
| 34 | kTileOffsets = 324, | ||
| 35 | kTileByteCounts = 325, | ||
| 36 | kExtraSamples = 338, | ||
| 37 | kSampleFormat = 339, | ||
| 38 | kModelPixelScale = 33550, | ||
| 39 | kModelTiepoint = 33922, | ||
| 40 | kModelTransformation = 34264, | ||
| 41 | kGeoKeyDirectory = 34735, | ||
| 42 | kGeoDoubleParams = 34736, | ||
| 43 | kGeoAsciiParams = 34737, | ||
| 44 | kGdalMetadata = 42112, | ||
| 45 | kGdalNoData = 42113, | ||
| 46 | }; | ||
| 47 | |||
| 48 | /// TIFF field types. | ||
| 49 | enum FieldType : std::uint16_t { | ||
| 50 | kByte = 1, | ||
| 51 | kAscii = 2, | ||
| 52 | kShort = 3, | ||
| 53 | kLong = 4, | ||
| 54 | kRational = 5, | ||
| 55 | kSByte = 6, | ||
| 56 | kUndefined = 7, | ||
| 57 | kSShort = 8, | ||
| 58 | kSLong = 9, | ||
| 59 | kSRational = 10, | ||
| 60 | kFloat = 11, | ||
| 61 | kDouble = 12, | ||
| 62 | kLong8 = 16, | ||
| 63 | kSLong8 = 17, | ||
| 64 | kIfd8 = 18, | ||
| 65 | }; | ||
| 66 | |||
| 67 | /// Values of the Compression tag. | ||
| 68 | enum CompressionCode : std::uint16_t { | ||
| 69 | kCompressionNone = 1, | ||
| 70 | kCompressionLzw = 5, | ||
| 71 | kCompressionDeflate = 8, | ||
| 72 | kCompressionAdobeDeflate = 32946, | ||
| 73 | kCompressionPackBits = 32773, | ||
| 74 | }; | ||
| 75 | |||
| 76 | /// GeoKey numbers from OGC 19-008r4. | ||
| 77 | enum GeoKey : std::uint16_t { | ||
| 78 | kGtModelTypeGeoKey = 1024, | ||
| 79 | kGtRasterTypeGeoKey = 1025, | ||
| 80 | kGeographicTypeGeoKey = 2048, | ||
| 81 | kGeogGeodeticDatumGeoKey = 2050, | ||
| 82 | kGeogAngularUnitsGeoKey = 2054, | ||
| 83 | kGeogEllipsoidGeoKey = 2056, | ||
| 84 | kGeogSemiMajorAxisGeoKey = 2057, | ||
| 85 | kGeogSemiMinorAxisGeoKey = 2058, | ||
| 86 | }; | ||
| 87 | |||
| 88 | constexpr std::uint16_t kModelTypeGeographic = 2; ///< GTModelTypeGeoKey value. | ||
| 89 | constexpr std::uint16_t kRasterPixelIsArea = 1; ///< GTRasterTypeGeoKey value. | ||
| 90 | constexpr std::uint16_t kRasterPixelIsPoint = 2; ///< GTRasterTypeGeoKey value. | ||
| 91 | constexpr std::uint16_t kUserDefined = 32767; ///< A user-defined CRS, datum or ellipsoid. | ||
| 92 | constexpr std::uint16_t kAngularDegree = 9102; ///< GeogAngularUnitsGeoKey value. | ||
| 93 | |||
| 94 | /// The size in bytes of one value of a TIFF field type code, or 0 for an unknown type. | ||
| 95 | std::size_t FieldSize(std::uint16_t type); | ||
| 96 | |||
| 97 | /// The compression a Compression tag value names, or nothing for a scheme this library does not | ||
| 98 | /// decode. | ||
| 99 | std::optional<TiffCompression> CompressionFromCode(std::uint64_t code); | ||
| 100 | |||
| 101 | /// The Compression tag value written for `compression`; Deflate is written as code 8. | ||
| 102 | std::uint16_t CompressionCodeOf(TiffCompression compression); | ||
| 103 | |||
| 104 | /// The sizes of IFD fields in classic TIFF or BigTIFF. | ||
| 105 | struct IfdFormat { | ||
| 106 | std::size_t countSize; ///< Size of the entry count before the entries. | ||
| 107 | std::size_t wordSize; ///< Size of a value count, an inline value and an offset. | ||
| 108 | |||
| 109 | /// The format of classic TIFF (`bigTiff` false) or BigTIFF. | ||
| 110 | 862 | static constexpr IfdFormat For(bool bigTiff) { | |
| 111 | 862 | return bigTiff ? IfdFormat{8, 8} : IfdFormat{2, 4}; | |
| 112 | } | ||
| 113 | |||
| 114 | /// The size in bytes of one entry: tag, type, count and value or offset. | ||
| 115 | 9467 | constexpr std::size_t EntrySize() const { | |
| 116 | 9467 | return 4 + 2 * wordSize; | |
| 117 | } | ||
| 118 | |||
| 119 | /// The byte offset within an entry where its value or offset starts. | ||
| 120 | 8912 | constexpr std::size_t ValueAt() const { | |
| 121 | 8912 | return 4 + wordSize; | |
| 122 | } | ||
| 123 | }; | ||
| 124 | |||
| 125 | /// One IFD entry with its value bytes, already read from wherever they are stored. | ||
| 126 | struct Entry { | ||
| 127 | std::uint16_t type = 0; ///< Field type (`FieldType`). | ||
| 128 | std::uint64_t count = 0; ///< Number of values. | ||
| 129 | std::vector<std::uint8_t> bytes; ///< The values, in the file's byte order. | ||
| 130 | }; | ||
| 131 | |||
| 132 | /// `transform` shifted by half a pixel along both pixel axes. | ||
| 133 | /// @param sign +1 to shift forward, -1 back. | ||
| 134 | GeoTransform ShiftHalfPixel(const GeoTransform& transform, double sign); | ||
| 135 | |||
| 136 | } // namespace terraingen::detail | ||
| 137 |