tiff_parser.h revision 3eaa83178e9d1722c126d598d3eee7fb383c2c85
129345531d776962073312d423917406fc59b09f6Jaesung Chung// Copyright 2015 Google Inc.
229345531d776962073312d423917406fc59b09f6Jaesung Chung//
329345531d776962073312d423917406fc59b09f6Jaesung Chung// Licensed under the Apache License, Version 2.0 (the "License");
429345531d776962073312d423917406fc59b09f6Jaesung Chung// you may not use this file except in compliance with the License.
529345531d776962073312d423917406fc59b09f6Jaesung Chung// You may obtain a copy of the License at
629345531d776962073312d423917406fc59b09f6Jaesung Chung//
729345531d776962073312d423917406fc59b09f6Jaesung Chung//      http://www.apache.org/licenses/LICENSE-2.0
829345531d776962073312d423917406fc59b09f6Jaesung Chung//
929345531d776962073312d423917406fc59b09f6Jaesung Chung// Unless required by applicable law or agreed to in writing, software
1029345531d776962073312d423917406fc59b09f6Jaesung Chung// distributed under the License is distributed on an "AS IS" BASIS,
1129345531d776962073312d423917406fc59b09f6Jaesung Chung// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1229345531d776962073312d423917406fc59b09f6Jaesung Chung// See the License for the specific language governing permissions and
1329345531d776962073312d423917406fc59b09f6Jaesung Chung// limitations under the License.
1429345531d776962073312d423917406fc59b09f6Jaesung Chung//
1529345531d776962073312d423917406fc59b09f6Jaesung Chung////////////////////////////////////////////////////////////////////////////////
1629345531d776962073312d423917406fc59b09f6Jaesung Chung
1729345531d776962073312d423917406fc59b09f6Jaesung Chung#ifndef PIEX_TIFF_PARSER_H_
1829345531d776962073312d423917406fc59b09f6Jaesung Chung#define PIEX_TIFF_PARSER_H_
1929345531d776962073312d423917406fc59b09f6Jaesung Chung
2029345531d776962073312d423917406fc59b09f6Jaesung Chung#include <cstdint>
2129345531d776962073312d423917406fc59b09f6Jaesung Chung#include <memory>
2229345531d776962073312d423917406fc59b09f6Jaesung Chung#include <set>
2329345531d776962073312d423917406fc59b09f6Jaesung Chung#include <vector>
2429345531d776962073312d423917406fc59b09f6Jaesung Chung
2529345531d776962073312d423917406fc59b09f6Jaesung Chung#include "src/piex_types.h"
2629345531d776962073312d423917406fc59b09f6Jaesung Chung#include "src/tiff_directory/tiff_directory.h"
2729345531d776962073312d423917406fc59b09f6Jaesung Chung
2829345531d776962073312d423917406fc59b09f6Jaesung Chungnamespace piex {
2929345531d776962073312d423917406fc59b09f6Jaesung Chung
3029345531d776962073312d423917406fc59b09f6Jaesung Chung// Specifies all tags that might be of interest to get the preview data.
313eaa83178e9d1722c126d598d3eee7fb383c2c85Yujie Qinenum GpsTags {
323eaa83178e9d1722c126d598d3eee7fb383c2c85Yujie Qin  kGpsTagLatitudeRef = 1,
333eaa83178e9d1722c126d598d3eee7fb383c2c85Yujie Qin  kGpsTagLatitude = 2,
343eaa83178e9d1722c126d598d3eee7fb383c2c85Yujie Qin  kGpsTagLongitudeRef = 3,
353eaa83178e9d1722c126d598d3eee7fb383c2c85Yujie Qin  kGpsTagLongitude = 4,
363eaa83178e9d1722c126d598d3eee7fb383c2c85Yujie Qin  kGpsTagAltitudeRef = 5,
373eaa83178e9d1722c126d598d3eee7fb383c2c85Yujie Qin  kGpsTagAltitude = 6,
383eaa83178e9d1722c126d598d3eee7fb383c2c85Yujie Qin  kGpsTagTimeStamp = 7,
393eaa83178e9d1722c126d598d3eee7fb383c2c85Yujie Qin  kGpsTagDateStamp = 29,
403eaa83178e9d1722c126d598d3eee7fb383c2c85Yujie Qin};
413eaa83178e9d1722c126d598d3eee7fb383c2c85Yujie Qin
423eaa83178e9d1722c126d598d3eee7fb383c2c85Yujie Qinenum TiffTags {
4329345531d776962073312d423917406fc59b09f6Jaesung Chung  kExifTagColorSpace = 0xA001,
4429345531d776962073312d423917406fc59b09f6Jaesung Chung  kExifTagDateTimeOriginal = 0x9003,
4529345531d776962073312d423917406fc59b09f6Jaesung Chung  kExifTagDefaultCropSize = 0xC620,
4629345531d776962073312d423917406fc59b09f6Jaesung Chung  kExifTagExposureTime = 0x829a,
4729345531d776962073312d423917406fc59b09f6Jaesung Chung  kExifTagFnumber = 0x829d,
4829345531d776962073312d423917406fc59b09f6Jaesung Chung  kExifTagFocalLength = 0x920A,
4929345531d776962073312d423917406fc59b09f6Jaesung Chung  kExifTagGps = 0x8825,
5029345531d776962073312d423917406fc59b09f6Jaesung Chung  kExifTagHeight = 0xA003,
5129345531d776962073312d423917406fc59b09f6Jaesung Chung  kExifTagIsoSpeed = 0x8827,
5229345531d776962073312d423917406fc59b09f6Jaesung Chung  kExifTagMakernotes = 0x927C,
5329345531d776962073312d423917406fc59b09f6Jaesung Chung  kExifTagWidth = 0xA002,
5429345531d776962073312d423917406fc59b09f6Jaesung Chung  kOlymTagAspectFrame = 0x1113,
5529345531d776962073312d423917406fc59b09f6Jaesung Chung  kOlymTagCameraSettings = 0x2020,
5629345531d776962073312d423917406fc59b09f6Jaesung Chung  kOlymTagRawProcessing = 0x2040,
5729345531d776962073312d423917406fc59b09f6Jaesung Chung  kPanaTagBottomBorder = 0x006,
5829345531d776962073312d423917406fc59b09f6Jaesung Chung  kPanaTagIso = 0x0017,
5929345531d776962073312d423917406fc59b09f6Jaesung Chung  kPanaTagJpegImage = 0x002E,
6029345531d776962073312d423917406fc59b09f6Jaesung Chung  kPanaTagLeftBorder = 0x0005,
6129345531d776962073312d423917406fc59b09f6Jaesung Chung  kPanaTagRightBorder = 0x007,
6229345531d776962073312d423917406fc59b09f6Jaesung Chung  kPanaTagTopBorder = 0x0004,
633eaa83178e9d1722c126d598d3eee7fb383c2c85Yujie Qin  kPentaxTagColorSpace = 0x0037,
6429345531d776962073312d423917406fc59b09f6Jaesung Chung  kTiffTagArtist = 0x013B,
6529345531d776962073312d423917406fc59b09f6Jaesung Chung  kTiffTagBitsPerSample = 0x0102,
6629345531d776962073312d423917406fc59b09f6Jaesung Chung  kTiffTagCompression = 0x0103,
6729345531d776962073312d423917406fc59b09f6Jaesung Chung  kTiffTagDateTime = 0x0132,
6829345531d776962073312d423917406fc59b09f6Jaesung Chung  kTiffTagExifIfd = 0x8769,
6929345531d776962073312d423917406fc59b09f6Jaesung Chung  kTiffTagImageDescription = 0x010E,
7029345531d776962073312d423917406fc59b09f6Jaesung Chung  kTiffTagImageLength = 0x0101,
7129345531d776962073312d423917406fc59b09f6Jaesung Chung  kTiffTagImageWidth = 0x0100,
7229345531d776962073312d423917406fc59b09f6Jaesung Chung  kTiffTagJpegByteCount = 0x0202,
7329345531d776962073312d423917406fc59b09f6Jaesung Chung  kTiffTagJpegOffset = 0x0201,
7429345531d776962073312d423917406fc59b09f6Jaesung Chung  kTiffTagMake = 0x010F,
7529345531d776962073312d423917406fc59b09f6Jaesung Chung  kTiffTagModel = 0x0110,
7629345531d776962073312d423917406fc59b09f6Jaesung Chung  kTiffTagOrientation = 0x0112,
7729345531d776962073312d423917406fc59b09f6Jaesung Chung  kTiffTagPhotometric = 0x0106,
7829345531d776962073312d423917406fc59b09f6Jaesung Chung  kTiffTagPlanarConfig = 0x011C,
7929345531d776962073312d423917406fc59b09f6Jaesung Chung  kTiffTagResolutionUnit = 0x0128,
8029345531d776962073312d423917406fc59b09f6Jaesung Chung  kTiffTagRowsPerStrip = 0x0116,
8129345531d776962073312d423917406fc59b09f6Jaesung Chung  kTiffTagSamplesPerPixel = 0x0115,
8229345531d776962073312d423917406fc59b09f6Jaesung Chung  kTiffTagSoftware = 0x0131,
8329345531d776962073312d423917406fc59b09f6Jaesung Chung  kTiffTagStripByteCounts = 0x0117,
8429345531d776962073312d423917406fc59b09f6Jaesung Chung  kTiffTagStripOffsets = 0x0111,
8529345531d776962073312d423917406fc59b09f6Jaesung Chung  kTiffTagSubIfd = 0x014A,
8629345531d776962073312d423917406fc59b09f6Jaesung Chung  kTiffTagTileByteCounts = 0x0145,
8729345531d776962073312d423917406fc59b09f6Jaesung Chung  kTiffTagTileLength = 0x0143,
8829345531d776962073312d423917406fc59b09f6Jaesung Chung  kTiffTagTileOffsets = 0x0144,
8929345531d776962073312d423917406fc59b09f6Jaesung Chung  kTiffTagTileWidth = 0x0142,
9029345531d776962073312d423917406fc59b09f6Jaesung Chung  kTiffTagXresolution = 0x011A,
9129345531d776962073312d423917406fc59b09f6Jaesung Chung  kTiffTagYresolution = 0x011B,
9229345531d776962073312d423917406fc59b09f6Jaesung Chung};
9329345531d776962073312d423917406fc59b09f6Jaesung Chung
943eaa83178e9d1722c126d598d3eee7fb383c2c85Yujie Qintypedef int Tags;
9529345531d776962073312d423917406fc59b09f6Jaesung Chungtypedef std::set<Tags> TagSet;
9629345531d776962073312d423917406fc59b09f6Jaesung Chungtypedef std::vector<tiff_directory::TiffDirectory> IfdVector;
9729345531d776962073312d423917406fc59b09f6Jaesung Chung
9829345531d776962073312d423917406fc59b09f6Jaesung Chungstruct TiffContent {
9929345531d776962073312d423917406fc59b09f6Jaesung Chung  IfdVector tiff_directory;
10029345531d776962073312d423917406fc59b09f6Jaesung Chung  std::unique_ptr<tiff_directory::TiffDirectory> exif_directory;
10129345531d776962073312d423917406fc59b09f6Jaesung Chung  std::unique_ptr<tiff_directory::TiffDirectory> gps_directory;
10229345531d776962073312d423917406fc59b09f6Jaesung Chung};
10329345531d776962073312d423917406fc59b09f6Jaesung Chung
10429345531d776962073312d423917406fc59b09f6Jaesung Chung// Reads 2 bytes, an unsigned 16bit from 'stream' at a certain 'offset'. The
10529345531d776962073312d423917406fc59b09f6Jaesung Chung// bytes get swapped according to the desired endianness returning true on
10629345531d776962073312d423917406fc59b09f6Jaesung Chung// success. Returns false when something is wrong.
10729345531d776962073312d423917406fc59b09f6Jaesung Chungbool Get16u(StreamInterface* stream, const std::uint32_t offset,
10829345531d776962073312d423917406fc59b09f6Jaesung Chung            const tiff_directory::Endian& endian, std::uint16_t* value);
10929345531d776962073312d423917406fc59b09f6Jaesung Chung
11029345531d776962073312d423917406fc59b09f6Jaesung Chung// Reads 4 bytes, an unsigned 32bit 'value' from 'stream' at a certain 'offset'.
11129345531d776962073312d423917406fc59b09f6Jaesung Chung// The bytes get swapped according to the desired endianness returning true on
11229345531d776962073312d423917406fc59b09f6Jaesung Chung// success. Returns false when something is wrong.
11329345531d776962073312d423917406fc59b09f6Jaesung Chungbool Get32u(StreamInterface* stream, const std::uint32_t offset,
11429345531d776962073312d423917406fc59b09f6Jaesung Chung            const tiff_directory::Endian& endian, std::uint32_t* value);
11529345531d776962073312d423917406fc59b09f6Jaesung Chung
11629345531d776962073312d423917406fc59b09f6Jaesung Chung// Retrieves a byte vector of size 'length' from 'stream' beginning at some
11729345531d776962073312d423917406fc59b09f6Jaesung Chung// 'offset' reading the data in chunks of one MiB.
11829345531d776962073312d423917406fc59b09f6Jaesung Chung// If 'error' is not set to kOk the returned value is invalid.
11929345531d776962073312d423917406fc59b09f6Jaesung Chungstd::vector<std::uint8_t> GetData(const size_t offset, const size_t length,
12029345531d776962073312d423917406fc59b09f6Jaesung Chung                                  StreamInterface* stream, Error* error);
12129345531d776962073312d423917406fc59b09f6Jaesung Chung
12229345531d776962073312d423917406fc59b09f6Jaesung Chung// Retrieves the endianness of TIFF compliant data at 'tiff_offset' from
12329345531d776962073312d423917406fc59b09f6Jaesung Chung// 'stream' returning true on success. Returns false if when something is wrong.
12429345531d776962073312d423917406fc59b09f6Jaesung Chungbool GetEndianness(const std::uint32_t tiff_offset, StreamInterface* stream,
12529345531d776962073312d423917406fc59b09f6Jaesung Chung                   tiff_directory::Endian* endian);
12629345531d776962073312d423917406fc59b09f6Jaesung Chung
12729345531d776962073312d423917406fc59b09f6Jaesung Chung// Retrieves the width and height from the jpeg preview returning true on
12829345531d776962073312d423917406fc59b09f6Jaesung Chung// success. Returns false when something is wrong.
12929345531d776962073312d423917406fc59b09f6Jaesung Chungbool GetPreviewDimensions(const std::uint32_t jpeg_offset,
13029345531d776962073312d423917406fc59b09f6Jaesung Chung                          StreamInterface* stream, std::uint16_t* width,
13129345531d776962073312d423917406fc59b09f6Jaesung Chung                          std::uint16_t* height);
13229345531d776962073312d423917406fc59b09f6Jaesung Chung
13329345531d776962073312d423917406fc59b09f6Jaesung Chung// Parses through a Tiff IFD and writes all 'desired_tags' to a
13429345531d776962073312d423917406fc59b09f6Jaesung Chung// 'tiff_directory'.
13529345531d776962073312d423917406fc59b09f6Jaesung Chung// Sets 'error' to kFail if something with the Tiff data is wrong.
13629345531d776962073312d423917406fc59b09f6Jaesung ChungError ParseDirectory(const std::uint32_t tiff_offset,
13729345531d776962073312d423917406fc59b09f6Jaesung Chung                     const std::uint32_t ifd_offset,
13829345531d776962073312d423917406fc59b09f6Jaesung Chung                     const tiff_directory::Endian endian,
13929345531d776962073312d423917406fc59b09f6Jaesung Chung                     const TagSet& desired_tags, StreamInterface* stream,
14029345531d776962073312d423917406fc59b09f6Jaesung Chung                     tiff_directory::TiffDirectory* tiff_directory,
14129345531d776962073312d423917406fc59b09f6Jaesung Chung                     std::uint32_t* next_ifd_offset);
14229345531d776962073312d423917406fc59b09f6Jaesung Chung
14329345531d776962073312d423917406fc59b09f6Jaesung Chung// Enables us to parse through data that complies to the Tiff/EP specification.
14429345531d776962073312d423917406fc59b09f6Jaesung Chungclass TiffParser {
14529345531d776962073312d423917406fc59b09f6Jaesung Chung public:
14629345531d776962073312d423917406fc59b09f6Jaesung Chung  // The caller owns 'stream' and is responsible to keep it alive while the
14729345531d776962073312d423917406fc59b09f6Jaesung Chung  // TiffParser object is used.
14829345531d776962073312d423917406fc59b09f6Jaesung Chung  explicit TiffParser(StreamInterface* stream);
14929345531d776962073312d423917406fc59b09f6Jaesung Chung  TiffParser(StreamInterface* stream, const std::uint32_t offset);
15029345531d776962073312d423917406fc59b09f6Jaesung Chung
15129345531d776962073312d423917406fc59b09f6Jaesung Chung  // Runs over the Tiff IFD, Exif IFD and subIFDs to get the preview image data.
15229345531d776962073312d423917406fc59b09f6Jaesung Chung  // Returns kFail if something with the Tiff tags is wrong.
15329345531d776962073312d423917406fc59b09f6Jaesung Chung  Error GetPreviewImageData(const TiffContent& tiff_content,
15429345531d776962073312d423917406fc59b09f6Jaesung Chung                            PreviewImageData* image_metadata);
15529345531d776962073312d423917406fc59b09f6Jaesung Chung
15629345531d776962073312d423917406fc59b09f6Jaesung Chung  // Returns kFail if called more that once or something with the Tiff data is
15729345531d776962073312d423917406fc59b09f6Jaesung Chung  // wrong.
15829345531d776962073312d423917406fc59b09f6Jaesung Chung  Error Parse(const TagSet& desired_tags, const std::uint16_t max_number_ifds,
15929345531d776962073312d423917406fc59b09f6Jaesung Chung              TiffContent* tiff_content);
16029345531d776962073312d423917406fc59b09f6Jaesung Chung
16129345531d776962073312d423917406fc59b09f6Jaesung Chung private:
16229345531d776962073312d423917406fc59b09f6Jaesung Chung  // Disallow copy and assignment.
16329345531d776962073312d423917406fc59b09f6Jaesung Chung  TiffParser(const TiffParser&) = delete;
16429345531d776962073312d423917406fc59b09f6Jaesung Chung  TiffParser& operator=(const TiffParser&) = delete;
16529345531d776962073312d423917406fc59b09f6Jaesung Chung
16629345531d776962073312d423917406fc59b09f6Jaesung Chung  Error ParseIfd(const std::uint32_t ifd_offset, const TagSet& desired_tags,
16729345531d776962073312d423917406fc59b09f6Jaesung Chung                 const std::uint16_t max_number_ifds,
16829345531d776962073312d423917406fc59b09f6Jaesung Chung                 IfdVector* tiff_directory);
16929345531d776962073312d423917406fc59b09f6Jaesung Chung
17029345531d776962073312d423917406fc59b09f6Jaesung Chung  StreamInterface* stream_ = nullptr;
17129345531d776962073312d423917406fc59b09f6Jaesung Chung  std::uint32_t tiff_offset_ = 0;
17229345531d776962073312d423917406fc59b09f6Jaesung Chung  tiff_directory::Endian endian_;
17329345531d776962073312d423917406fc59b09f6Jaesung Chung};
17429345531d776962073312d423917406fc59b09f6Jaesung Chung
17529345531d776962073312d423917406fc59b09f6Jaesung Chung}  // namespace piex
17629345531d776962073312d423917406fc59b09f6Jaesung Chung
17729345531d776962073312d423917406fc59b09f6Jaesung Chung#endif  // PIEX_TIFF_PARSER_H_
178