aboutsummaryrefslogtreecommitdiff
path: root/third_party/image_io/src/jpeg/jpeg_image_extractor.cc
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/image_io/src/jpeg/jpeg_image_extractor.cc')
-rw-r--r--third_party/image_io/src/jpeg/jpeg_image_extractor.cc114
1 files changed, 114 insertions, 0 deletions
diff --git a/third_party/image_io/src/jpeg/jpeg_image_extractor.cc b/third_party/image_io/src/jpeg/jpeg_image_extractor.cc
new file mode 100644
index 0000000..b915839
--- /dev/null
+++ b/third_party/image_io/src/jpeg/jpeg_image_extractor.cc
@@ -0,0 +1,114 @@
+#include "image_io/jpeg/jpeg_image_extractor.h"
+
+#include <sstream>
+
+#include "image_io/base/data_range_tracking_destination.h"
+#include "image_io/base/message_handler.h"
+#include "image_io/extras/base64_decoder_data_destination.h"
+#include "image_io/jpeg/jpeg_segment.h"
+#include "image_io/jpeg/jpeg_xmp_data_extractor.h"
+
+/// Set this macro to 1 for debug output.
+#define PHOTOS_EDITING_FORMATS_IMAGE_IO_JPEG_JPEG_IMAGE_EXTRACTOR_DEBUG 0
+
+namespace photos_editing_formats {
+namespace image_io {
+
+using std::vector;
+
+namespace {
+
+/// The optimim size to use for the DataSource::TransferData() function.
+constexpr size_t kBestDataSize = 0x10000;
+
+} // namespace
+
+bool JpegImageExtractor::ExtractAppleDepthImage(
+ DataDestination* image_destination) {
+ bool succeeded =
+ ExtractImage(jpeg_info_.GetAppleDepthImageRange(), image_destination);
+ return jpeg_info_.HasAppleDepth() && succeeded;
+}
+
+bool JpegImageExtractor::ExtractAppleMatteImage(
+ DataDestination* image_destination) {
+ bool succeeded =
+ ExtractImage(jpeg_info_.GetAppleMatteImageRange(), image_destination);
+ return jpeg_info_.HasAppleMatte() && succeeded;
+}
+
+bool JpegImageExtractor::ExtractImage(const DataRange& image_range,
+ DataDestination* image_destination) {
+ DataRangeTrackingDestination data_range_destination(image_destination);
+ bool has_errors = false;
+ data_range_destination.StartTransfer();
+ if (image_range.IsValid()) {
+ DataSource::TransferDataResult result = data_source_->TransferData(
+ image_range, kBestDataSize, &data_range_destination);
+ if (result == DataSource::kTransferDataError) {
+ has_errors = true;
+ } else if (result == DataSource::kTransferDataNone ||
+ data_range_destination.HasDisjointTransferRanges() ||
+ data_range_destination.GetTrackedDataRange() != image_range) {
+ has_errors = true;
+ if (message_handler_) {
+ message_handler_->ReportMessage(Message::kPrematureEndOfDataError, "");
+ }
+ }
+ }
+ data_range_destination.FinishTransfer();
+ return !has_errors;
+}
+
+bool JpegImageExtractor::ExtractGDepthImage(
+ DataDestination* image_destination) {
+ return ExtractImage(JpegXmpInfo::kGDepthInfoType, image_destination);
+}
+
+bool JpegImageExtractor::ExtractGImageImage(
+ DataDestination* image_destination) {
+ return ExtractImage(JpegXmpInfo::kGImageInfoType, image_destination);
+}
+
+bool JpegImageExtractor::ExtractImage(JpegXmpInfo::Type xmp_info_type,
+ DataDestination* image_destination) {
+ bool has_errors = false;
+ const bool has_image = jpeg_info_.HasImage(xmp_info_type);
+ Base64DecoderDataDestination base64_decoder(image_destination,
+ message_handler_);
+ const vector<DataRange>& data_ranges =
+ jpeg_info_.GetSegmentDataRanges(xmp_info_type);
+ size_t data_ranges_count = data_ranges.size();
+ JpegXmpDataExtractor xmp_data_extractor(xmp_info_type, data_ranges_count,
+ &base64_decoder, message_handler_);
+ xmp_data_extractor.StartTransfer();
+ if (has_image) {
+ for (size_t index = 0; index < data_ranges_count; ++index) {
+ const DataRange& data_range = data_ranges[index];
+ xmp_data_extractor.SetSegmentIndex(index);
+#if PHOTOS_EDITING_FORMATS_IMAGE_IO_JPEG_JPEG_IMAGE_EXTRACTOR_DEBUG
+ std::stringstream sstream;
+ sstream << "Segment " << index << " from " << data_range.GetBegin()
+ << " to " << data_range.GetEnd();
+ MessageHandler::Get()->ReportMessage(Message::kStatus, sstream.str());
+#endif // PHOTOS_EDITING_FORMATS_IMAGE_IO_JPEG_JPEG_IMAGE_EXTRACTOR_DEBUG
+ DataSource::TransferDataResult result = data_source_->TransferData(
+ data_range, kBestDataSize, &xmp_data_extractor);
+ if (result == DataSource::kTransferDataError) {
+ has_errors = true;
+ break;
+ } else if (result == DataSource::kTransferDataNone) {
+ has_errors = true;
+ if (message_handler_) {
+ message_handler_->ReportMessage(Message::kPrematureEndOfDataError,
+ "");
+ }
+ }
+ }
+ }
+ xmp_data_extractor.FinishTransfer();
+ return has_image && !has_errors;
+}
+
+} // namespace image_io
+} // namespace photos_editing_formats