#include "image_io/jpeg/jpeg_xmp_data_extractor.h"
|
|
#include <iomanip>
|
#include <sstream>
|
#include <string>
|
|
#include "image_io/base/message_handler.h"
|
#include "image_io/jpeg/jpeg_marker.h"
|
#include "image_io/jpeg/jpeg_segment.h"
|
|
/// Set this flag to 1 for debugging output.
|
#define PHOTOS_EDITING_FORMATS_IMAGE_IO_JPEG_JPEG_XMP_DATA_EXTRACTOR_DEBUG 0
|
|
namespace photos_editing_formats {
|
namespace image_io {
|
|
using std::string;
|
using std::stringstream;
|
|
void JpegXmpDataExtractor::StartTransfer() {
|
data_destination_->StartTransfer();
|
}
|
|
DataDestination::TransferStatus JpegXmpDataExtractor::Transfer(
|
const DataRange& transfer_range, const DataSegment& data_segment) {
|
if (HasError()) {
|
return kTransferError;
|
}
|
#if PHOTOS_EDITING_FORMATS_IMAGE_IO_JPEG_JPEG_XMP_DATA_EXTRACTOR_DEBUG
|
stringstream sstream1;
|
sstream1 << "Segment " << segment_index_ << " of " << last_segment_index_
|
<< " - data range from " << transfer_range.GetBegin() << " to "
|
<< transfer_range.GetEnd();
|
MessageHandler::Get()->ReportMessage(Message::kStatus, sstream1.str());
|
#endif // PHOTOS_EDITING_FORMATS_IMAGE_IO_JPEG_JPEG_XMP_DATA_EXTRACTOR_DEBUG
|
const size_t xmp_header_length = JpegMarker::kLength +
|
JpegSegment::kVariablePayloadDataOffset +
|
kXmpExtendedHeaderSize;
|
size_t encoded_data_begin = transfer_range.GetBegin() + xmp_header_length;
|
size_t xmp_data_begin = encoded_data_begin;
|
size_t xmp_data_end = transfer_range.GetEnd();
|
if (segment_index_ == 0) {
|
string property_name = JpegXmpInfo::GetDataPropertyName(xmp_info_type_);
|
size_t gdepth_data_location = data_segment.Find(
|
encoded_data_begin, property_name.c_str(), property_name.length());
|
if (gdepth_data_location != transfer_range.GetEnd()) {
|
size_t quote_location = data_segment.Find(gdepth_data_location, '"');
|
if (quote_location != transfer_range.GetEnd()) {
|
xmp_data_begin = quote_location + 1;
|
}
|
}
|
if (xmp_data_begin == encoded_data_begin) {
|
if (message_handler_) {
|
message_handler_->ReportMessage(Message::kStringNotFoundError,
|
property_name + "=\"");
|
}
|
has_error_ = true;
|
return kTransferError;
|
}
|
}
|
if (segment_index_ == last_segment_index_) {
|
xmp_data_end = data_segment.Find(xmp_data_begin, '"');
|
if (xmp_data_end == transfer_range.GetEnd()) {
|
if (message_handler_) {
|
message_handler_->ReportMessage(Message::kStringNotFoundError, "\"");
|
}
|
has_error_ = true;
|
return kTransferError;
|
}
|
}
|
|
DataRange xmp_data_range(xmp_data_begin, xmp_data_end);
|
#if PHOTOS_EDITING_FORMATS_IMAGE_IO_JPEG_JPEG_XMP_DATA_EXTRACTOR_DEBUG
|
string strb((const char*)data_segment.GetBuffer(xmp_data_range.GetBegin()),
|
50);
|
string stre((const char*)data_segment.GetBuffer(xmp_data_end - 50), 50);
|
stringstream sstream2;
|
sstream2 << " " << xmp_data_begin << ":" << xmp_data_end << " = "
|
<< xmp_data_range.GetLength() << " bytes: [" << strb << "..." << stre
|
<< "] - ";
|
MessageHandler::Get()->ReportMessage(Message::kStatus, sstream2.str());
|
for (size_t i = transfer_range.GetBegin(); i < data_segment.GetEnd();
|
i += 32) {
|
stringstream hex_stream, ascii_stream;
|
hex_stream << std::hex << std::setfill('0') << std::setw(2)
|
<< std::uppercase;
|
for (size_t j = 0; j < 32 && (i + j) < data_segment.GetEnd(); ++j) {
|
Byte value = data_segment.GetValidatedByte(i + j).value;
|
hex_stream << " " << size_t(value);
|
ascii_stream << (isprint(value) ? static_cast<char>(value) : '.');
|
}
|
stringstream sstream3;
|
sstream3 << " * " << std::hex << std::setfill('0') << std::setw(8)
|
<< std::uppercase << i;
|
sstream3 << ":" << hex_stream.str() << " [" << ascii_stream.str() << "]";
|
MessageHandler::Get()->ReportMessage(Message::kStatus, sstream3.str());
|
}
|
#endif // PHOTOS_EDITING_FORMATS_IMAGE_IO_JPEG_JPEG_XMP_DATA_EXTRACTOR_DEBUG
|
return data_destination_->Transfer(xmp_data_range, data_segment);
|
}
|
|
void JpegXmpDataExtractor::FinishTransfer() {
|
data_destination_->FinishTransfer();
|
}
|
|
} // namespace image_io
|
} // namespace photos_editing_formats
|