aboutsummaryrefslogtreecommitdiff
path: root/src/piex.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/piex.cc')
-rw-r--r--src/piex.cc740
1 files changed, 0 insertions, 740 deletions
diff --git a/src/piex.cc b/src/piex.cc
deleted file mode 100644
index ac2ef0b..0000000
--- a/src/piex.cc
+++ /dev/null
@@ -1,740 +0,0 @@
-// 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.
-//
-////////////////////////////////////////////////////////////////////////////////
-
-#include "src/piex.h"
-
-#include <cstdint>
-#include <limits>
-#include <set>
-#include <vector>
-
-#include "src/binary_parse/range_checked_byte_ptr.h"
-#include "src/image_type_recognition/image_type_recognition_lite.h"
-#include "src/piex_cr3.h"
-#include "src/tiff_parser.h"
-
-namespace piex {
-namespace {
-
-using binary_parse::RangeCheckedBytePtr;
-using image_type_recognition::RawImageTypes;
-using image_type_recognition::RecognizeRawImageTypeLite;
-using tiff_directory::Endian;
-using tiff_directory::TiffDirectory;
-
-const std::uint32_t kRafOffsetToPreviewOffset = 84;
-
-bool GetDngInformation(const tiff_directory::TiffDirectory& tiff_directory,
- std::uint32_t* width, std::uint32_t* height,
- std::vector<std::uint32_t>* cfa_pattern_dim) {
- if (!GetFullDimension32(tiff_directory, width, height) || *width == 0 ||
- *height == 0) {
- return false;
- }
-
- if (!tiff_directory.Get(kTiffTagCfaPatternDim, cfa_pattern_dim) ||
- cfa_pattern_dim->size() != 2) {
- return false;
- }
- return true;
-}
-
-bool GetDngInformation(const TagSet& extended_tags, StreamInterface* data,
- std::uint32_t* width, std::uint32_t* height,
- std::vector<std::uint32_t>* cfa_pattern_dim) {
- TagSet desired_tags = {kExifTagDefaultCropSize, kTiffTagCfaPatternDim,
- kTiffTagExifIfd, kTiffTagSubFileType};
- desired_tags.insert(extended_tags.cbegin(), extended_tags.cend());
-
- TiffParser tiff_parser(data, 0 /* offset */);
-
- TiffContent tiff_content;
- if (!tiff_parser.Parse(desired_tags, 1, &tiff_content) ||
- tiff_content.tiff_directory.empty()) {
- return false;
- }
-
- // If IFD0 contains already the full dimensions we do not parse into the sub
- // IFD.
- const TiffDirectory& tiff_directory = tiff_content.tiff_directory[0];
- if (tiff_directory.GetSubDirectories().empty()) {
- return GetDngInformation(tiff_directory, width, height, cfa_pattern_dim);
- } else {
- return GetDngInformation(tiff_directory.GetSubDirectories()[0], width,
- height, cfa_pattern_dim);
- }
-}
-
-bool GetPreviewData(const TagSet& extended_tags,
- const std::uint32_t tiff_offset,
- const std::uint32_t number_of_ifds, StreamInterface* stream,
- TiffContent* tiff_content,
- PreviewImageData* preview_image_data) {
- TagSet desired_tags = {
- kExifTagColorSpace, kExifTagDateTimeOriginal, kExifTagExposureTime,
- kExifTagFnumber, kExifTagFocalLength, kExifTagGps,
- kExifTagIsoSpeed, kTiffTagCompression, kTiffTagDateTime,
- kTiffTagExifIfd, kTiffTagCfaPatternDim, kTiffTagMake,
- kTiffTagModel, kTiffTagOrientation, kTiffTagPhotometric};
- desired_tags.insert(extended_tags.cbegin(), extended_tags.cend());
-
- TiffParser tiff_parser(stream, tiff_offset);
-
- if (!tiff_parser.Parse(desired_tags, number_of_ifds, tiff_content)) {
- return false;
- }
- if (tiff_content->tiff_directory.empty()) {
- // Returns false if the stream does not contain any TIFF structure.
- return false;
- }
- return tiff_parser.GetPreviewImageData(*tiff_content, preview_image_data);
-}
-
-bool GetPreviewData(const TagSet& extended_tags,
- const std::uint32_t number_of_ifds, StreamInterface* stream,
- PreviewImageData* preview_image_data) {
- const std::uint32_t kTiffOffset = 0;
- TiffContent tiff_content;
- return GetPreviewData(extended_tags, kTiffOffset, number_of_ifds, stream,
- &tiff_content, preview_image_data);
-}
-
-bool GetExifData(const std::uint32_t exif_offset, StreamInterface* stream,
- PreviewImageData* preview_image_data) {
- const TagSet kExtendedTags = {kTiffTagJpegByteCount, kTiffTagJpegOffset};
- const std::uint32_t kNumberOfIfds = 2;
- TiffContent tiff_content;
- return GetPreviewData(kExtendedTags, exif_offset, kNumberOfIfds, stream,
- &tiff_content, preview_image_data);
-}
-
-// Reads the jpeg compressed thumbnail information.
-void GetThumbnailOffsetAndLength(const TagSet& extended_tags,
- StreamInterface* stream,
- PreviewImageData* preview_image_data) {
- TagSet desired_tags = {kTiffTagJpegByteCount, kTiffTagJpegOffset};
- desired_tags.insert(extended_tags.cbegin(), extended_tags.cend());
-
- const std::uint32_t kNumberOfIfds = 2;
- PreviewImageData thumbnail_data;
- if (GetPreviewData(desired_tags, kNumberOfIfds, stream, &thumbnail_data)) {
- preview_image_data->thumbnail = thumbnail_data.thumbnail;
- }
-}
-
-bool GetExifIfd(const Endian endian, StreamInterface* stream,
- TiffDirectory* exif_ifd) {
- const std::uint32_t kTiffOffset = 0;
- std::uint32_t offset_to_ifd;
- if (!Get32u(stream, sizeof(offset_to_ifd), endian, &offset_to_ifd)) {
- return false;
- }
-
- std::uint32_t next_ifd_offset;
- TiffDirectory tiff_ifd(endian);
- if (!ParseDirectory(kTiffOffset, offset_to_ifd, endian, {kTiffTagExifIfd},
- stream, &tiff_ifd, &next_ifd_offset)) {
- return false;
- }
-
- std::uint32_t exif_offset;
- if (tiff_ifd.Get(kTiffTagExifIfd, &exif_offset)) {
- return ParseDirectory(kTiffOffset, exif_offset, endian,
- {kExifTagMakernotes}, stream, exif_ifd,
- &next_ifd_offset);
- }
-
- return true;
-}
-
-bool GetMakernoteIfd(const TiffDirectory& exif_ifd, const Endian endian,
- const std::uint32_t skip_offset, StreamInterface* stream,
- std::uint32_t* makernote_offset,
- TiffDirectory* makernote_ifd) {
- std::uint32_t makernote_length;
- if (!exif_ifd.GetOffsetAndLength(kExifTagMakernotes,
- tiff_directory::TIFF_TYPE_UNDEFINED,
- makernote_offset, &makernote_length)) {
- return false;
- }
-
- std::uint32_t next_ifd_offset;
- return ParseDirectory(*makernote_offset, *makernote_offset + skip_offset,
- endian, {kTiffTagImageWidth, kOlymTagCameraSettings,
- kOlymTagRawProcessing, kPentaxTagColorSpace},
- stream, makernote_ifd, &next_ifd_offset);
-}
-
-bool GetCameraSettingsIfd(const TiffDirectory& makernote_ifd,
- const std::uint32_t makernote_offset,
- const Endian endian, StreamInterface* stream,
- TiffDirectory* camera_settings_ifd) {
- std::uint32_t camera_settings_offset;
- std::uint32_t camera_settings_length;
- if (!makernote_ifd.GetOffsetAndLength(
- kOlymTagCameraSettings, tiff_directory::TIFF_IFD,
- &camera_settings_offset, &camera_settings_length)) {
- return false;
- }
-
- std::uint32_t next_ifd_offset;
- if (!Get32u(stream, camera_settings_offset, endian,
- &camera_settings_offset)) {
- return false;
- }
- return ParseDirectory(makernote_offset,
- makernote_offset + camera_settings_offset, endian,
- {kTiffTagBitsPerSample, kTiffTagImageLength}, stream,
- camera_settings_ifd, &next_ifd_offset);
-}
-
-bool GetRawProcessingIfd(const TagSet& desired_tags,
- const TiffDirectory& makernote_ifd,
- const std::uint32_t makernote_offset,
- const Endian endian, StreamInterface* stream,
- TiffDirectory* raw_processing_ifd) {
- std::uint32_t raw_processing_offset;
- std::uint32_t raw_processing_length;
- if (!makernote_ifd.GetOffsetAndLength(
- kOlymTagRawProcessing, tiff_directory::TIFF_IFD,
- &raw_processing_offset, &raw_processing_length)) {
- return false;
- }
-
- std::uint32_t next_ifd_offset;
- if (!Get32u(stream, raw_processing_offset, endian, &raw_processing_offset)) {
- return false;
- }
-
- return ParseDirectory(
- makernote_offset, makernote_offset + raw_processing_offset, endian,
- desired_tags, stream, raw_processing_ifd, &next_ifd_offset);
-}
-
-// Retrieves the preview image offset and length from the camera settings and
-// the 'full_width' and 'full_height' from the raw processing ifd in 'stream'.
-// Returns false if anything is wrong.
-bool GetOlympusPreviewImage(StreamInterface* stream,
- PreviewImageData* preview_image_data) {
- Endian endian;
- if (!GetEndianness(0 /* tiff offset */, stream, &endian)) {
- return false;
- }
-
- TiffDirectory exif_ifd(endian);
- if (!GetExifIfd(endian, stream, &exif_ifd)) {
- return false;
- }
-
- std::uint32_t makernote_offset;
- TiffDirectory makernote_ifd(endian);
- const std::uint32_t kSkipMakernoteStart = 12;
- if (!GetMakernoteIfd(exif_ifd, endian, kSkipMakernoteStart, stream,
- &makernote_offset, &makernote_ifd)) {
- return false;
- }
-
- const std::uint32_t kThumbnailTag = 0x0100;
- if (makernote_ifd.Has(kThumbnailTag)) {
- if (!makernote_ifd.GetOffsetAndLength(
- kThumbnailTag, tiff_directory::TIFF_TYPE_UNDEFINED,
- &preview_image_data->thumbnail.offset,
- &preview_image_data->thumbnail.length)) {
- return false;
- }
- }
-
- TiffDirectory camera_settings_ifd(endian);
- if (!GetCameraSettingsIfd(makernote_ifd, makernote_offset, endian, stream,
- &camera_settings_ifd)) {
- return false;
- }
-
- const std::uint32_t kPreviewOffset = 0x0101;
- const std::uint32_t kPreviewLength = 0x0102;
- if (!camera_settings_ifd.Has(kPreviewOffset) ||
- !camera_settings_ifd.Has(kPreviewLength)) {
- return false;
- }
-
- camera_settings_ifd.Get(kPreviewOffset, &preview_image_data->preview.offset);
- preview_image_data->preview.offset += makernote_offset;
- camera_settings_ifd.Get(kPreviewLength, &preview_image_data->preview.length);
-
- // Get the crop size from the raw processing ifd.
- TiffDirectory raw_processing_ifd(endian);
- if (!GetRawProcessingIfd({kOlymTagAspectFrame}, makernote_ifd,
- makernote_offset, endian, stream,
- &raw_processing_ifd)) {
- return false;
- }
-
- if (raw_processing_ifd.Has(kOlymTagAspectFrame)) {
- std::vector<std::uint32_t> aspect_frame;
- if (raw_processing_ifd.Get(kOlymTagAspectFrame, &aspect_frame) &&
- aspect_frame.size() == 4 && aspect_frame[2] > aspect_frame[0] &&
- aspect_frame[3] > aspect_frame[1]) {
- preview_image_data->full_width = aspect_frame[2] - aspect_frame[0] + 1;
- preview_image_data->full_height = aspect_frame[3] - aspect_frame[1] + 1;
- if (preview_image_data->full_width < preview_image_data->full_height) {
- std::swap(preview_image_data->full_width,
- preview_image_data->full_height);
- }
- }
- }
-
- return true;
-}
-
-bool PefGetColorSpace(StreamInterface* stream,
- PreviewImageData* preview_image_data) {
- Endian endian;
- if (!GetEndianness(0 /* tiff offset */, stream, &endian)) {
- return false;
- }
-
- TiffDirectory exif_ifd(endian);
- if (!GetExifIfd(endian, stream, &exif_ifd)) {
- return false;
- }
-
- std::uint32_t makernote_offset;
- TiffDirectory makernote_ifd(endian);
- const std::uint32_t kSkipMakernoteStart = 6;
- if (!GetMakernoteIfd(exif_ifd, endian, kSkipMakernoteStart, stream,
- &makernote_offset, &makernote_ifd)) {
- return false;
- }
- if (makernote_ifd.Has(kPentaxTagColorSpace)) {
- std::uint32_t color_space;
- if (!makernote_ifd.Get(kPentaxTagColorSpace, &color_space)) {
- return false;
- }
- preview_image_data->color_space = color_space == 0
- ? PreviewImageData::kSrgb
- : PreviewImageData::kAdobeRgb;
- }
- return true;
-}
-
-bool RafGetOrientation(StreamInterface* stream, std::uint32_t* orientation) {
- // Parse the Fuji RAW header to get the offset and length of the preview
- // image, which contains the Exif information.
- const Endian endian = tiff_directory::kBigEndian;
- std::uint32_t preview_offset = 0;
- if (!Get32u(stream, kRafOffsetToPreviewOffset, endian, &preview_offset)) {
- return false;
- }
-
- const std::uint32_t exif_offset = preview_offset + 12;
- return GetExifOrientation(stream, exif_offset, orientation);
-}
-
-// Parses the Fuji Cfa header for the image width and height.
-bool RafGetDimension(StreamInterface* stream, std::uint32_t* width,
- std::uint32_t* height) {
- const Endian endian = tiff_directory::kBigEndian;
- std::uint32_t cfa_header_index = 0; // actual position in the cfa header.
- std::uint32_t cfa_header_entries = 0;
- if (!Get32u(stream, 92 /* cfa header offset */, endian, &cfa_header_index) ||
- !Get32u(stream, cfa_header_index, endian, &cfa_header_entries)) {
- return false;
- }
-
- // Add 4 to point to the actual read position in the cfa header.
- cfa_header_index += 4;
-
- for (std::uint32_t i = 0; i < cfa_header_entries; ++i) {
- std::uint16_t id = 0;
- std::uint16_t length = 0;
- if (!Get16u(stream, cfa_header_index, endian, &id) ||
- !Get16u(stream, cfa_header_index + 2, endian, &length)) {
- return false;
- }
-
- std::uint16_t tmp_width = 0;
- std::uint16_t tmp_height = 0;
- if (id == 0x0111 /* tags the crop dimensions */ &&
- Get16u(stream, cfa_header_index + 4, endian, &tmp_height) &&
- Get16u(stream, cfa_header_index + 6, endian, &tmp_width)) {
- *width = tmp_width;
- *height = tmp_height;
- return true;
- }
- cfa_header_index += 4u + length;
- }
- return false;
-}
-
-Error ArwGetPreviewData(StreamInterface* stream,
- PreviewImageData* preview_image_data) {
- const TagSet extended_tags = {kExifTagHeight, kExifTagWidth,
- kTiffTagJpegByteCount, kTiffTagJpegOffset,
- kTiffTagSubIfd};
-
- GetThumbnailOffsetAndLength(TagSet(), stream, preview_image_data);
-
- const std::uint32_t kNumberOfIfds = 1;
- if (GetPreviewData(extended_tags, kNumberOfIfds, stream,
- preview_image_data)) {
- return kOk;
- }
- return kFail;
-}
-
-Error Cr2GetPreviewData(StreamInterface* stream,
- PreviewImageData* preview_image_data) {
- const TagSet extended_tags = {kExifTagHeight, kExifTagWidth,
- kTiffTagStripByteCounts, kTiffTagStripOffsets};
-
- GetThumbnailOffsetAndLength(TagSet(), stream, preview_image_data);
-
- const std::uint32_t kNumberOfIfds = 1;
- if (GetPreviewData(extended_tags, kNumberOfIfds, stream,
- preview_image_data)) {
- return kOk;
- }
- return kFail;
-}
-
-Error DngGetPreviewData(StreamInterface* stream,
- PreviewImageData* preview_image_data) {
- // Some thumbnails from DngCreator are larger than the specified 256 pixel.
- const int kDngThumbnailMaxDimension = 512;
-
- const TagSet extended_tags = {
- kExifTagDefaultCropSize, kTiffTagImageWidth, kTiffTagImageLength,
- kTiffTagStripByteCounts, kTiffTagStripOffsets, kTiffTagSubIfd};
-
- TiffContent tiff_content;
- const std::uint32_t kNumberOfIfds = 3;
- if (!GetPreviewData(extended_tags, 0, kNumberOfIfds, stream, &tiff_content,
- preview_image_data)) {
- return kFail;
- }
-
- const TiffDirectory& tiff_directory = tiff_content.tiff_directory[0];
-
- if (!GetFullCropDimension(tiff_directory, &preview_image_data->full_width,
- &preview_image_data->full_height)) {
- return kFail;
- }
-
- // Find the jpeg compressed thumbnail and preview image.
- Image preview;
- Image thumbnail;
-
- // Search for images in IFD0
- Image temp_image;
- if (GetImageData(tiff_directory, stream, &temp_image)) {
- if (IsThumbnail(temp_image, kDngThumbnailMaxDimension)) {
- thumbnail = temp_image;
- } else if (temp_image.format == Image::kJpegCompressed) {
- preview = temp_image;
- }
- }
-
- // Search for images in other IFDs
- for (const auto& ifd : tiff_directory.GetSubDirectories()) {
- if (GetImageData(ifd, stream, &temp_image)) {
- // Try to find the largest thumbnail/preview.
- if (IsThumbnail(temp_image, kDngThumbnailMaxDimension)) {
- if (temp_image > thumbnail) {
- thumbnail = temp_image;
- }
- } else {
- if (temp_image > preview &&
- temp_image.format == Image::kJpegCompressed) {
- preview = temp_image;
- }
- }
- }
- }
- preview_image_data->preview = preview;
- preview_image_data->thumbnail = thumbnail;
-
- return kOk;
-}
-
-Error NefGetPreviewData(StreamInterface* stream,
- PreviewImageData* preview_image_data) {
- const TagSet extended_tags = {kTiffTagImageWidth, kTiffTagImageLength,
- kTiffTagJpegByteCount, kTiffTagJpegOffset,
- kTiffTagStripByteCounts, kTiffTagStripOffsets,
- kTiffTagSubIfd};
- const std::uint32_t kNumberOfIfds = 2;
- if (!GetPreviewData(extended_tags, kNumberOfIfds, stream,
- preview_image_data)) {
- return kFail;
- }
-
- if (preview_image_data->thumbnail.length == 0) {
- PreviewImageData thumbnail_data;
- GetThumbnailOffsetAndLength(TagSet(), stream, &thumbnail_data);
- preview_image_data->thumbnail = thumbnail_data.thumbnail;
- }
-
- // The Nikon RAW data provides the dimensions of the sensor image, which are
- // slightly larger than the dimensions of the preview image. In order to
- // determine the correct full width and height of the image, the preview image
- // size needs to be taken into account. Based on experiments the preview image
- // dimensions must be at least 90% of the sensor image dimensions to let it be
- // a full size preview image.
- if (preview_image_data->preview.length > 0) { // when preview image exists
- const float kEpsilon = 0.9f;
-
- std::uint16_t width;
- std::uint16_t height;
- if (!GetJpegDimensions(preview_image_data->preview.offset, stream, &width,
- &height) ||
- preview_image_data->full_width == 0 ||
- preview_image_data->full_height == 0) {
- return kUnsupported;
- }
-
- if (static_cast<float>(width) /
- static_cast<float>(preview_image_data->full_width) >
- kEpsilon ||
- static_cast<float>(height) /
- static_cast<float>(preview_image_data->full_height) >
- kEpsilon) {
- preview_image_data->full_width = width;
- preview_image_data->full_height = height;
- }
- }
- return kOk;
-}
-
-Error OrfGetPreviewData(StreamInterface* stream,
- PreviewImageData* preview_image_data) {
- if (!GetExifData(0, stream, preview_image_data)) {
- return kFail;
- }
- // Omit errors, because some images do not contain any preview data.
- GetOlympusPreviewImage(stream, preview_image_data);
- return kOk;
-}
-
-Error PefGetPreviewData(StreamInterface* stream,
- PreviewImageData* preview_image_data) {
- const TagSet extended_tags = {kTiffTagImageWidth, kTiffTagImageLength,
- kTiffTagJpegByteCount, kTiffTagJpegOffset,
- kTiffTagSubIfd};
- const std::uint32_t kNumberOfIfds = 3;
- if (!GetPreviewData(extended_tags, kNumberOfIfds, stream,
- preview_image_data) ||
- !PefGetColorSpace(stream, preview_image_data)) {
- return kFail;
- }
-
- PreviewImageData thumbnail_data;
- GetThumbnailOffsetAndLength(TagSet(), stream, &thumbnail_data);
- preview_image_data->thumbnail = thumbnail_data.thumbnail;
-
- return kOk;
-}
-
-Error RafGetPreviewData(StreamInterface* stream,
- PreviewImageData* preview_image_data) {
- // Parse the Fuji RAW header to get the offset and length of the preview
- // image, which contains the Exif information.
- const Endian endian = tiff_directory::kBigEndian;
- std::uint32_t preview_offset = 0;
- std::uint32_t preview_length = 0;
- if (!Get32u(stream, kRafOffsetToPreviewOffset, endian, &preview_offset) ||
- !Get32u(stream, kRafOffsetToPreviewOffset + 4, endian, &preview_length)) {
- return kFail;
- }
-
- if (!RafGetDimension(stream, &preview_image_data->full_width,
- &preview_image_data->full_height)) {
- return kFail;
- }
-
- if (preview_length > 0) { // when preview image exists
- // Parse the Exif information from the preview image.
- const std::uint32_t exif_offset = preview_offset + 12;
- if (!GetExifData(exif_offset, stream, preview_image_data)) {
- return kFail;
- }
- }
-
- // Merge the Exif data with the RAW data to form the preview_image_data.
- preview_image_data->thumbnail.offset += 160; // Skip the cfa header.
- preview_image_data->preview.offset = preview_offset;
- preview_image_data->preview.length = preview_length;
- return kOk;
-}
-
-Error Rw2GetPreviewData(StreamInterface* stream,
- PreviewImageData* preview_image_data) {
- const TagSet extended_tags = {kPanaTagTopBorder, kPanaTagLeftBorder,
- kPanaTagBottomBorder, kPanaTagRightBorder,
- kPanaTagIso, kPanaTagJpegImage,
- kTiffTagJpegByteCount, kTiffTagJpegOffset};
- // Parse the RAW data to get the ISO, offset and length of the preview image,
- // which contains the Exif information.
- const std::uint32_t kNumberOfIfds = 1;
- PreviewImageData preview_data;
- if (!GetPreviewData(extended_tags, kNumberOfIfds, stream, &preview_data)) {
- return kFail;
- }
-
- if (preview_data.preview.length > 0) { // when preview image exists
- // Parse the Exif information from the preview image.
- const std::uint32_t exif_offset = preview_data.preview.offset + 12;
- if (!GetExifData(exif_offset, stream, preview_image_data)) {
- return kFail;
- }
- preview_image_data->thumbnail.offset += exif_offset;
- }
-
- // Merge the Exif data with the RAW data to form the preview_image_data.
- preview_image_data->preview = preview_data.preview;
- preview_image_data->iso = preview_data.iso;
- preview_image_data->full_width = preview_data.full_width;
- preview_image_data->full_height = preview_data.full_height;
-
- return kOk;
-}
-
-Error SrwGetPreviewData(StreamInterface* stream,
- PreviewImageData* preview_image_data) {
- GetThumbnailOffsetAndLength({kTiffTagSubIfd}, stream, preview_image_data);
-
- const TagSet extended_tags = {kExifTagWidth, kExifTagHeight,
- kTiffTagJpegByteCount, kTiffTagJpegOffset,
- kTiffTagSubIfd};
- const std::uint32_t kNumberOfIfds = 1;
- if (!GetPreviewData(extended_tags, kNumberOfIfds, stream,
- preview_image_data)) {
- return kFail;
- }
- return kOk;
-}
-
-} // namespace
-
-size_t BytesRequiredForIsRaw() {
- return image_type_recognition::GetNumberOfBytesForIsRawLite();
-}
-
-bool IsRaw(StreamInterface* data) {
- const size_t bytes = BytesRequiredForIsRaw();
- if (data == nullptr) {
- return false;
- }
-
- // Read required number of bytes into a vector.
- std::vector<std::uint8_t> file_header(bytes);
- if (data->GetData(0, file_header.size(), file_header.data()) != kOk) {
- return false;
- }
-
- RangeCheckedBytePtr data_buffer(file_header.data(), file_header.size());
-
- return image_type_recognition::IsRawLite(data_buffer);
-}
-
-Error GetPreviewImageData(StreamInterface* data,
- PreviewImageData* preview_image_data,
- RawImageTypes* output_type) {
- const size_t bytes = BytesRequiredForIsRaw();
- if (data == nullptr || bytes == 0) {
- return kFail;
- }
-
- std::vector<std::uint8_t> file_header(bytes);
- Error error = data->GetData(0, file_header.size(), file_header.data());
- if (error != kOk) {
- return error;
- }
- RangeCheckedBytePtr header_buffer(file_header.data(), file_header.size());
-
- RawImageTypes type = RecognizeRawImageTypeLite(header_buffer);
- if (output_type != nullptr) *output_type = type;
- switch (type) {
- case image_type_recognition::kArwImage:
- return ArwGetPreviewData(data, preview_image_data);
- case image_type_recognition::kCr2Image:
- return Cr2GetPreviewData(data, preview_image_data);
- case image_type_recognition::kCr3Image:
- return Cr3GetPreviewData(data, preview_image_data);
- case image_type_recognition::kDngImage:
- return DngGetPreviewData(data, preview_image_data);
- case image_type_recognition::kNefImage:
- case image_type_recognition::kNrwImage:
- return NefGetPreviewData(data, preview_image_data);
- case image_type_recognition::kOrfImage:
- return OrfGetPreviewData(data, preview_image_data);
- case image_type_recognition::kPefImage:
- return PefGetPreviewData(data, preview_image_data);
- case image_type_recognition::kRafImage:
- return RafGetPreviewData(data, preview_image_data);
- case image_type_recognition::kRw2Image:
- return Rw2GetPreviewData(data, preview_image_data);
- case image_type_recognition::kSrwImage:
- return SrwGetPreviewData(data, preview_image_data);
- default:
- return kUnsupported;
- }
-}
-
-bool GetDngInformation(StreamInterface* data, std::uint32_t* width,
- std::uint32_t* height,
- std::vector<std::uint32_t>* cfa_pattern_dim) {
- // If IFD0 contains already the full dimensions we do not parse into the sub
- // IFD.
- if (!GetDngInformation({}, data, width, height, cfa_pattern_dim)) {
- return GetDngInformation({kTiffTagSubIfd}, data, width, height,
- cfa_pattern_dim);
- }
- return true;
-}
-
-bool GetOrientation(StreamInterface* data, std::uint32_t* orientation) {
- using image_type_recognition::GetNumberOfBytesForIsOfType;
- using image_type_recognition::IsOfType;
-
- size_t min_header_bytes =
- std::max(GetNumberOfBytesForIsOfType(image_type_recognition::kRafImage),
- GetNumberOfBytesForIsOfType(image_type_recognition::kCr3Image));
-
- std::vector<std::uint8_t> file_header(min_header_bytes);
- if (data->GetData(0, file_header.size(), file_header.data()) != kOk) {
- return false;
- }
-
- // For RAF and CR# files a special routine is necessary to get orientation.
- // For others the general approach is sufficient.
- if (IsOfType(RangeCheckedBytePtr(file_header.data(), file_header.size()),
- image_type_recognition::kRafImage)) {
- return RafGetOrientation(data, orientation);
- } else if (IsOfType(
- RangeCheckedBytePtr(file_header.data(), file_header.size()),
- image_type_recognition::kCr3Image)) {
- return Cr3GetOrientation(data, orientation);
- } else {
- return GetExifOrientation(data, 0 /* offset */, orientation);
- }
-}
-
-std::vector<std::string> SupportedExtensions() {
- return {"ARW", "CR2", "CR3", "DNG", "NEF", "NRW",
- "ORF", "PEF", "RAF", "RW2", "SRW"};
-}
-
-} // namespace piex