xref: /aosp_15_r20/external/piex/src/tiff_parser.h (revision 4d671364a067eb4f124488347677d916765212d1)
1*4d671364SKiyoung Kim // Copyright 2015 Google Inc.
2*4d671364SKiyoung Kim //
3*4d671364SKiyoung Kim // Licensed under the Apache License, Version 2.0 (the "License");
4*4d671364SKiyoung Kim // you may not use this file except in compliance with the License.
5*4d671364SKiyoung Kim // You may obtain a copy of the License at
6*4d671364SKiyoung Kim //
7*4d671364SKiyoung Kim //      http://www.apache.org/licenses/LICENSE-2.0
8*4d671364SKiyoung Kim //
9*4d671364SKiyoung Kim // Unless required by applicable law or agreed to in writing, software
10*4d671364SKiyoung Kim // distributed under the License is distributed on an "AS IS" BASIS,
11*4d671364SKiyoung Kim // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*4d671364SKiyoung Kim // See the License for the specific language governing permissions and
13*4d671364SKiyoung Kim // limitations under the License.
14*4d671364SKiyoung Kim //
15*4d671364SKiyoung Kim ////////////////////////////////////////////////////////////////////////////////
16*4d671364SKiyoung Kim 
17*4d671364SKiyoung Kim #ifndef PIEX_TIFF_PARSER_H_
18*4d671364SKiyoung Kim #define PIEX_TIFF_PARSER_H_
19*4d671364SKiyoung Kim 
20*4d671364SKiyoung Kim #include <cstdint>
21*4d671364SKiyoung Kim #include <memory>
22*4d671364SKiyoung Kim #include <set>
23*4d671364SKiyoung Kim #include <vector>
24*4d671364SKiyoung Kim 
25*4d671364SKiyoung Kim #include "src/piex_types.h"
26*4d671364SKiyoung Kim #include "src/tiff_directory/tiff_directory.h"
27*4d671364SKiyoung Kim 
28*4d671364SKiyoung Kim namespace piex {
29*4d671364SKiyoung Kim 
30*4d671364SKiyoung Kim // Specifies the maximum number of pixels for thumbnails in each direction.
31*4d671364SKiyoung Kim const int kThumbnailMaxDimension = 512;
32*4d671364SKiyoung Kim 
33*4d671364SKiyoung Kim // Specifies all tags that might be of interest to get the preview data.
34*4d671364SKiyoung Kim enum GpsTags {
35*4d671364SKiyoung Kim   kGpsTagLatitudeRef = 1,
36*4d671364SKiyoung Kim   kGpsTagLatitude = 2,
37*4d671364SKiyoung Kim   kGpsTagLongitudeRef = 3,
38*4d671364SKiyoung Kim   kGpsTagLongitude = 4,
39*4d671364SKiyoung Kim   kGpsTagAltitudeRef = 5,
40*4d671364SKiyoung Kim   kGpsTagAltitude = 6,
41*4d671364SKiyoung Kim   kGpsTagTimeStamp = 7,
42*4d671364SKiyoung Kim   kGpsTagDateStamp = 29,
43*4d671364SKiyoung Kim };
44*4d671364SKiyoung Kim 
45*4d671364SKiyoung Kim enum TiffTags {
46*4d671364SKiyoung Kim   kExifTagColorSpace = 0xA001,
47*4d671364SKiyoung Kim   kExifTagDateTimeOriginal = 0x9003,
48*4d671364SKiyoung Kim   kExifTagDefaultCropSize = 0xC620,
49*4d671364SKiyoung Kim   kExifTagExposureTime = 0x829a,
50*4d671364SKiyoung Kim   kExifTagFnumber = 0x829d,
51*4d671364SKiyoung Kim   kExifTagFocalLength = 0x920A,
52*4d671364SKiyoung Kim   kExifTagGps = 0x8825,
53*4d671364SKiyoung Kim   kExifTagHeight = 0xA003,
54*4d671364SKiyoung Kim   kExifTagIsoSpeed = 0x8827,
55*4d671364SKiyoung Kim   kExifTagMakernotes = 0x927C,
56*4d671364SKiyoung Kim   kExifTagWidth = 0xA002,
57*4d671364SKiyoung Kim   kOlymTagAspectFrame = 0x1113,
58*4d671364SKiyoung Kim   kOlymTagCameraSettings = 0x2020,
59*4d671364SKiyoung Kim   kOlymTagRawProcessing = 0x2040,
60*4d671364SKiyoung Kim   kPanaTagBottomBorder = 0x006,
61*4d671364SKiyoung Kim   kPanaTagIso = 0x0017,
62*4d671364SKiyoung Kim   kPanaTagJpegImage = 0x002E,
63*4d671364SKiyoung Kim   kPanaTagLeftBorder = 0x0005,
64*4d671364SKiyoung Kim   kPanaTagRightBorder = 0x007,
65*4d671364SKiyoung Kim   kPanaTagTopBorder = 0x0004,
66*4d671364SKiyoung Kim   kPentaxTagColorSpace = 0x0037,
67*4d671364SKiyoung Kim   kTiffTagArtist = 0x013B,
68*4d671364SKiyoung Kim   kTiffTagBitsPerSample = 0x0102,
69*4d671364SKiyoung Kim   kTiffTagCfaPatternDim = 0x828D,
70*4d671364SKiyoung Kim   kTiffTagCompression = 0x0103,
71*4d671364SKiyoung Kim   kTiffTagDateTime = 0x0132,
72*4d671364SKiyoung Kim   kTiffTagExifIfd = 0x8769,
73*4d671364SKiyoung Kim   kTiffTagImageDescription = 0x010E,
74*4d671364SKiyoung Kim   kTiffTagImageLength = 0x0101,
75*4d671364SKiyoung Kim   kTiffTagImageWidth = 0x0100,
76*4d671364SKiyoung Kim   kTiffTagJpegByteCount = 0x0202,
77*4d671364SKiyoung Kim   kTiffTagJpegOffset = 0x0201,
78*4d671364SKiyoung Kim   kTiffTagMake = 0x010F,
79*4d671364SKiyoung Kim   kTiffTagModel = 0x0110,
80*4d671364SKiyoung Kim   kTiffTagOrientation = 0x0112,
81*4d671364SKiyoung Kim   kTiffTagPhotometric = 0x0106,
82*4d671364SKiyoung Kim   kTiffTagPlanarConfig = 0x011C,
83*4d671364SKiyoung Kim   kTiffTagResolutionUnit = 0x0128,
84*4d671364SKiyoung Kim   kTiffTagRowsPerStrip = 0x0116,
85*4d671364SKiyoung Kim   kTiffTagSamplesPerPixel = 0x0115,
86*4d671364SKiyoung Kim   kTiffTagSoftware = 0x0131,
87*4d671364SKiyoung Kim   kTiffTagStripByteCounts = 0x0117,
88*4d671364SKiyoung Kim   kTiffTagStripOffsets = 0x0111,
89*4d671364SKiyoung Kim   kTiffTagSubFileType = 0x00FE,
90*4d671364SKiyoung Kim   kTiffTagSubIfd = 0x014A,
91*4d671364SKiyoung Kim   kTiffTagTileByteCounts = 0x0145,
92*4d671364SKiyoung Kim   kTiffTagTileLength = 0x0143,
93*4d671364SKiyoung Kim   kTiffTagTileOffsets = 0x0144,
94*4d671364SKiyoung Kim   kTiffTagTileWidth = 0x0142,
95*4d671364SKiyoung Kim   kTiffTagXresolution = 0x011A,
96*4d671364SKiyoung Kim   kTiffTagYresolution = 0x011B,
97*4d671364SKiyoung Kim };
98*4d671364SKiyoung Kim 
99*4d671364SKiyoung Kim typedef std::set<tiff_directory::TiffDirectory::Tag> TagSet;
100*4d671364SKiyoung Kim typedef std::vector<tiff_directory::TiffDirectory> IfdVector;
101*4d671364SKiyoung Kim 
102*4d671364SKiyoung Kim struct TiffContent {
103*4d671364SKiyoung Kim   IfdVector tiff_directory;
104*4d671364SKiyoung Kim   std::unique_ptr<tiff_directory::TiffDirectory> exif_directory;
105*4d671364SKiyoung Kim   std::unique_ptr<tiff_directory::TiffDirectory> gps_directory;
106*4d671364SKiyoung Kim };
107*4d671364SKiyoung Kim 
108*4d671364SKiyoung Kim // Reads 2 bytes, an unsigned 16bit from 'stream' at a certain 'offset'. The
109*4d671364SKiyoung Kim // bytes get swapped according to the desired endianness returning true on
110*4d671364SKiyoung Kim // success. Returns false when something is wrong.
111*4d671364SKiyoung Kim bool Get16u(StreamInterface* stream, const std::uint32_t offset,
112*4d671364SKiyoung Kim             const tiff_directory::Endian& endian, std::uint16_t* value);
113*4d671364SKiyoung Kim 
114*4d671364SKiyoung Kim // Reads 4 bytes, an unsigned 32bit 'value' from 'stream' at a certain 'offset'.
115*4d671364SKiyoung Kim // The bytes get swapped according to the desired endianness returning true on
116*4d671364SKiyoung Kim // success. Returns false when something is wrong.
117*4d671364SKiyoung Kim bool Get32u(StreamInterface* stream, const std::uint32_t offset,
118*4d671364SKiyoung Kim             const tiff_directory::Endian& endian, std::uint32_t* value);
119*4d671364SKiyoung Kim 
120*4d671364SKiyoung Kim // Retrieves a byte vector of size 'length' from 'stream' beginning at some
121*4d671364SKiyoung Kim // 'offset' reading the data in chunks of one MiB.
122*4d671364SKiyoung Kim // If 'error' is not set to kOk the returned value is invalid.
123*4d671364SKiyoung Kim std::vector<std::uint8_t> GetData(const size_t offset, const size_t length,
124*4d671364SKiyoung Kim                                   StreamInterface* stream, Error* error);
125*4d671364SKiyoung Kim 
126*4d671364SKiyoung Kim // Retrieves the endianness of TIFF compliant data at 'tiff_offset' from
127*4d671364SKiyoung Kim // 'stream' returning true on success. Returns false when something is wrong.
128*4d671364SKiyoung Kim bool GetEndianness(const std::uint32_t tiff_offset, StreamInterface* stream,
129*4d671364SKiyoung Kim                    tiff_directory::Endian* endian);
130*4d671364SKiyoung Kim 
131*4d671364SKiyoung Kim // Retrieves an image from tiff_directory. Return false when something is wrong.
132*4d671364SKiyoung Kim bool GetImageData(const tiff_directory::TiffDirectory& tiff_directory,
133*4d671364SKiyoung Kim                   StreamInterface* stream, Image* image);
134*4d671364SKiyoung Kim 
135*4d671364SKiyoung Kim // Retrieves the width and height from the jpeg image returning true on
136*4d671364SKiyoung Kim // success. Returns false when something is wrong.
137*4d671364SKiyoung Kim bool GetJpegDimensions(const std::uint32_t jpeg_offset, StreamInterface* stream,
138*4d671364SKiyoung Kim                        std::uint16_t* width, std::uint16_t* height);
139*4d671364SKiyoung Kim 
140*4d671364SKiyoung Kim // According to Tiff/EP a thumbnail has max 256 pixels per dimension.
141*4d671364SKiyoung Kim // http://standardsproposals.bsigroup.com/Home/getPDF/567
142*4d671364SKiyoung Kim bool IsThumbnail(const Image& image,
143*4d671364SKiyoung Kim                  const int max_dimension = kThumbnailMaxDimension);
144*4d671364SKiyoung Kim 
145*4d671364SKiyoung Kim // Parses through a Tiff IFD and writes all 'desired_tags' to a
146*4d671364SKiyoung Kim // 'tiff_directory'.
147*4d671364SKiyoung Kim // Returns false if something with the Tiff data is wrong.
148*4d671364SKiyoung Kim bool ParseDirectory(const std::uint32_t tiff_offset,
149*4d671364SKiyoung Kim                     const std::uint32_t ifd_offset,
150*4d671364SKiyoung Kim                     const tiff_directory::Endian endian,
151*4d671364SKiyoung Kim                     const TagSet& desired_tags, StreamInterface* stream,
152*4d671364SKiyoung Kim                     tiff_directory::TiffDirectory* tiff_directory,
153*4d671364SKiyoung Kim                     std::uint32_t* next_ifd_offset);
154*4d671364SKiyoung Kim 
155*4d671364SKiyoung Kim // Returns true if Exif orientation for the image can be obtained. False
156*4d671364SKiyoung Kim // otherwise.
157*4d671364SKiyoung Kim bool GetExifOrientation(StreamInterface* stream, const std::uint32_t offset,
158*4d671364SKiyoung Kim                         std::uint32_t* orientation);
159*4d671364SKiyoung Kim 
160*4d671364SKiyoung Kim // Reads the width and height of the full resolution image. The tag groups are
161*4d671364SKiyoung Kim // exclusive.
162*4d671364SKiyoung Kim bool GetFullDimension32(const tiff_directory::TiffDirectory& tiff_directory,
163*4d671364SKiyoung Kim                         std::uint32_t* width, std::uint32_t* height);
164*4d671364SKiyoung Kim 
165*4d671364SKiyoung Kim // Reads the width and height of the crop information if available.
166*4d671364SKiyoung Kim // Returns false if an error occurred.
167*4d671364SKiyoung Kim bool GetFullCropDimension(const tiff_directory::TiffDirectory& tiff_directory,
168*4d671364SKiyoung Kim                           std::uint32_t* width, std::uint32_t* height);
169*4d671364SKiyoung Kim 
170*4d671364SKiyoung Kim // Reads 1 or more rational values for a tag and stores results into data.
171*4d671364SKiyoung Kim // Returns false if an error occurred.
172*4d671364SKiyoung Kim bool GetRational(const tiff_directory::TiffDirectory::Tag& tag,
173*4d671364SKiyoung Kim                  const tiff_directory::TiffDirectory& directory,
174*4d671364SKiyoung Kim                  const int data_size, PreviewImageData::Rational* data);
175*4d671364SKiyoung Kim 
176*4d671364SKiyoung Kim // Enables us to parse through data that complies to the Tiff/EP specification.
177*4d671364SKiyoung Kim class TiffParser {
178*4d671364SKiyoung Kim  public:
179*4d671364SKiyoung Kim   // The caller owns 'stream' and is responsible to keep it alive while the
180*4d671364SKiyoung Kim   // TiffParser object is used.
181*4d671364SKiyoung Kim   explicit TiffParser(StreamInterface* stream);
182*4d671364SKiyoung Kim   TiffParser(StreamInterface* stream, const std::uint32_t offset);
183*4d671364SKiyoung Kim 
184*4d671364SKiyoung Kim   // Runs over the Tiff IFD, Exif IFD and subIFDs to get the preview image data.
185*4d671364SKiyoung Kim   // Returns false if something with the Tiff tags is wrong.
186*4d671364SKiyoung Kim   bool GetPreviewImageData(const TiffContent& tiff_content,
187*4d671364SKiyoung Kim                            PreviewImageData* preview_image_data);
188*4d671364SKiyoung Kim 
189*4d671364SKiyoung Kim   // Returns false if called more that once or something with the Tiff data is
190*4d671364SKiyoung Kim   // wrong.
191*4d671364SKiyoung Kim   bool Parse(const TagSet& desired_tags, const std::uint16_t max_number_ifds,
192*4d671364SKiyoung Kim              TiffContent* tiff_content);
193*4d671364SKiyoung Kim 
194*4d671364SKiyoung Kim  private:
195*4d671364SKiyoung Kim   // Disallow copy and assignment.
196*4d671364SKiyoung Kim   TiffParser(const TiffParser&) = delete;
197*4d671364SKiyoung Kim   TiffParser& operator=(const TiffParser&) = delete;
198*4d671364SKiyoung Kim 
199*4d671364SKiyoung Kim   bool ParseIfd(const std::uint32_t ifd_offset, const TagSet& desired_tags,
200*4d671364SKiyoung Kim                 const std::uint16_t max_number_ifds, IfdVector* tiff_directory);
201*4d671364SKiyoung Kim   bool ParseGpsData(const tiff_directory::TiffDirectory* tiff_ifd,
202*4d671364SKiyoung Kim                     TiffContent* tiff_content);
203*4d671364SKiyoung Kim 
204*4d671364SKiyoung Kim   StreamInterface* stream_ = nullptr;
205*4d671364SKiyoung Kim   std::uint32_t tiff_offset_ = 0;
206*4d671364SKiyoung Kim   tiff_directory::Endian endian_;
207*4d671364SKiyoung Kim };
208*4d671364SKiyoung Kim 
209*4d671364SKiyoung Kim }  // namespace piex
210*4d671364SKiyoung Kim 
211*4d671364SKiyoung Kim #endif  // PIEX_TIFF_PARSER_H_
212