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