diff options
Diffstat (limited to 'src/piex.cc')
-rw-r--r-- | src/piex.cc | 740 |
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 |