1 #include "image_io/jpeg/jpeg_xmp_data_extractor.h"
2
3 #include <iomanip>
4 #include <sstream>
5 #include <string>
6
7 #include "image_io/base/message_handler.h"
8 #include "image_io/jpeg/jpeg_marker.h"
9 #include "image_io/jpeg/jpeg_segment.h"
10
11 /// Set this flag to 1 for debugging output.
12 #define PHOTOS_EDITING_FORMATS_IMAGE_IO_JPEG_JPEG_XMP_DATA_EXTRACTOR_DEBUG 0
13
14 namespace photos_editing_formats {
15 namespace image_io {
16
17 using std::string;
18 using std::stringstream;
19
StartTransfer()20 void JpegXmpDataExtractor::StartTransfer() {
21 data_destination_->StartTransfer();
22 }
23
Transfer(const DataRange & transfer_range,const DataSegment & data_segment)24 DataDestination::TransferStatus JpegXmpDataExtractor::Transfer(
25 const DataRange& transfer_range, const DataSegment& data_segment) {
26 if (HasError()) {
27 return kTransferError;
28 }
29 #if PHOTOS_EDITING_FORMATS_IMAGE_IO_JPEG_JPEG_XMP_DATA_EXTRACTOR_DEBUG
30 stringstream sstream1;
31 sstream1 << "Segment " << segment_index_ << " of " << last_segment_index_
32 << " - data range from " << transfer_range.GetBegin() << " to "
33 << transfer_range.GetEnd();
34 MessageHandler::Get()->ReportMessage(Message::kStatus, sstream1.str());
35 #endif // PHOTOS_EDITING_FORMATS_IMAGE_IO_JPEG_JPEG_XMP_DATA_EXTRACTOR_DEBUG
36 const size_t xmp_header_length = JpegMarker::kLength +
37 JpegSegment::kVariablePayloadDataOffset +
38 kXmpExtendedHeaderSize;
39 size_t encoded_data_begin = transfer_range.GetBegin() + xmp_header_length;
40 size_t xmp_data_begin = encoded_data_begin;
41 size_t xmp_data_end = transfer_range.GetEnd();
42 if (segment_index_ == 0) {
43 string property_name = JpegXmpInfo::GetDataPropertyName(xmp_info_type_);
44 size_t gdepth_data_location = data_segment.Find(
45 encoded_data_begin, property_name.c_str(), property_name.length());
46 if (gdepth_data_location != transfer_range.GetEnd()) {
47 size_t quote_location = data_segment.Find(gdepth_data_location, '"');
48 if (quote_location != transfer_range.GetEnd()) {
49 xmp_data_begin = quote_location + 1;
50 }
51 }
52 if (xmp_data_begin == encoded_data_begin) {
53 if (message_handler_) {
54 message_handler_->ReportMessage(Message::kStringNotFoundError,
55 property_name + "=\"");
56 }
57 has_error_ = true;
58 return kTransferError;
59 }
60 }
61 if (segment_index_ == last_segment_index_) {
62 xmp_data_end = data_segment.Find(xmp_data_begin, '"');
63 if (xmp_data_end == transfer_range.GetEnd()) {
64 if (message_handler_) {
65 message_handler_->ReportMessage(Message::kStringNotFoundError, "\"");
66 }
67 has_error_ = true;
68 return kTransferError;
69 }
70 }
71
72 DataRange xmp_data_range(xmp_data_begin, xmp_data_end);
73 #if PHOTOS_EDITING_FORMATS_IMAGE_IO_JPEG_JPEG_XMP_DATA_EXTRACTOR_DEBUG
74 string strb((const char*)data_segment.GetBuffer(xmp_data_range.GetBegin()),
75 50);
76 string stre((const char*)data_segment.GetBuffer(xmp_data_end - 50), 50);
77 stringstream sstream2;
78 sstream2 << " " << xmp_data_begin << ":" << xmp_data_end << " = "
79 << xmp_data_range.GetLength() << " bytes: [" << strb << "..." << stre
80 << "] - ";
81 MessageHandler::Get()->ReportMessage(Message::kStatus, sstream2.str());
82 for (size_t i = transfer_range.GetBegin(); i < data_segment.GetEnd();
83 i += 32) {
84 stringstream hex_stream, ascii_stream;
85 hex_stream << std::hex << std::setfill('0') << std::setw(2)
86 << std::uppercase;
87 for (size_t j = 0; j < 32 && (i + j) < data_segment.GetEnd(); ++j) {
88 Byte value = data_segment.GetValidatedByte(i + j).value;
89 hex_stream << " " << size_t(value);
90 ascii_stream << (isprint(value) ? static_cast<char>(value) : '.');
91 }
92 stringstream sstream3;
93 sstream3 << " * " << std::hex << std::setfill('0') << std::setw(8)
94 << std::uppercase << i;
95 sstream3 << ":" << hex_stream.str() << " [" << ascii_stream.str() << "]";
96 MessageHandler::Get()->ReportMessage(Message::kStatus, sstream3.str());
97 }
98 #endif // PHOTOS_EDITING_FORMATS_IMAGE_IO_JPEG_JPEG_XMP_DATA_EXTRACTOR_DEBUG
99 return data_destination_->Transfer(xmp_data_range, data_segment);
100 }
101
FinishTransfer()102 void JpegXmpDataExtractor::FinishTransfer() {
103 data_destination_->FinishTransfer();
104 }
105
106 } // namespace image_io
107 } // namespace photos_editing_formats
108