• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "image_io/jpeg/jpeg_segment_builder.h"
2 
3 #include "image_io/jpeg/jpeg_marker.h"
4 
5 namespace photos_editing_formats {
6 namespace image_io {
7 
8 using std::string;
9 
10 // The strings needed to build the xml data associated with XMP data. See
11 // https://wwwimages2.adobe.com/content/dam/acom/en/devnet/xmp/pdfs/
12 //   XMP%20SDK%20Release%20cc-2016-08/XMPSpecificationPart1.pdf
13 const char kXmpMetaPrefix[] = "<x:xmpmeta xmlns:x=\"adobe:ns:meta/\">";
14 const char kXmpMetaSuffix[] = "</x:xmpmeta>";
15 const char kRdfPrefix[] =
16     "<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\""
17     "xmlns:xmp=\"http://ns.adobe.com/xap/1.0/\">";
18 const char kRdfSuffix[] = "</rdf:RDF>";
19 const char kRdfDescriptionPrefix[] = "<rdf:Description rdf:about=\"\"";
20 const char kRdfDescriptionSuffix[] = "/>";
21 
SetPayloadSize(ByteBuffer * byte_buffer)22 bool JpegSegmentBuilder::SetPayloadSize(ByteBuffer* byte_buffer) {
23   std::uint16_t size = byte_buffer->GetSize();
24   if (size == byte_buffer->GetSize() && size >= 4) {
25     return byte_buffer->SetBigEndianValue(2, size - 2);
26   }
27   return false;
28 }
29 
GetByteDataValues() const30 string JpegSegmentBuilder::GetByteDataValues() const {
31   string values;
32   for (const auto& byte_datum : byte_data_) {
33     if (!byte_datum.IsValid()) {
34       return "";
35     }
36     values += byte_datum.GetValue();
37     if (byte_datum.GetType() == ByteData::kAscii0) {
38       values.append(1, 0);
39     }
40   }
41   return values;
42 }
43 
AddMarkerAndSize(Byte marker_type,size_t size)44 void JpegSegmentBuilder::AddMarkerAndSize(Byte marker_type, size_t size) {
45   JpegMarker marker(marker_type);
46   string hex_string = marker.GetHexString("FF");
47   if (marker.HasVariablePayloadSize()) {
48     hex_string += ByteData::Byte2Hex((size >> 8) & 0xFF);
49     hex_string += ByteData::Byte2Hex(size & 0xFF);
50   }
51   byte_data_.emplace_back(ByteData::kHex, hex_string);
52 }
53 
AddMarkerAndSizePlaceholder(Byte marker_type)54 size_t JpegSegmentBuilder::AddMarkerAndSizePlaceholder(Byte marker_type) {
55   JpegMarker marker(marker_type);
56   string hex_string = marker.GetHexString("FF");
57   if (marker.HasVariablePayloadSize()) {
58     hex_string += "0000";
59   }
60   byte_data_.emplace_back(ByteData::kHex, hex_string);
61   return byte_data_.size() - 1;
62 }
63 
ReplaceSizePlaceholder(size_t index,size_t size)64 bool JpegSegmentBuilder::ReplaceSizePlaceholder(size_t index, size_t size) {
65   if (index >= byte_data_.size() || size < 2 || size > 0xFFFF) {
66     return false;
67   }
68   const ByteData& byte_datum = byte_data_[index];
69   if (byte_datum.GetType() != ByteData::kHex) {
70     return false;
71   }
72   string value = byte_datum.GetValue();
73   if (value.length() < 4) {
74     return false;
75   }
76   Byte flag, type;
77   if (!ByteData::Hex2Byte(value[0], value[1], &flag) ||
78       !ByteData::Hex2Byte(value[2], value[3], &type)) {
79     return false;
80   }
81   JpegMarker marker(type);
82   if (flag != JpegMarker::kStart || !marker.IsValid() ||
83       !marker.HasVariablePayloadSize()) {
84     return false;
85   }
86   value.replace(2, 2, ByteData::Byte2Hex((size >> 8) & 0xFF));
87   value.replace(4, 2, ByteData::Byte2Hex(size & 0xFF));
88   byte_data_[index] = ByteData(ByteData::kHex, value);
89   return true;
90 }
91 
AddExtendedXmpHeader(const std::string & xmp_guid)92 void JpegSegmentBuilder::AddExtendedXmpHeader(const std::string& xmp_guid) {
93   string guid_value(xmp_guid);
94   guid_value.resize(kXmpGuidSize, '0');
95   byte_data_.emplace_back(ByteData::kAscii0, kXmpExtendedId);
96   byte_data_.emplace_back(ByteData::kAscii, guid_value);
97   byte_data_.emplace_back(ByteData::kAscii, string(8, '0'));
98 }
99 
AddXmpMetaPrefix()100 void JpegSegmentBuilder::AddXmpMetaPrefix() {
101   byte_data_.emplace_back(ByteData::kAscii, kXmpMetaPrefix);
102 }
103 
AddXmpMetaSuffix()104 void JpegSegmentBuilder::AddXmpMetaSuffix() {
105   byte_data_.emplace_back(ByteData::kAscii, kXmpMetaSuffix);
106 }
107 
AddRdfPrefix()108 void JpegSegmentBuilder::AddRdfPrefix() {
109   byte_data_.emplace_back(ByteData::kAscii, kRdfPrefix);
110 }
111 
AddRdfSuffix()112 void JpegSegmentBuilder::AddRdfSuffix() {
113   byte_data_.emplace_back(ByteData::kAscii, kRdfSuffix);
114 }
115 
AddRdfDescriptionPrefix()116 void JpegSegmentBuilder::AddRdfDescriptionPrefix() {
117   byte_data_.emplace_back(ByteData::kAscii, kRdfDescriptionPrefix);
118 }
119 
AddRdfDescriptionSuffix()120 void JpegSegmentBuilder::AddRdfDescriptionSuffix() {
121   byte_data_.emplace_back(ByteData::kAscii, kRdfDescriptionSuffix);
122 }
123 
AddXmpPropertyPrefix(const std::string & property_name)124 void JpegSegmentBuilder::AddXmpPropertyPrefix(
125     const std::string& property_name) {
126   string property_name_equals_quote = property_name + "=\"";
127   byte_data_.emplace_back(ByteData::kAscii, property_name_equals_quote);
128 }
129 
AddXmpPropertySuffix()130 void JpegSegmentBuilder::AddXmpPropertySuffix() {
131   byte_data_.emplace_back(ByteData::kAscii, "\"");
132 }
133 
AddXmpPropertyNameAndValue(const std::string & property_name,const std::string & property_value)134 void JpegSegmentBuilder::AddXmpPropertyNameAndValue(
135     const std::string& property_name, const std::string& property_value) {
136   AddXmpPropertyPrefix(property_name);
137   byte_data_.emplace_back(ByteData::kAscii, property_value);
138   AddXmpPropertySuffix();
139 }
140 
AddApp1XmpMarkerAndXmpExtendedHeader(const std::string & xmp_guid)141 void JpegSegmentBuilder::AddApp1XmpMarkerAndXmpExtendedHeader(
142     const std::string& xmp_guid) {
143   AddMarkerAndSizePlaceholder(JpegMarker::kAPP1);
144   AddExtendedXmpHeader(xmp_guid);
145 }
146 
AddXmpAndRdfPrefixes()147 void JpegSegmentBuilder::AddXmpAndRdfPrefixes() {
148   AddXmpMetaPrefix();
149   AddRdfPrefix();
150   AddRdfDescriptionPrefix();
151 }
152 
AddXmpAndRdfSuffixes()153 void JpegSegmentBuilder::AddXmpAndRdfSuffixes() {
154   AddRdfDescriptionSuffix();
155   AddRdfSuffix();
156   AddXmpMetaSuffix();
157 }
158 
159 }  // namespace image_io
160 }  // namespace photos_editing_formats
161