• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "image_io/jpeg/jpeg_image_extractor.h"
2 
3 #include <sstream>
4 
5 #include "image_io/base/data_range_tracking_destination.h"
6 #include "image_io/base/message_handler.h"
7 #include "image_io/extras/base64_decoder_data_destination.h"
8 #include "image_io/jpeg/jpeg_segment.h"
9 #include "image_io/jpeg/jpeg_xmp_data_extractor.h"
10 
11 /// Set this macro to 1 for debug output.
12 #define PHOTOS_EDITING_FORMATS_IMAGE_IO_JPEG_JPEG_IMAGE_EXTRACTOR_DEBUG 0
13 
14 namespace photos_editing_formats {
15 namespace image_io {
16 
17 using std::vector;
18 
19 namespace {
20 
21 /// The optimim size to use for the DataSource::TransferData() function.
22 constexpr size_t kBestDataSize = 0x10000;
23 
24 }  // namespace
25 
ExtractAppleDepthImage(DataDestination * image_destination)26 bool JpegImageExtractor::ExtractAppleDepthImage(
27     DataDestination* image_destination) {
28   bool succeeded =
29       ExtractImage(jpeg_info_.GetAppleDepthImageRange(), image_destination);
30   return jpeg_info_.HasAppleDepth() && succeeded;
31 }
32 
ExtractAppleMatteImage(DataDestination * image_destination)33 bool JpegImageExtractor::ExtractAppleMatteImage(
34     DataDestination* image_destination) {
35   bool succeeded =
36       ExtractImage(jpeg_info_.GetAppleMatteImageRange(), image_destination);
37   return jpeg_info_.HasAppleMatte() && succeeded;
38 }
39 
ExtractImage(const DataRange & image_range,DataDestination * image_destination)40 bool JpegImageExtractor::ExtractImage(const DataRange& image_range,
41                                       DataDestination* image_destination) {
42   DataRangeTrackingDestination data_range_destination(image_destination);
43   bool has_errors = false;
44   data_range_destination.StartTransfer();
45   if (image_range.IsValid()) {
46     DataSource::TransferDataResult result = data_source_->TransferData(
47         image_range, kBestDataSize, &data_range_destination);
48     if (result == DataSource::kTransferDataError) {
49       has_errors = true;
50     } else if (result == DataSource::kTransferDataNone ||
51                data_range_destination.HasDisjointTransferRanges() ||
52                data_range_destination.GetTrackedDataRange() != image_range) {
53       has_errors = true;
54       if (message_handler_) {
55         message_handler_->ReportMessage(Message::kPrematureEndOfDataError, "");
56       }
57     }
58   }
59   data_range_destination.FinishTransfer();
60   return !has_errors;
61 }
62 
ExtractGDepthImage(DataDestination * image_destination)63 bool JpegImageExtractor::ExtractGDepthImage(
64     DataDestination* image_destination) {
65   return ExtractImage(JpegXmpInfo::kGDepthInfoType, image_destination);
66 }
67 
ExtractGImageImage(DataDestination * image_destination)68 bool JpegImageExtractor::ExtractGImageImage(
69     DataDestination* image_destination) {
70   return ExtractImage(JpegXmpInfo::kGImageInfoType, image_destination);
71 }
72 
ExtractImage(JpegXmpInfo::Type xmp_info_type,DataDestination * image_destination)73 bool JpegImageExtractor::ExtractImage(JpegXmpInfo::Type xmp_info_type,
74                                       DataDestination* image_destination) {
75   bool has_errors = false;
76   const bool has_image = jpeg_info_.HasImage(xmp_info_type);
77   Base64DecoderDataDestination base64_decoder(image_destination,
78                                               message_handler_);
79   const vector<DataRange>& data_ranges =
80       jpeg_info_.GetSegmentDataRanges(xmp_info_type);
81   size_t data_ranges_count = data_ranges.size();
82   JpegXmpDataExtractor xmp_data_extractor(xmp_info_type, data_ranges_count,
83                                           &base64_decoder, message_handler_);
84   xmp_data_extractor.StartTransfer();
85   if (has_image) {
86     for (size_t index = 0; index < data_ranges_count; ++index) {
87       const DataRange& data_range = data_ranges[index];
88       xmp_data_extractor.SetSegmentIndex(index);
89 #if PHOTOS_EDITING_FORMATS_IMAGE_IO_JPEG_JPEG_IMAGE_EXTRACTOR_DEBUG
90       std::stringstream sstream;
91       sstream << "Segment " << index << " from " << data_range.GetBegin()
92               << " to " << data_range.GetEnd();
93       MessageHandler::Get()->ReportMessage(Message::kStatus, sstream.str());
94 #endif  // PHOTOS_EDITING_FORMATS_IMAGE_IO_JPEG_JPEG_IMAGE_EXTRACTOR_DEBUG
95       DataSource::TransferDataResult result = data_source_->TransferData(
96           data_range, kBestDataSize, &xmp_data_extractor);
97       if (result == DataSource::kTransferDataError) {
98         has_errors = true;
99         break;
100       } else if (result == DataSource::kTransferDataNone) {
101         has_errors = true;
102         if (message_handler_) {
103           message_handler_->ReportMessage(Message::kPrematureEndOfDataError,
104                                           "");
105         }
106       }
107     }
108   }
109   xmp_data_extractor.FinishTransfer();
110   return has_image && !has_errors;
111 }
112 
113 }  // namespace image_io
114 }  // namespace photos_editing_formats
115