blob: 71e5f6f21ae23cb8952c3707901c7e5f2742e1c2 [file] [log] [blame]
Dichen Zhang85b37562022-10-11 11:08:28 -07001/*
2 * Copyright 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Dichen Zhang72fd2b12022-11-01 06:11:50 +000017#include "image_io/xml/xml_writer.h"
18
Dichen Zhang85b37562022-10-11 11:08:28 -070019#include <jpegrecoverymap/recoverymap.h>
Dichen Zhang72fd2b12022-11-01 06:11:50 +000020#include <sstream>
21#include <string>
22
23using namespace std;
Dichen Zhang85b37562022-10-11 11:08:28 -070024
25namespace android::recoverymap {
26
Dichen Zhang72fd2b12022-11-01 06:11:50 +000027/*
28 * Helper function used for generating XMP metadata.
29 *
30 * @param prefix The prefix part of the name.
31 * @param suffix The suffix part of the name.
32 * @return A name of the form "prefix:suffix".
33 */
34string Name(const string &prefix, const string &suffix) {
35 std::stringstream ss;
36 ss << prefix << ":" << suffix;
37 return ss.str();
38}
39
Dichen Zhang6947d532022-10-22 02:16:21 +000040status_t RecoveryMap::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image,
41 jr_uncompressed_ptr uncompressed_yuv_420_image,
Dichen Zhangffa34012022-11-03 23:21:13 +000042 void* dest,
43 int quality,
44 jr_exif_ptr /* exif */,
45 float /* hdr_ratio */) {
Dichen Zhang6947d532022-10-22 02:16:21 +000046 if (uncompressed_p010_image == nullptr
47 || uncompressed_yuv_420_image == nullptr
48 || dest == nullptr) {
Dichen Zhang80b72482022-11-02 01:55:35 +000049 return ERROR_JPEGR_INVALID_NULL_PTR;
Dichen Zhang6947d532022-10-22 02:16:21 +000050 }
51
Dichen Zhangffa34012022-11-03 23:21:13 +000052 if (quality < 0 || quality > 100) {
53 return ERROR_JPEGR_INVALID_INPUT_TYPE;
54 }
55
Dichen Zhang6947d532022-10-22 02:16:21 +000056 // TBD
57 return NO_ERROR;
58}
59
60status_t RecoveryMap::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image,
61 jr_uncompressed_ptr uncompressed_yuv_420_image,
62 void* compressed_jpeg_image,
Dichen Zhangffa34012022-11-03 23:21:13 +000063 void* dest,
64 float /* hdr_ratio */) {
Dichen Zhang6947d532022-10-22 02:16:21 +000065
66 if (uncompressed_p010_image == nullptr
67 || uncompressed_yuv_420_image == nullptr
68 || compressed_jpeg_image == nullptr
69 || dest == nullptr) {
Dichen Zhang80b72482022-11-02 01:55:35 +000070 return ERROR_JPEGR_INVALID_NULL_PTR;
Dichen Zhang6947d532022-10-22 02:16:21 +000071 }
72
73 // TBD
74 return NO_ERROR;
75}
76
77status_t RecoveryMap::encodeJPEGR(jr_uncompressed_ptr uncompressed_p010_image,
78 void* compressed_jpeg_image,
Dichen Zhangffa34012022-11-03 23:21:13 +000079 void* dest,
80 float /* hdr_ratio */) {
Dichen Zhang6947d532022-10-22 02:16:21 +000081 if (uncompressed_p010_image == nullptr
82 || compressed_jpeg_image == nullptr
83 || dest == nullptr) {
Dichen Zhang80b72482022-11-02 01:55:35 +000084 return ERROR_JPEGR_INVALID_NULL_PTR;
Dichen Zhang6947d532022-10-22 02:16:21 +000085 }
86
87 // TBD
88 return NO_ERROR;
89}
90
Dichen Zhangffa34012022-11-03 23:21:13 +000091status_t RecoveryMap::decodeJPEGR(void* compressed_jpegr_image,
92 jr_uncompressed_ptr dest,
93 jr_exif_ptr /* exif */,
94 bool /* request_sdr */) {
Dichen Zhang6947d532022-10-22 02:16:21 +000095 if (compressed_jpegr_image == nullptr || dest == nullptr) {
Dichen Zhang80b72482022-11-02 01:55:35 +000096 return ERROR_JPEGR_INVALID_NULL_PTR;
Dichen Zhang6947d532022-10-22 02:16:21 +000097 }
98
99 // TBD
100 return NO_ERROR;
101}
102
103status_t RecoveryMap::decodeRecoveryMap(jr_compressed_ptr compressed_recovery_map,
104 jr_uncompressed_ptr dest) {
Dichen Zhang596a7562022-10-12 14:57:05 -0700105 if (compressed_recovery_map == nullptr || dest == nullptr) {
Dichen Zhang80b72482022-11-02 01:55:35 +0000106 return ERROR_JPEGR_INVALID_NULL_PTR;
Dichen Zhang596a7562022-10-12 14:57:05 -0700107 }
108
109 // TBD
Dichen Zhang6947d532022-10-22 02:16:21 +0000110 return NO_ERROR;
Dichen Zhang596a7562022-10-12 14:57:05 -0700111}
112
Dichen Zhang6947d532022-10-22 02:16:21 +0000113status_t RecoveryMap::encodeRecoveryMap(jr_uncompressed_ptr uncompressed_recovery_map,
114 jr_compressed_ptr dest) {
Dichen Zhang596a7562022-10-12 14:57:05 -0700115 if (uncompressed_recovery_map == nullptr || dest == nullptr) {
Dichen Zhang80b72482022-11-02 01:55:35 +0000116 return ERROR_JPEGR_INVALID_NULL_PTR;
Dichen Zhang596a7562022-10-12 14:57:05 -0700117 }
118
119 // TBD
Dichen Zhang6947d532022-10-22 02:16:21 +0000120 return NO_ERROR;
Dichen Zhang596a7562022-10-12 14:57:05 -0700121}
122
Dichen Zhang6947d532022-10-22 02:16:21 +0000123status_t RecoveryMap::generateRecoveryMap(jr_uncompressed_ptr uncompressed_yuv_420_image,
124 jr_uncompressed_ptr uncompressed_p010_image,
125 jr_uncompressed_ptr dest) {
Dichen Zhang596a7562022-10-12 14:57:05 -0700126 if (uncompressed_yuv_420_image == nullptr
127 || uncompressed_p010_image == nullptr
128 || dest == nullptr) {
Dichen Zhang80b72482022-11-02 01:55:35 +0000129 return ERROR_JPEGR_INVALID_NULL_PTR;
Dichen Zhang596a7562022-10-12 14:57:05 -0700130 }
131
132 // TBD
Dichen Zhang6947d532022-10-22 02:16:21 +0000133 return NO_ERROR;
Dichen Zhang596a7562022-10-12 14:57:05 -0700134}
135
Dichen Zhang6947d532022-10-22 02:16:21 +0000136status_t RecoveryMap::applyRecoveryMap(jr_uncompressed_ptr uncompressed_yuv_420_image,
137 jr_uncompressed_ptr uncompressed_recovery_map,
138 jr_uncompressed_ptr dest) {
Dichen Zhang596a7562022-10-12 14:57:05 -0700139 if (uncompressed_yuv_420_image == nullptr
140 || uncompressed_recovery_map == nullptr
141 || dest == nullptr) {
Dichen Zhang80b72482022-11-02 01:55:35 +0000142 return ERROR_JPEGR_INVALID_NULL_PTR;
Dichen Zhang596a7562022-10-12 14:57:05 -0700143 }
144
145 // TBD
Dichen Zhang6947d532022-10-22 02:16:21 +0000146 return NO_ERROR;
Dichen Zhang596a7562022-10-12 14:57:05 -0700147}
148
Dichen Zhang6947d532022-10-22 02:16:21 +0000149status_t RecoveryMap::extractRecoveryMap(void* compressed_jpegr_image, jr_compressed_ptr dest) {
150 if (compressed_jpegr_image == nullptr || dest == nullptr) {
Dichen Zhang80b72482022-11-02 01:55:35 +0000151 return ERROR_JPEGR_INVALID_NULL_PTR;
Dichen Zhang85b37562022-10-11 11:08:28 -0700152 }
153
154 // TBD
Dichen Zhang6947d532022-10-22 02:16:21 +0000155 return NO_ERROR;
Dichen Zhang85b37562022-10-11 11:08:28 -0700156}
157
Dichen Zhang6947d532022-10-22 02:16:21 +0000158status_t RecoveryMap::appendRecoveryMap(void* compressed_jpeg_image,
159 jr_compressed_ptr compressed_recovery_map,
160 void* dest) {
161 if (compressed_jpeg_image == nullptr
162 || compressed_recovery_map == nullptr
163 || dest == nullptr) {
Dichen Zhang80b72482022-11-02 01:55:35 +0000164 return ERROR_JPEGR_INVALID_NULL_PTR;
Dichen Zhang85b37562022-10-11 11:08:28 -0700165 }
166
167 // TBD
Dichen Zhang6947d532022-10-22 02:16:21 +0000168 return NO_ERROR;
Dichen Zhang85b37562022-10-11 11:08:28 -0700169}
170
Dichen Zhang72fd2b12022-11-01 06:11:50 +0000171string RecoveryMap::generateXmp(int secondary_image_length, float hdr_ratio) {
172 const string kContainerPrefix = "GContainer";
173 const string kContainerUri = "http://ns.google.com/photos/1.0/container/";
174 const string kItemPrefix = "Item";
175 const string kRecoveryMap = "RecoveryMap";
176 const string kDirectory = "Directory";
177 const string kImageJpeg = "image/jpeg";
178 const string kItem = "Item";
179 const string kLength = "Length";
180 const string kMime = "Mime";
181 const string kPrimary = "Primary";
182 const string kSemantic = "Semantic";
183 const string kVersion = "Version";
184 const int kVersionValue = 1;
185
186 const string kConDir = Name(kContainerPrefix, kDirectory);
187 const string kContainerItem = Name(kContainerPrefix, kItem);
188 const string kItemLength = Name(kItemPrefix, kLength);
189 const string kItemMime = Name(kItemPrefix, kMime);
190 const string kItemSemantic = Name(kItemPrefix, kSemantic);
191
192 const vector<string> kConDirSeq({kConDir, string("rdf:Seq")});
193 const vector<string> kLiItem({string("rdf:li"), kContainerItem});
194
195 std::stringstream ss;
196 photos_editing_formats::image_io::XmlWriter writer(ss);
197 writer.StartWritingElement("x:xmpmeta");
198 writer.WriteXmlns("x", "adobe:ns:meta/");
199 writer.WriteAttributeNameAndValue("x:xmptk", "Adobe XMP Core 5.1.2");
200 writer.StartWritingElement("rdf:RDF");
201 writer.WriteXmlns("rdf", "http://www.w3.org/1999/02/22-rdf-syntax-ns#");
202 writer.StartWritingElement("rdf:Description");
203 writer.WriteXmlns(kContainerPrefix, kContainerUri);
204 writer.WriteElementAndContent(Name(kContainerPrefix, kVersion), kVersionValue);
205 writer.WriteElementAndContent(Name(kContainerPrefix, "HdrRatio"), hdr_ratio);
206 writer.StartWritingElements(kConDirSeq);
207 size_t item_depth = writer.StartWritingElements(kLiItem);
208 writer.WriteAttributeNameAndValue(kItemSemantic, kPrimary);
209 writer.WriteAttributeNameAndValue(kItemMime, kImageJpeg);
210 writer.FinishWritingElementsToDepth(item_depth);
211 writer.StartWritingElements(kLiItem);
212 writer.WriteAttributeNameAndValue(kItemSemantic, kRecoveryMap);
213 writer.WriteAttributeNameAndValue(kItemMime, kImageJpeg);
214 writer.WriteAttributeNameAndValue(kItemLength, secondary_image_length);
215 writer.FinishWriting();
216
217 return ss.str();
218}
219
Dichen Zhang85b37562022-10-11 11:08:28 -0700220} // namespace android::recoverymap