diff options
Diffstat (limited to 'src/tiff_parser.h')
-rw-r--r-- | src/tiff_parser.h | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/src/tiff_parser.h b/src/tiff_parser.h new file mode 100644 index 0000000..087844d --- /dev/null +++ b/src/tiff_parser.h @@ -0,0 +1,172 @@ +// Copyright 2015 Google Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +//////////////////////////////////////////////////////////////////////////////// + +#ifndef PIEX_TIFF_PARSER_H_ +#define PIEX_TIFF_PARSER_H_ + +#include <cstdint> +#include <memory> +#include <set> +#include <vector> + +#include "src/piex_types.h" +#include "src/tiff_directory/tiff_directory.h" + +namespace piex { + +// Specifies all tags that might be of interest to get the preview data. +enum Tags { + kExifTagColorSpace = 0xA001, + kExifTagDateTimeOriginal = 0x9003, + kExifTagDefaultCropSize = 0xC620, + kExifTagExposureTime = 0x829a, + kExifTagFnumber = 0x829d, + kExifTagFocalLength = 0x920A, + kExifTagGps = 0x8825, + kExifTagHeight = 0xA003, + kExifTagIsoSpeed = 0x8827, + kExifTagMakernotes = 0x927C, + kExifTagWidth = 0xA002, + kGpsTagLatitudeRef = 1, + kGpsTagLatitude = 2, + kGpsTagLongitudeRef = 3, + kGpsTagLongitude = 4, + kGpsTagAltitudeRef = 5, + kGpsTagAltitude = 6, + kGpsTagTimeStamp = 7, + kGpsTagDateStamp = 29, + kOlymTagAspectFrame = 0x1113, + kOlymTagCameraSettings = 0x2020, + kOlymTagRawProcessing = 0x2040, + kPanaTagBottomBorder = 0x006, + kPanaTagIso = 0x0017, + kPanaTagJpegImage = 0x002E, + kPanaTagLeftBorder = 0x0005, + kPanaTagRightBorder = 0x007, + kPanaTagTopBorder = 0x0004, + kTiffTagArtist = 0x013B, + kTiffTagBitsPerSample = 0x0102, + kTiffTagCompression = 0x0103, + kTiffTagDateTime = 0x0132, + kTiffTagExifIfd = 0x8769, + kTiffTagImageDescription = 0x010E, + kTiffTagImageLength = 0x0101, + kTiffTagImageWidth = 0x0100, + kTiffTagJpegByteCount = 0x0202, + kTiffTagJpegOffset = 0x0201, + kTiffTagMake = 0x010F, + kTiffTagModel = 0x0110, + kTiffTagOrientation = 0x0112, + kTiffTagPhotometric = 0x0106, + kTiffTagPlanarConfig = 0x011C, + kTiffTagResolutionUnit = 0x0128, + kTiffTagRowsPerStrip = 0x0116, + kTiffTagSamplesPerPixel = 0x0115, + kTiffTagSoftware = 0x0131, + kTiffTagStripByteCounts = 0x0117, + kTiffTagStripOffsets = 0x0111, + kTiffTagSubIfd = 0x014A, + kTiffTagTileByteCounts = 0x0145, + kTiffTagTileLength = 0x0143, + kTiffTagTileOffsets = 0x0144, + kTiffTagTileWidth = 0x0142, + kTiffTagXresolution = 0x011A, + kTiffTagYresolution = 0x011B, +}; + +typedef std::set<Tags> TagSet; +typedef std::vector<tiff_directory::TiffDirectory> IfdVector; + +struct TiffContent { + IfdVector tiff_directory; + std::unique_ptr<tiff_directory::TiffDirectory> exif_directory; + std::unique_ptr<tiff_directory::TiffDirectory> gps_directory; +}; + +// Reads 2 bytes, an unsigned 16bit from 'stream' at a certain 'offset'. The +// bytes get swapped according to the desired endianness returning true on +// success. Returns false when something is wrong. +bool Get16u(StreamInterface* stream, const std::uint32_t offset, + const tiff_directory::Endian& endian, std::uint16_t* value); + +// Reads 4 bytes, an unsigned 32bit 'value' from 'stream' at a certain 'offset'. +// The bytes get swapped according to the desired endianness returning true on +// success. Returns false when something is wrong. +bool Get32u(StreamInterface* stream, const std::uint32_t offset, + const tiff_directory::Endian& endian, std::uint32_t* value); + +// Retrieves a byte vector of size 'length' from 'stream' beginning at some +// 'offset' reading the data in chunks of one MiB. +// If 'error' is not set to kOk the returned value is invalid. +std::vector<std::uint8_t> GetData(const size_t offset, const size_t length, + StreamInterface* stream, Error* error); + +// Retrieves the endianness of TIFF compliant data at 'tiff_offset' from +// 'stream' returning true on success. Returns false if when something is wrong. +bool GetEndianness(const std::uint32_t tiff_offset, StreamInterface* stream, + tiff_directory::Endian* endian); + +// Retrieves the width and height from the jpeg preview returning true on +// success. Returns false when something is wrong. +bool GetPreviewDimensions(const std::uint32_t jpeg_offset, + StreamInterface* stream, std::uint16_t* width, + std::uint16_t* height); + +// Parses through a Tiff IFD and writes all 'desired_tags' to a +// 'tiff_directory'. +// Sets 'error' to kFail if something with the Tiff data is wrong. +Error ParseDirectory(const std::uint32_t tiff_offset, + const std::uint32_t ifd_offset, + const tiff_directory::Endian endian, + const TagSet& desired_tags, StreamInterface* stream, + tiff_directory::TiffDirectory* tiff_directory, + std::uint32_t* next_ifd_offset); + +// Enables us to parse through data that complies to the Tiff/EP specification. +class TiffParser { + public: + // The caller owns 'stream' and is responsible to keep it alive while the + // TiffParser object is used. + explicit TiffParser(StreamInterface* stream); + TiffParser(StreamInterface* stream, const std::uint32_t offset); + + // Runs over the Tiff IFD, Exif IFD and subIFDs to get the preview image data. + // Returns kFail if something with the Tiff tags is wrong. + Error GetPreviewImageData(const TiffContent& tiff_content, + PreviewImageData* image_metadata); + + // Returns kFail if called more that once or something with the Tiff data is + // wrong. + Error Parse(const TagSet& desired_tags, const std::uint16_t max_number_ifds, + TiffContent* tiff_content); + + private: + // Disallow copy and assignment. + TiffParser(const TiffParser&) = delete; + TiffParser& operator=(const TiffParser&) = delete; + + Error ParseIfd(const std::uint32_t ifd_offset, const TagSet& desired_tags, + const std::uint16_t max_number_ifds, + IfdVector* tiff_directory); + + StreamInterface* stream_ = nullptr; + std::uint32_t tiff_offset_ = 0; + tiff_directory::Endian endian_; +}; + +} // namespace piex + +#endif // PIEX_TIFF_PARSER_H_ |