1 /*
2 * Copyright (C) 2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "hdr_helper.h"
17
18 #include <dlfcn.h>
19 #include <securec.h>
20
21 #include "hilog/log.h"
22 #include "log_tags.h"
23 #include "image_log.h"
24 #include "jpeg_mpf_parser.h"
25 #include "image_utils.h"
26 #include "media_errors.h"
27 #include "src/codec/SkJpegCodec.h"
28 #include "src/codec/SkJpegDecoderMgr.h"
29 #ifdef HEIF_HW_DECODE_ENABLE
30 #include "heif_impl/HeifDecoder.h"
31 #endif
32 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
33 #include "v1_0/hdr_static_metadata.h"
34 #endif
35
36 #undef LOG_DOMAIN
37 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_PLUGIN
38
39 #undef LOG_TAG
40 #define LOG_TAG "HdrHelper"
41
42 namespace OHOS {
43 namespace ImagePlugin {
44 using namespace std;
45 using namespace Media;
46 #if !defined(IOS_PLATFORM) && !defined(ANDROID_PLATFORM)
47 using namespace HDI::Display::Graphic::Common::V1_0;
48 #endif
49 constexpr uint8_t JPEG_MARKER_PREFIX = 0xFF;
50 constexpr uint8_t JPEG_MARKER_APP0 = 0xE0;
51
52 constexpr uint8_t JPEG_MARKER_APP2 = 0xE2;
53 constexpr uint8_t JPEG_MARKER_APP5 = 0xE5;
54 constexpr uint8_t JPEG_MARKER_APP8 = 0xE8;
55 constexpr uint8_t JPEG_MARKER_APP11 = 0xEB;
56 constexpr uint8_t JPEG_SOI = 0xD8;
57 constexpr uint32_t MOVE_ONE_BYTE = 8;
58 constexpr uint32_t VIVID_BASE_IMAGE_MARKER_SIZE = 22;
59 constexpr int JPEG_MARKER_LENGTH_SIZE = 2;
60 constexpr int JPEG_MARKER_TAG_SIZE = 2;
61 constexpr int MPF_TAG_SIZE = 4;
62 constexpr uint32_t UINT8_BYTE_COUNT = 1;
63 constexpr uint32_t UINT16_BYTE_COUNT = 2;
64 constexpr uint32_t UINT32_BYTE_COUNT = 4;
65 constexpr uint8_t JPEG_IMAGE_NUM = 2;
66 constexpr uint8_t VIVID_FILE_TYPE_BASE = 1;
67 constexpr uint8_t VIVID_FILE_TYPE_GAINMAP = 2;
68 constexpr uint8_t EMPTY_SIZE = 0;
69 constexpr uint8_t VIVID_STATIC_METADATA_SIZE_IN_IMAGE = 28;
70 constexpr uint8_t ITUT35_TAG_SIZE = 6;
71 constexpr uint8_t INDEX_ZERO = 0;
72 constexpr uint8_t INDEX_ONE = 1;
73 constexpr uint8_t INDEX_TWO = 2;
74 constexpr uint8_t INDEX_THREE = 3;
75 constexpr uint8_t COLOR_INFO_BYTES = 3;
76 constexpr uint8_t ONE_COMPONENT = 1;
77 constexpr uint8_t THREE_COMPONENTS = 3;
78 constexpr uint8_t VIVID_PRE_INFO_SIZE = 10;
79 constexpr uint8_t VIVID_METADATA_PRE_INFO_SIZE = 10;
80 constexpr uint32_t HDR_MULTI_PICTURE_APP_LENGTH = 90;
81 constexpr uint32_t EXTEND_INFO_MAIN_SIZE = 60;
82 constexpr uint32_t ISO_GAINMAP_METADATA_PAYLOAD_MIN_SIZE = 38;
83 constexpr uint32_t DENOMINATOR = 1000000;
84
85 const float SM_COLOR_SCALE = 0.00002f;
86 const float SM_LUM_SCALE = 0.0001f;
87
88 static constexpr uint8_t ITUT35_TAG[ITUT35_TAG_SIZE] = {
89 'I', 'T', 'U', 'T', '3', '5',
90 };
91
92 constexpr uint8_t ISO_GAINMAP_TAG_SIZE = 28;
93 constexpr uint8_t ISO_GAINMAP_TAG[ISO_GAINMAP_TAG_SIZE] = {
94 'u', 'r', 'n', ':', 'i', 's', 'o', ':', 's', 't', 'd', ':', 'i', 's', 'o', ':', 't', 's', ':', '2', '1', '4', '9',
95 '6', ':', '-', '1', '\0'
96 };
97 constexpr uint8_t HDR_MEDIA_TYPE_TAG_SIZE = 45;
98 constexpr uint8_t HDR_MEDIA_TYPE_TAG[HDR_MEDIA_TYPE_TAG_SIZE] = {
99 'u', 'r', 'n', ':', 'h', 'a', 'r', 'm', 'o', 'n', 'y', 'o', 's', ':', 'm', 'u', 'l', 't', 'i', 'm', 'e',
100 'd', 'i', 'a', ':', 'i', 'm', 'a', 'g', 'e', ':', 'v', 'i', 'd', 'e', 'o', 'c', 'o', 'v', 'e', 'r', ':',
101 'v', '1', '\0'
102 };
103
104 #ifdef HEIF_HW_DECODE_ENABLE
105 static const map<HeifImageHdrType, ImageHdrType> HEIF_HDR_TYPE_MAP = {
106 { HeifImageHdrType::UNKNOWN, ImageHdrType::UNKNOWN},
107 { HeifImageHdrType::VIVID_DUAL, ImageHdrType::HDR_VIVID_DUAL},
108 { HeifImageHdrType::ISO_DUAL, ImageHdrType::HDR_ISO_DUAL},
109 { HeifImageHdrType::VIVID_SINGLE, ImageHdrType::HDR_VIVID_SINGLE},
110 { HeifImageHdrType::ISO_SINGLE, ImageHdrType::HDR_ISO_SINGLE},
111 };
112 #endif
113
114 typedef bool (*GetCuvaGainMapOffsetT)(jpeg_marker_struct* marker, uint32_t appSize, uint32_t& offset);
115 typedef bool (*GetCuvaGainMapMetadataT)(jpeg_marker_struct* marker, std::vector<uint8_t>& metadata);
116
117 struct ColorInfo {
118 uint8_t primary;
119 uint8_t transFunc;
120 uint8_t model;
121 };
122
123 struct ExtendInfoMain {
124 float gainMapMax[3];
125 float gainMapMin[3];
126 float gamma[3];
127 float baseSdrImageOffset[3];
128 float altHdrImageOffset[3];
129 };
130
131 struct TransformInfo {
132 uint8_t mappingFlag;
133 std::vector<uint8_t> mapping;
134 };
135
136 struct ExtendInfoExtention {
137 ColorInfo baseColor;
138 ColorInfo enhanceDataColor;
139 ColorInfo combineColor;
140 ColorInfo enhanceColor;
141 TransformInfo baseMapping;
142 TransformInfo combineMapping;
143 };
144
GetVividJpegGainMapOffset(const vector<jpeg_marker_struct * > & markerList,vector<uint32_t> preOffsets,uint32_t & offset)145 static bool GetVividJpegGainMapOffset(const vector<jpeg_marker_struct*>& markerList, vector<uint32_t> preOffsets,
146 uint32_t& offset)
147 {
148 if (markerList.size() == EMPTY_SIZE) {
149 return false;
150 }
151 for (uint32_t i = 0; i < markerList.size(); i++) {
152 jpeg_marker_struct* marker = markerList[i];
153 uint32_t size = marker->data_length;
154 if (JPEG_MARKER_APP8 != marker->marker || marker->data_length < VIVID_BASE_IMAGE_MARKER_SIZE) {
155 continue;
156 }
157 uint8_t* data = marker->data;
158 uint32_t dataOffset = 0;
159 if (memcmp(marker->data, ITUT35_TAG, sizeof(ITUT35_TAG)) != EOK) {
160 continue;
161 }
162 dataOffset += ITUT35_TAG_SIZE;
163 uint8_t itut35CountryCode = data[dataOffset++];
164 uint16_t terminalProvideCode = ImageUtils::BytesToUint16(data, dataOffset, size);
165 uint16_t terminalProvideOrientedCode = ImageUtils::BytesToUint16(data, dataOffset, size);
166 IMAGE_LOGD("vivid base info countryCode=%{public}d,terminalCode=%{public}d,orientedcode=%{public}d",
167 itut35CountryCode, terminalProvideCode, terminalProvideOrientedCode);
168 uint8_t extendedFrameNumber = data[dataOffset++];
169 if (extendedFrameNumber < JPEG_IMAGE_NUM) {
170 continue;
171 }
172 uint8_t fileType = data[dataOffset++];
173 uint8_t metaType = data[dataOffset++];
174 uint8_t enhanceType = data[dataOffset++];
175 uint8_t hdrType = data[dataOffset++];
176 IMAGE_LOGD("vivid base info metaType=%{public}d, enhanceType=%{public}d, hdrType=%{public}d",
177 metaType, enhanceType, hdrType);
178 if (fileType != VIVID_FILE_TYPE_BASE) {
179 continue;
180 }
181 uint32_t originOffset = ImageUtils::BytesToUint32(data, dataOffset, size);
182 offset = originOffset + preOffsets[i];
183 uint32_t relativeOffset = ImageUtils::BytesToUint32(data, dataOffset, size); // offset minus all app size
184 IMAGE_LOGD("vivid base info originOffset=%{public}d, relativeOffset=%{public}d, offset=%{public}d",
185 originOffset, relativeOffset, offset);
186 return true;
187 }
188 return false;
189 }
190
GetCuvaJpegGainMapOffset(vector<jpeg_marker_struct * > & markerList,uint32_t appSize,uint32_t & offset)191 static bool GetCuvaJpegGainMapOffset(vector<jpeg_marker_struct*>& markerList,
192 uint32_t appSize, uint32_t& offset) __attribute__((no_sanitize("cfi")))
193 {
194 if (markerList.size() == EMPTY_SIZE) {
195 return false;
196 }
197 auto handle = dlopen("libimage_cuva_parser.z.so", RTLD_LAZY);
198 if (!handle) {
199 dlclose(handle);
200 return false;
201 }
202 GetCuvaGainMapOffsetT check = reinterpret_cast<GetCuvaGainMapOffsetT>(dlsym(handle, "GetCuvaGainMapOffset"));
203 if (!check) {
204 dlclose(handle);
205 return false;
206 }
207 bool result = false;
208 for (auto marker : markerList) {
209 if (marker == nullptr || marker->data == nullptr || JPEG_MARKER_APP5 != marker->marker) {
210 continue;
211 }
212 result = check(marker, appSize, offset);
213 if (result) {
214 break;
215 }
216 }
217 dlclose(handle);
218 return result;
219 }
220
ParseMpfOffset(jpeg_marker_struct * marker,uint32_t preOffset)221 static vector<uint32_t> ParseMpfOffset(jpeg_marker_struct* marker, uint32_t preOffset)
222 {
223 if (JPEG_MARKER_APP2 != marker->marker) {
224 return {};
225 }
226 auto jpegMpf = std::make_unique<JpegMpfParser>();
227 if (!jpegMpf->Parsing(marker->data, marker->data_length)) {
228 return {};
229 }
230 uint32_t imageNum = jpegMpf->images_.size();
231 if (imageNum < JPEG_IMAGE_NUM) {
232 return {};
233 }
234 vector<uint32_t> offsetArray(imageNum);
235 // gain map offset need add Mpf marker offset;
236 uint32_t markerHeaderOffset = preOffset + JPEG_MARKER_TAG_SIZE + JPEG_MARKER_LENGTH_SIZE + MPF_TAG_SIZE;
237 for (uint32_t i = INDEX_ONE; i < imageNum; i++) {
238 offsetArray[i] = jpegMpf->images_[i].offset + markerHeaderOffset;
239 }
240 return offsetArray;
241 }
242
ParseBaseISOTag(jpeg_marker_struct * marker)243 static bool ParseBaseISOTag(jpeg_marker_struct* marker)
244 {
245 if (JPEG_MARKER_APP2 != marker->marker) {
246 return false;
247 }
248 if (marker->data_length <= ISO_GAINMAP_TAG_SIZE) {
249 return false;
250 }
251 if (memcmp(marker->data, ISO_GAINMAP_TAG, ISO_GAINMAP_TAG_SIZE) == EOK) {
252 return true;
253 }
254 return false;
255 }
256
GetISOJpegGainMapOffset(vector<jpeg_marker_struct * > & markerList,vector<uint32_t> preOffsets,uint32_t & offset)257 static bool GetISOJpegGainMapOffset(vector<jpeg_marker_struct*>& markerList,
258 vector<uint32_t> preOffsets, uint32_t& offset)
259 {
260 if (markerList.size() == EMPTY_SIZE) {
261 return false;
262 }
263 vector<uint32_t> offsetArray;
264 bool isoTag = false;
265 for (uint32_t i = 0; i < markerList.size(); i++) {
266 jpeg_marker_struct* marker = markerList[i];
267 if (JPEG_MARKER_APP2 != marker->marker) {
268 continue;
269 }
270 uint32_t markerOffset = preOffsets[i];
271 if (offsetArray.size() == EMPTY_SIZE) {
272 offsetArray = ParseMpfOffset(marker, markerOffset);
273 }
274 if (!isoTag) {
275 isoTag = ParseBaseISOTag(marker);
276 }
277 }
278 if (isoTag && offsetArray.size() == INDEX_TWO) {
279 offset = offsetArray[INDEX_ONE];
280 return true;
281 }
282 return false;
283 }
284
285
CheckJpegGainMapHdrType(SkJpegCodec * jpegCodec,uint32_t & offset)286 static ImageHdrType CheckJpegGainMapHdrType(SkJpegCodec* jpegCodec,
287 uint32_t& offset) __attribute__((no_sanitize("cfi")))
288 {
289 uint32_t allAppSize = JPEG_MARKER_TAG_SIZE;
290 vector<jpeg_marker_struct*> vividMarkerList;
291 vector<jpeg_marker_struct*> cuvaMarkerList;
292 vector<jpeg_marker_struct*> isoMarkerList;
293 vector<uint32_t> isoPreMarkerOffset;
294 vector<uint32_t> vividPreMarkerOffset;
295 for (jpeg_marker_struct* marker = jpegCodec->decoderMgr()->dinfo()->marker_list; marker; marker = marker->next) {
296 if (JPEG_MARKER_APP8 == marker->marker) {
297 vividMarkerList.push_back(marker);
298 vividPreMarkerOffset.push_back(allAppSize);
299 }
300 if (JPEG_MARKER_APP5 == marker->marker) {
301 cuvaMarkerList.push_back(marker);
302 }
303 if (JPEG_MARKER_APP2 == marker->marker) {
304 isoMarkerList.push_back(marker);
305 isoPreMarkerOffset.push_back(allAppSize);
306 }
307 if (JPEG_MARKER_APP0 == (marker->marker & 0xF0)) {
308 allAppSize += marker->data_length + JPEG_MARKER_TAG_SIZE + JPEG_MARKER_LENGTH_SIZE;
309 }
310 }
311 if (GetVividJpegGainMapOffset(vividMarkerList, vividPreMarkerOffset, offset)) {
312 uint32_t tmpOffset = 0;
313 GetISOJpegGainMapOffset(isoMarkerList, isoPreMarkerOffset, offset);
314 if (tmpOffset > 0 && tmpOffset != offset) {
315 IMAGE_LOGD("vivid gainmap offset from mpf, offset:%{public}d-%{public}d", tmpOffset, offset);
316 offset = tmpOffset;
317 }
318 return ImageHdrType::HDR_VIVID_DUAL;
319 }
320 if (GetCuvaJpegGainMapOffset(cuvaMarkerList, allAppSize, offset)) {
321 return ImageHdrType::HDR_CUVA;
322 }
323 if (GetISOJpegGainMapOffset(isoMarkerList, isoPreMarkerOffset, offset)) {
324 return ImageHdrType::HDR_ISO_DUAL;
325 }
326 return ImageHdrType::SDR;
327 }
328
329 #ifdef HEIF_HW_DECODE_ENABLE
CheckHeifHdrType(HeifDecoder * decoder)330 static ImageHdrType CheckHeifHdrType(HeifDecoder* decoder)
331 {
332 if (decoder == nullptr) {
333 return ImageHdrType::UNKNOWN;
334 }
335 HeifImageHdrType heifHdrType = decoder->getHdrType();
336 auto findItem = std::find_if(HEIF_HDR_TYPE_MAP.begin(), HEIF_HDR_TYPE_MAP.end(),
337 [heifHdrType](const map<HeifImageHdrType, ImageHdrType>::value_type item) {
338 return item.first == heifHdrType;
339 });
340 if (findItem == HEIF_HDR_TYPE_MAP.end()) {
341 return ImageHdrType::UNKNOWN;
342 }
343 return findItem->second;
344 }
345 #endif
346
CheckHdrType(SkCodec * codec,uint32_t & offset)347 ImageHdrType HdrHelper::CheckHdrType(SkCodec* codec, uint32_t& offset) __attribute__((no_sanitize("cfi")))
348 {
349 offset = 0;
350 ImageHdrType type = ImageHdrType::SDR;
351 if (codec == nullptr) {
352 return type;
353 }
354 switch (codec->getEncodedFormat()) {
355 case SkEncodedImageFormat::kJPEG: {
356 SkJpegCodec* jpegCodec = static_cast<SkJpegCodec*>(codec);
357 if (jpegCodec == nullptr || jpegCodec->decoderMgr() == nullptr) {
358 break;
359 }
360 type = CheckJpegGainMapHdrType(jpegCodec, offset);
361 break;
362 }
363 case SkEncodedImageFormat::kHEIF: {
364 #ifdef HEIF_HW_DECODE_ENABLE
365 auto decoder = reinterpret_cast<HeifDecoder*>(codec->getHeifContext());
366 if (decoder == nullptr) {
367 break;
368 }
369 type = CheckHeifHdrType(decoder);
370 #endif
371 break;
372 }
373 default:
374 type = ImageHdrType::SDR;
375 break;
376 }
377 return type;
378 }
379
ParseVividJpegStaticMetadata(uint8_t * data,uint32_t & offset,uint32_t size,vector<uint8_t> & staticMetaVec)380 static bool ParseVividJpegStaticMetadata(uint8_t* data, uint32_t& offset, uint32_t size, vector<uint8_t>& staticMetaVec)
381 {
382 #if defined(_WIN32) || defined(_APPLE) || defined(IOS_PLATFORM) || defined(ANDROID_PLATFORM)
383 return false;
384 #else
385 uint16_t staticMetadataSize = ImageUtils::BytesToUint16(data, offset, size);
386 if (staticMetadataSize == EMPTY_SIZE) {
387 staticMetaVec.resize(EMPTY_SIZE);
388 return true;
389 }
390 if (staticMetadataSize > size || staticMetadataSize < VIVID_STATIC_METADATA_SIZE_IN_IMAGE) {
391 return false;
392 }
393
394 HdrStaticMetadata staticMeta{};
395 staticMeta.smpte2086.displayPrimaryRed.x = (float)ImageUtils::BytesToUint16(data, offset, size) * SM_COLOR_SCALE;
396 staticMeta.smpte2086.displayPrimaryRed.y = (float)ImageUtils::BytesToUint16(data, offset, size) * SM_COLOR_SCALE;
397 staticMeta.smpte2086.displayPrimaryGreen.x = (float)ImageUtils::BytesToUint16(data, offset, size) * SM_COLOR_SCALE;
398 staticMeta.smpte2086.displayPrimaryGreen.y = (float)ImageUtils::BytesToUint16(data, offset, size) * SM_COLOR_SCALE;
399 staticMeta.smpte2086.displayPrimaryBlue.x = (float)ImageUtils::BytesToUint16(data, offset, size) * SM_COLOR_SCALE;
400 staticMeta.smpte2086.displayPrimaryBlue.y = (float)ImageUtils::BytesToUint16(data, offset, size) * SM_COLOR_SCALE;
401 staticMeta.smpte2086.whitePoint.x = (float)ImageUtils::BytesToUint16(data, offset, size) * SM_COLOR_SCALE;
402 staticMeta.smpte2086.whitePoint.y = (float)ImageUtils::BytesToUint16(data, offset, size) * SM_COLOR_SCALE;
403 staticMeta.smpte2086.maxLuminance = (float)ImageUtils::BytesToUint32(data, offset, size);
404 staticMeta.smpte2086.minLuminance = (float)ImageUtils::BytesToUint32(data, offset, size) * SM_LUM_SCALE;
405 staticMeta.cta861.maxContentLightLevel = (float)ImageUtils::BytesToUint16(data, offset, size);
406 staticMeta.cta861.maxFrameAverageLightLevel = (float)ImageUtils::BytesToUint16(data, offset, size);
407 uint32_t vecSize = sizeof(HdrStaticMetadata);
408 staticMetaVec.resize(vecSize);
409 if (memcpy_s(staticMetaVec.data(), vecSize, &staticMeta, vecSize) != EOK) {
410 return false;
411 }
412 if (staticMetadataSize > VIVID_STATIC_METADATA_SIZE_IN_IMAGE) {
413 offset += (staticMetadataSize - VIVID_STATIC_METADATA_SIZE_IN_IMAGE);
414 }
415 return true;
416 #endif
417 }
418
ParseExtendInfoMain(uint8_t * data,uint32_t & offset,uint32_t size,bool isThreeCom)419 static ExtendInfoMain ParseExtendInfoMain(uint8_t* data, uint32_t& offset, uint32_t size, bool isThreeCom)
420 {
421 ExtendInfoMain infoMain{};
422 infoMain.gainMapMin[INDEX_ZERO] = ImageUtils::BytesToFloat(data, offset, size);
423 infoMain.gainMapMax[INDEX_ZERO] = ImageUtils::BytesToFloat(data, offset, size);
424 infoMain.gamma[INDEX_ZERO] = ImageUtils::BytesToFloat(data, offset, size);
425 infoMain.baseSdrImageOffset[INDEX_ZERO] = ImageUtils::BytesToFloat(data, offset, size);
426 infoMain.altHdrImageOffset[INDEX_ZERO] = ImageUtils::BytesToFloat(data, offset, size);
427 if (isThreeCom) {
428 infoMain.gainMapMin[INDEX_ONE] = ImageUtils::BytesToFloat(data, offset, size);
429 infoMain.gainMapMax[INDEX_ONE] = ImageUtils::BytesToFloat(data, offset, size);
430 infoMain.gamma[INDEX_ONE] = ImageUtils::BytesToFloat(data, offset, size);
431 infoMain.baseSdrImageOffset[INDEX_ONE] = ImageUtils::BytesToFloat(data, offset, size);
432 infoMain.altHdrImageOffset[INDEX_ONE] = ImageUtils::BytesToFloat(data, offset, size);
433 infoMain.gainMapMin[INDEX_TWO] = ImageUtils::BytesToFloat(data, offset, size);
434 infoMain.gainMapMax[INDEX_TWO] = ImageUtils::BytesToFloat(data, offset, size);
435 infoMain.gamma[INDEX_TWO] = ImageUtils::BytesToFloat(data, offset, size);
436 infoMain.baseSdrImageOffset[INDEX_TWO] = ImageUtils::BytesToFloat(data, offset, size);
437 infoMain.altHdrImageOffset[INDEX_TWO] = ImageUtils::BytesToFloat(data, offset, size);
438 } else {
439 infoMain.gainMapMin[INDEX_ONE] = infoMain.gainMapMin[INDEX_ZERO];
440 infoMain.gainMapMax[INDEX_ONE] = infoMain.gainMapMax[INDEX_ZERO];
441 infoMain.gamma[INDEX_ONE] = infoMain.gamma[INDEX_ZERO];
442 infoMain.baseSdrImageOffset[INDEX_ONE] = infoMain.baseSdrImageOffset[INDEX_ZERO];
443 infoMain.altHdrImageOffset[INDEX_ONE] = infoMain.altHdrImageOffset[INDEX_ZERO];
444 infoMain.gainMapMin[INDEX_TWO] = infoMain.gainMapMin[INDEX_ZERO];
445 infoMain.gainMapMax[INDEX_TWO] = infoMain.gainMapMax[INDEX_ZERO];
446 infoMain.gamma[INDEX_TWO] = infoMain.gamma[INDEX_ZERO];
447 infoMain.baseSdrImageOffset[INDEX_TWO] = infoMain.baseSdrImageOffset[INDEX_ZERO];
448 infoMain.altHdrImageOffset[INDEX_TWO] = infoMain.altHdrImageOffset[INDEX_ZERO];
449 }
450 return infoMain;
451 }
452
ParseColorInfo(const uint8_t * data,uint32_t & offset,uint32_t length,ColorInfo & colorInfo)453 static bool ParseColorInfo(const uint8_t* data, uint32_t& offset, uint32_t length, ColorInfo& colorInfo)
454 {
455 uint8_t size = data[offset++];
456 if (size == EMPTY_SIZE) {
457 return true;
458 }
459 if (size > length - offset || size != COLOR_INFO_BYTES) {
460 return false;
461 }
462 colorInfo.primary = data[offset++];
463 colorInfo.transFunc = data[offset++];
464 colorInfo.model = data[offset++];
465 return true;
466 }
467
ParseTransformInfo(uint8_t * data,uint32_t & offset,uint32_t length,TransformInfo & info)468 static bool ParseTransformInfo(uint8_t* data, uint32_t& offset, uint32_t length, TransformInfo& info)
469 {
470 uint8_t size = ImageUtils::BytesToUint16(data, offset, length);
471 if (size == EMPTY_SIZE) {
472 info.mappingFlag = EMPTY_SIZE;
473 info.mapping.resize(EMPTY_SIZE);
474 return true;
475 }
476 if (size > length - offset || size <= UINT8_BYTE_COUNT) {
477 info.mappingFlag = EMPTY_SIZE;
478 info.mapping.resize(EMPTY_SIZE);
479 return false;
480 }
481 info.mappingFlag = data[offset++];
482 if (info.mappingFlag == INDEX_ZERO) {
483 info.mapping.resize(EMPTY_SIZE);
484 return true;
485 } else if (info.mappingFlag > size - UINT16_BYTE_COUNT) {
486 return false;
487 }
488 info.mapping.resize(info.mappingFlag);
489 if (memcpy_s(info.mapping.data(), info.mappingFlag, data + offset, info.mappingFlag) != EOK) {
490 return false;
491 }
492 offset += info.mappingFlag;
493 return true;
494 }
495
ConvertExtendInfoMain(ExtendInfoMain info,HDRVividExtendMetadata & metadata)496 static void ConvertExtendInfoMain(ExtendInfoMain info, HDRVividExtendMetadata& metadata)
497 {
498 metadata.metaISO.enhanceClippedThreholdMaxGainmap[INDEX_ZERO] = info.gainMapMax[INDEX_ZERO];
499 metadata.metaISO.enhanceClippedThreholdMaxGainmap[INDEX_ONE] = info.gainMapMax[INDEX_ONE];
500 metadata.metaISO.enhanceClippedThreholdMaxGainmap[INDEX_TWO] = info.gainMapMax[INDEX_TWO];
501 metadata.metaISO.enhanceClippedThreholdMinGainmap[INDEX_ZERO] = info.gainMapMin[INDEX_ZERO];
502 metadata.metaISO.enhanceClippedThreholdMinGainmap[INDEX_ONE] = info.gainMapMin[INDEX_ONE];
503 metadata.metaISO.enhanceClippedThreholdMinGainmap[INDEX_TWO] = info.gainMapMin[INDEX_TWO];
504 metadata.metaISO.enhanceMappingGamma[INDEX_ZERO] = info.gamma[INDEX_ZERO];
505 metadata.metaISO.enhanceMappingGamma[INDEX_ONE] = info.gamma[INDEX_ONE];
506 metadata.metaISO.enhanceMappingGamma[INDEX_TWO] = info.gamma[INDEX_TWO];
507 metadata.metaISO.enhanceMappingBaselineOffset[INDEX_ZERO] = info.baseSdrImageOffset[INDEX_ZERO];
508 metadata.metaISO.enhanceMappingBaselineOffset[INDEX_ONE] = info.baseSdrImageOffset[INDEX_ONE];
509 metadata.metaISO.enhanceMappingBaselineOffset[INDEX_TWO] = info.baseSdrImageOffset[INDEX_TWO];
510 metadata.metaISO.enhanceMappingAlternateOffset[INDEX_ZERO] = info.altHdrImageOffset[INDEX_ZERO];
511 metadata.metaISO.enhanceMappingAlternateOffset[INDEX_ONE] = info.altHdrImageOffset[INDEX_ONE];
512 metadata.metaISO.enhanceMappingAlternateOffset[INDEX_TWO] = info.altHdrImageOffset[INDEX_TWO];
513 const float eps = 1e-5;
514 if ((fabs(metadata.metaISO.enhanceClippedThreholdMaxGainmap[INDEX_ZERO] -
515 metadata.metaISO.enhanceClippedThreholdMaxGainmap[INDEX_ONE]) < eps) &&
516 (fabs(metadata.metaISO.enhanceClippedThreholdMaxGainmap[INDEX_ZERO] -
517 metadata.metaISO.enhanceClippedThreholdMaxGainmap[INDEX_TWO]) < eps) &&
518 (fabs(metadata.metaISO.enhanceClippedThreholdMinGainmap[INDEX_ZERO] -
519 metadata.metaISO.enhanceClippedThreholdMinGainmap[INDEX_ONE]) < eps) &&
520 (fabs(metadata.metaISO.enhanceClippedThreholdMinGainmap[INDEX_ZERO] -
521 metadata.metaISO.enhanceClippedThreholdMinGainmap[INDEX_TWO]) < eps)) {
522 metadata.metaISO.gainmapChannelNum = INDEX_ONE;
523 }
524 }
525
ConvertExtendInfoExtention(ExtendInfoExtention ext,HDRVividExtendMetadata & metadata)526 static void ConvertExtendInfoExtention(ExtendInfoExtention ext, HDRVividExtendMetadata& metadata)
527 {
528 metadata.baseColorMeta.baseColorPrimary = ext.baseColor.primary;
529 metadata.baseColorMeta.baseTransFunction = ext.baseColor.transFunc;
530 metadata.baseColorMeta.baseColorModel = ext.baseColor.model;
531 metadata.gainmapColorMeta.enhanceDataColorPrimary = ext.enhanceDataColor.primary;
532 metadata.gainmapColorMeta.enhanceDataTransFunction = ext.enhanceDataColor.transFunc;
533 metadata.gainmapColorMeta.enhanceDataColorModel = ext.enhanceDataColor.model;
534 metadata.gainmapColorMeta.combineColorPrimary = ext.combineColor.primary;
535 metadata.gainmapColorMeta.combineTransFunction = ext.combineColor.transFunc;
536 metadata.gainmapColorMeta.combineColorModel = ext.combineColor.model;
537 metadata.gainmapColorMeta.alternateColorPrimary = ext.enhanceColor.primary;
538 metadata.gainmapColorMeta.alternateTransFunction = ext.enhanceColor.transFunc;
539 metadata.gainmapColorMeta.alternateColorModel = ext.enhanceColor.model;
540 metadata.baseColorMeta.baseMappingFlag = ext.baseMapping.mappingFlag;
541 metadata.baseColorMeta.baseMapping = ext.baseMapping.mapping;
542 metadata.baseColorMeta.baseMappingSize = ext.baseMapping.mapping.size();
543 metadata.gainmapColorMeta.combineMappingFlag = ext.combineMapping.mappingFlag;
544 metadata.gainmapColorMeta.combineMapping = ext.combineMapping.mapping;
545 metadata.gainmapColorMeta.combineMappingSize = ext.combineMapping.mapping.size();
546 metadata.baseColorMeta.baseIccSize = EMPTY_SIZE;
547 metadata.baseColorMeta.baseICC.resize(EMPTY_SIZE);
548 metadata.gainmapColorMeta.enhanceICCSize = EMPTY_SIZE;
549 metadata.gainmapColorMeta.enhanceICC.resize(EMPTY_SIZE);
550 }
551
ParseVividJpegMetadata(uint8_t * data,uint32_t & dataOffset,uint32_t length,HdrMetadata & metadata)552 static bool ParseVividJpegMetadata(uint8_t* data, uint32_t& dataOffset, uint32_t length, HdrMetadata& metadata)
553 {
554 uint16_t metadataSize = ImageUtils::BytesToUint16(data, dataOffset, length);
555 if (metadataSize > length - dataOffset) {
556 return false;
557 }
558 if (!ParseVividJpegStaticMetadata(data, dataOffset, metadataSize, metadata.staticMetadata)) {
559 return false;
560 }
561 uint16_t dynamicMetaSize = ImageUtils::BytesToUint16(data, dataOffset, length);
562 if (dynamicMetaSize > 0) {
563 if (dynamicMetaSize > length - dataOffset) {
564 return false;
565 }
566 metadata.dynamicMetadata.resize(dynamicMetaSize);
567 if (memcpy_s(metadata.dynamicMetadata.data(), dynamicMetaSize, data + dataOffset, dynamicMetaSize) != 0) {
568 IMAGE_LOGD("get vivid dynamic metadata failed");
569 return false;
570 }
571 dataOffset += dynamicMetaSize;
572 }
573 return true;
574 }
575
ParseVividJpegExtendInfo(uint8_t * data,uint32_t length,HDRVividExtendMetadata & metadata)576 static bool ParseVividJpegExtendInfo(uint8_t* data, uint32_t length, HDRVividExtendMetadata& metadata)
577 {
578 uint32_t dataOffset = 0;
579 uint16_t metadataSize = ImageUtils::BytesToUint16(data, dataOffset, length);
580 if (metadataSize > length - UINT16_BYTE_COUNT) {
581 return false;
582 }
583 uint8_t components = data[dataOffset++];
584 if (components != THREE_COMPONENTS && components != ONE_COMPONENT) {
585 return false;
586 }
587 ExtendInfoMain extendInfoMain = ParseExtendInfoMain(data, dataOffset, length, components == THREE_COMPONENTS);
588 ExtendInfoExtention extendInfoExtention;
589 if (!ParseColorInfo(data, dataOffset, length, extendInfoExtention.baseColor)) {
590 return false;
591 }
592 if (!ParseColorInfo(data, dataOffset, length, extendInfoExtention.enhanceDataColor)) {
593 return false;
594 }
595 if (!ParseColorInfo(data, dataOffset, length, extendInfoExtention.enhanceColor)) {
596 return false;
597 }
598 if (!ParseColorInfo(data, dataOffset, length, extendInfoExtention.combineColor)) {
599 return false;
600 }
601 if (!ParseTransformInfo(data, dataOffset, length, extendInfoExtention.baseMapping)) {
602 return false;
603 }
604 if (!ParseTransformInfo(data, dataOffset, length, extendInfoExtention.combineMapping)) {
605 return false;
606 }
607 ConvertExtendInfoMain(extendInfoMain, metadata);
608 ConvertExtendInfoExtention(extendInfoExtention, metadata);
609 return true;
610 }
611
ParseVividMetadata(uint8_t * data,uint32_t length,HdrMetadata & metadata)612 static bool ParseVividMetadata(uint8_t* data, uint32_t length, HdrMetadata& metadata)
613 {
614 uint32_t dataOffset = 0;
615 uint8_t itut35CountryCode = data[dataOffset++];
616 uint16_t terminalProvideCode = ImageUtils::BytesToUint16(data, dataOffset, length);
617 uint16_t terminalProvideOrientedCode = ImageUtils::BytesToUint16(data, dataOffset, length);
618 IMAGE_LOGD("vivid metadata countryCode=%{public}d,terminalCode=%{public}d,orientedcode=%{public}d",
619 itut35CountryCode, terminalProvideCode, terminalProvideOrientedCode);
620 uint8_t extendedFrameNumber = data[dataOffset++];
621 if (extendedFrameNumber < JPEG_IMAGE_NUM) {
622 return false;
623 }
624 uint8_t fileType = data[dataOffset++];
625 uint8_t metaType = data[dataOffset++];
626 uint8_t enhanceType = data[dataOffset++];
627 uint8_t hdrType = data[dataOffset++];
628 IMAGE_LOGD("vivid metadata info hdrType=%{public}d, enhanceType=%{public}d", hdrType, enhanceType);
629 if (fileType != VIVID_FILE_TYPE_GAINMAP) {
630 return false;
631 }
632 bool getMetadata = false;
633 if (metaType > 0 && length > dataOffset + UINT16_BYTE_COUNT) {
634 getMetadata = ParseVividJpegMetadata(data, dataOffset, length, metadata);
635 }
636 const uint8_t hasEnhanceInfo = 1;
637 if (enhanceType == hasEnhanceInfo && length > dataOffset + UINT16_BYTE_COUNT) {
638 metadata.extendMetaFlag =
639 ParseVividJpegExtendInfo(data + dataOffset, length - dataOffset, metadata.extendMeta);
640 IMAGE_LOGD("vivid get extend info result = %{public}d", metadata.extendMetaFlag);
641 } else {
642 metadata.extendMetaFlag = false;
643 }
644 return getMetadata;
645 }
646
GetVividJpegMetadata(jpeg_marker_struct * markerList,HdrMetadata & metadata)647 static bool GetVividJpegMetadata(jpeg_marker_struct* markerList, HdrMetadata& metadata)
648 {
649 for (jpeg_marker_struct* marker = markerList; marker; marker = marker->next) {
650 if (JPEG_MARKER_APP8 != marker->marker) {
651 continue;
652 }
653 if (memcmp(marker->data, ITUT35_TAG, ITUT35_TAG_SIZE) != 0) {
654 continue;
655 }
656 uint8_t* data = marker->data + ITUT35_TAG_SIZE;
657 uint32_t length = marker->data_length - ITUT35_TAG_SIZE;
658 return ParseVividMetadata(data, length, metadata);
659 }
660 return false;
661 }
662
ParseISOExtendInfoMain(uint8_t * data,uint32_t & offset,uint32_t length,ExtendInfoMain & info,uint8_t index)663 static void ParseISOExtendInfoMain(uint8_t* data, uint32_t& offset, uint32_t length,
664 ExtendInfoMain& info, uint8_t index)
665 {
666 if (index > INDEX_TWO) {
667 return;
668 }
669 int32_t minGainmapNumerator = ImageUtils::BytesToInt32(data, offset, length);
670 uint32_t minGainmapDenominator = ImageUtils::BytesToUint32(data, offset, length);
671 int32_t maxGainmapNumerator = ImageUtils::BytesToInt32(data, offset, length);
672 uint32_t maxGainmapDenominator = ImageUtils::BytesToUint32(data, offset, length);
673 uint32_t gammaNumerator = ImageUtils::BytesToUint32(data, offset, length);
674 uint32_t gammaDenominator = ImageUtils::BytesToUint32(data, offset, length);
675 int32_t baseImageOffsetNumerator = ImageUtils::BytesToInt32(data, offset, length);
676 uint32_t baseImageOffsetDenominator = ImageUtils::BytesToUint32(data, offset, length);
677 int32_t altImageOffsetNumerator = ImageUtils::BytesToInt32(data, offset, length);
678 uint32_t altImageOffsetDenominator = ImageUtils::BytesToUint32(data, offset, length);
679 if (minGainmapDenominator == EMPTY_SIZE) {
680 info.gainMapMin[index] = EMPTY_SIZE;
681 } else {
682 info.gainMapMin[index] = (float)minGainmapNumerator / (float)minGainmapDenominator;
683 }
684
685 if (maxGainmapDenominator == EMPTY_SIZE) {
686 info.gainMapMax[index] = EMPTY_SIZE;
687 } else {
688 info.gainMapMax[index] = (float)maxGainmapNumerator / (float)maxGainmapDenominator;
689 }
690
691 if (gammaDenominator == EMPTY_SIZE) {
692 info.gamma[index] = EMPTY_SIZE;
693 } else {
694 info.gamma[index] = (float)gammaNumerator / (float)gammaDenominator;
695 }
696
697 if (baseImageOffsetDenominator == EMPTY_SIZE) {
698 info.baseSdrImageOffset[index] = EMPTY_SIZE;
699 } else {
700 info.baseSdrImageOffset[index] = (float)baseImageOffsetNumerator / (float)baseImageOffsetDenominator;
701 }
702
703 if (altImageOffsetDenominator == EMPTY_SIZE) {
704 info.altHdrImageOffset[index] = EMPTY_SIZE;
705 } else {
706 info.altHdrImageOffset[index] = (float)altImageOffsetNumerator / (float)altImageOffsetDenominator;
707 }
708 }
709
ParseISOExtendInfoThreeCom(uint8_t * data,uint32_t & offset,uint32_t lenght,uint8_t channelNum,ExtendInfoMain & info)710 static void ParseISOExtendInfoThreeCom(uint8_t* data, uint32_t& offset, uint32_t lenght,
711 uint8_t channelNum, ExtendInfoMain& info)
712 {
713 ParseISOExtendInfoMain(data, offset, lenght, info, INDEX_ZERO);
714 if (channelNum == THREE_COMPONENTS) {
715 ParseISOExtendInfoMain(data, offset, lenght, info, INDEX_ONE);
716 ParseISOExtendInfoMain(data, offset, lenght, info, INDEX_TWO);
717 } else {
718 info.gainMapMin[INDEX_ONE] = info.gainMapMin[INDEX_ZERO];
719 info.gainMapMax[INDEX_ONE] = info.gainMapMax[INDEX_ZERO];
720 info.gamma[INDEX_ONE] = info.gamma[INDEX_ZERO];
721 info.baseSdrImageOffset[INDEX_ONE] = info.baseSdrImageOffset[INDEX_ZERO];
722 info.altHdrImageOffset[INDEX_ONE] = info.altHdrImageOffset[INDEX_ZERO];
723 info.gainMapMin[INDEX_TWO] = info.gainMapMin[INDEX_ZERO];
724 info.gainMapMax[INDEX_TWO] = info.gainMapMax[INDEX_ZERO];
725 info.gamma[INDEX_TWO] = info.gamma[INDEX_ZERO];
726 info.baseSdrImageOffset[INDEX_TWO] = info.baseSdrImageOffset[INDEX_ZERO];
727 info.altHdrImageOffset[INDEX_TWO] = info.altHdrImageOffset[INDEX_ZERO];
728 }
729 }
730
ParseISOMetadata(uint8_t * data,uint32_t length,HdrMetadata & metadata)731 static bool ParseISOMetadata(uint8_t* data, uint32_t length, HdrMetadata& metadata)
732 {
733 uint32_t dataOffset = 0;
734 if (length < ISO_GAINMAP_METADATA_PAYLOAD_MIN_SIZE) {
735 return false;
736 }
737 metadata.extendMeta.metaISO.writeVersion = ImageUtils::BytesToUint32(data, dataOffset, length);
738 metadata.extendMeta.metaISO.miniVersion = metadata.extendMeta.metaISO.writeVersion & 0xFF;
739 if (metadata.extendMeta.metaISO.miniVersion != EMPTY_SIZE) {
740 return false;
741 }
742 uint8_t flag = data[dataOffset++];
743
744 // The first bit indicates the gainmapChannelNum, the second bit indicates the useBaseColorFlag.
745 metadata.extendMeta.metaISO.gainmapChannelNum = ((flag & 0x80) == 0x80) ? THREE_COMPONENTS : ONE_COMPONENT;
746 metadata.extendMeta.metaISO.useBaseColorFlag = ((flag & 0x40) == 0x40) ? 0x01 : 0x00;
747
748 uint32_t baseHeadroomNumerator = ImageUtils::BytesToUint32(data, dataOffset, length);
749 uint32_t baseHeadroomDenominator = ImageUtils::BytesToUint32(data, dataOffset, length);
750 uint32_t altHeadroomNumerator = ImageUtils::BytesToUint32(data, dataOffset, length);
751 uint32_t altHeadroomDenominator = ImageUtils::BytesToUint32(data, dataOffset, length);
752
753 if (baseHeadroomDenominator != EMPTY_SIZE) {
754 metadata.extendMeta.metaISO.baseHeadroom = (float)baseHeadroomNumerator / (float)baseHeadroomDenominator;
755 } else {
756 metadata.extendMeta.metaISO.baseHeadroom = (float)EMPTY_SIZE;
757 }
758 if (altHeadroomDenominator != EMPTY_SIZE) {
759 metadata.extendMeta.metaISO.alternateHeadroom = (float)altHeadroomNumerator / (float)altHeadroomDenominator;
760 } else {
761 metadata.extendMeta.metaISO.alternateHeadroom = (float)EMPTY_SIZE;
762 }
763 ExtendInfoMain infoMain{};
764 ParseISOExtendInfoThreeCom(data, dataOffset, length, metadata.extendMeta.metaISO.gainmapChannelNum, infoMain);
765 ConvertExtendInfoMain(infoMain, metadata.extendMeta);
766 metadata.extendMetaFlag = true;
767 return true;
768 }
769
GetISOGainmapMetadata(jpeg_marker_struct * markerList,HdrMetadata & metadata)770 static bool GetISOGainmapMetadata(jpeg_marker_struct* markerList, HdrMetadata& metadata)
771 {
772 for (jpeg_marker_struct* marker = markerList; marker; marker = marker->next) {
773 if (JPEG_MARKER_APP2 != marker->marker) {
774 continue;
775 }
776 if (marker->data_length <= ISO_GAINMAP_TAG_SIZE ||
777 memcmp(marker->data, ISO_GAINMAP_TAG, ISO_GAINMAP_TAG_SIZE) != 0) {
778 continue;
779 }
780 uint8_t* data = marker->data + ISO_GAINMAP_TAG_SIZE;
781 uint32_t length = marker->data_length - ISO_GAINMAP_TAG_SIZE;
782 return ParseISOMetadata(data, length, metadata);
783 }
784 return false;
785 }
786
GetHdrMediaTypeInfo(jpeg_marker_struct * markerList,HdrMetadata & metadata)787 static bool GetHdrMediaTypeInfo(jpeg_marker_struct* markerList, HdrMetadata& metadata)
788 {
789 for (jpeg_marker_struct* marker = markerList; marker; marker = marker->next) {
790 if (JPEG_MARKER_APP11 != marker->marker) {
791 continue;
792 }
793 if (marker->data_length <= HDR_MEDIA_TYPE_TAG_SIZE ||
794 memcmp(marker->data, HDR_MEDIA_TYPE_TAG, HDR_MEDIA_TYPE_TAG_SIZE) != 0) {
795 continue;
796 }
797 uint8_t* data = marker->data + HDR_MEDIA_TYPE_TAG_SIZE;
798 uint32_t dataOffset = 0;
799 uint32_t hdrMediaType = ImageUtils::BytesToUint32(data, dataOffset, marker->data_length);
800 metadata.hdrMetadataType = static_cast<int32_t>(hdrMediaType);
801 return true;
802 }
803 return false;
804 }
805
GetJpegGainMapMetadata(SkJpegCodec * codec,ImageHdrType type,HdrMetadata & metadata)806 static bool GetJpegGainMapMetadata(SkJpegCodec* codec, ImageHdrType type, HdrMetadata& metadata)
807 {
808 if (codec == nullptr || codec->decoderMgr() == nullptr) {
809 IMAGE_LOGE("GetJpegGainMapMetadata codec is nullptr");
810 return false;
811 }
812 jpeg_marker_struct* markerList = codec->decoderMgr()->dinfo()->marker_list;
813 if (!markerList) {
814 return false;
815 }
816 GetHdrMediaTypeInfo(markerList, metadata);
817 switch (type) {
818 case ImageHdrType::HDR_VIVID_DUAL: {
819 bool res = GetVividJpegMetadata(markerList, metadata);
820 if (res && !metadata.extendMetaFlag) {
821 GetISOGainmapMetadata(markerList, metadata);
822 }
823 return res;
824 }
825 case ImageHdrType::HDR_CUVA:
826 return true;
827 case ImageHdrType::HDR_ISO_DUAL:
828 return GetISOGainmapMetadata(markerList, metadata);
829 default:
830 return false;
831 }
832 }
833
834 #ifdef HEIF_HW_DECODE_ENABLE
ParseHeifStaticMetadata(const vector<uint8_t> & displayInfo,const vector<uint8_t> & lightInfo)835 static vector<uint8_t> ParseHeifStaticMetadata(const vector<uint8_t>& displayInfo, const vector<uint8_t>& lightInfo)
836 {
837 #if defined(_WIN32) || defined(_APPLE) || defined(IOS_PLATFORM) || defined(ANDROID_PLATFORM)
838 return {};
839 #else
840 HDI::Display::Graphic::Common::V1_0::HdrStaticMetadata staticMetadata{};
841 DisplayColourVolume displayColourVolume{};
842 ContentLightLevelInfo lightLevelInfo{};
843 if (!lightInfo.empty()) {
844 if (memcpy_s(&lightLevelInfo, sizeof(ContentLightLevelInfo), lightInfo.data(), lightInfo.size()) != EOK) {
845 return {};
846 }
847 }
848 if (!displayInfo.empty()) {
849 if (memcpy_s(&displayColourVolume, sizeof(DisplayColourVolume),
850 displayInfo.data(), displayInfo.size()) != EOK) {
851 return {};
852 }
853 }
854 const float colorScale = 0.00002f;
855 const float lumScale = 0.0001f;
856 staticMetadata.smpte2086.displayPrimaryRed.x = colorScale * (float)displayColourVolume.red.x;
857 staticMetadata.smpte2086.displayPrimaryRed.y = colorScale * (float)displayColourVolume.red.y;
858 staticMetadata.smpte2086.displayPrimaryGreen.x = colorScale * (float)displayColourVolume.green.x;
859 staticMetadata.smpte2086.displayPrimaryGreen.y = colorScale * (float)displayColourVolume.green.y;
860 staticMetadata.smpte2086.displayPrimaryBlue.x = colorScale * (float)displayColourVolume.blue.x;
861 staticMetadata.smpte2086.displayPrimaryBlue.y = colorScale * (float)displayColourVolume.blue.y;
862 staticMetadata.smpte2086.whitePoint.x = colorScale * (float)displayColourVolume.whitePoint.x;
863 staticMetadata.smpte2086.whitePoint.y = colorScale * (float)displayColourVolume.whitePoint.y;
864 staticMetadata.smpte2086.maxLuminance = (float)displayColourVolume.luminanceMax;
865 staticMetadata.smpte2086.minLuminance = lumScale * (float)displayColourVolume.luminanceMin;
866 staticMetadata.cta861.maxContentLightLevel = (float)lightLevelInfo.maxContentLightLevel;
867 staticMetadata.cta861.maxFrameAverageLightLevel = (float)lightLevelInfo.maxPicAverageLightLevel;
868 uint32_t vecSize = sizeof(HDI::Display::Graphic::Common::V1_0::HdrStaticMetadata);
869 std::vector<uint8_t> staticMetadataVec(vecSize);
870 if (memcpy_s(staticMetadataVec.data(), vecSize, &staticMetadata, vecSize) != EOK) {
871 return {};
872 }
873 return staticMetadataVec;
874 #endif
875 }
876
GetHeifMetadata(HeifDecoder * heifDecoder,ImageHdrType type,HdrMetadata & metadata)877 static bool GetHeifMetadata(HeifDecoder* heifDecoder, ImageHdrType type, HdrMetadata& metadata)
878 {
879 if (heifDecoder == nullptr) {
880 return false;
881 }
882 if (type == ImageHdrType::HDR_VIVID_DUAL || type == ImageHdrType::HDR_VIVID_SINGLE) {
883 vector<uint8_t> uwaInfo;
884 vector<uint8_t> displayInfo;
885 vector<uint8_t> lightInfo;
886 heifDecoder->getVividMetadata(uwaInfo, displayInfo, lightInfo);
887 if (uwaInfo.empty()) {
888 return false;
889 }
890 metadata.staticMetadata = ParseHeifStaticMetadata(displayInfo, lightInfo);
891 bool res = ParseVividMetadata(uwaInfo.data(), uwaInfo.size(), metadata);
892 if (!metadata.extendMetaFlag) {
893 vector<uint8_t> isoMetadata;
894 heifDecoder->getISOMetadata(isoMetadata);
895 if (isoMetadata.empty()) {
896 return res;
897 }
898 if (isoMetadata.size() > EMPTY_SIZE && isoMetadata[INDEX_ZERO] == EMPTY_SIZE) {
899 ParseISOMetadata(isoMetadata.data() + INDEX_ONE, isoMetadata.size() - INDEX_ONE, metadata);
900 }
901 }
902 return res;
903 } else if (type == ImageHdrType::HDR_ISO_DUAL || type == ImageHdrType::HDR_ISO_SINGLE) {
904 vector<uint8_t> isoMetadata;
905 heifDecoder->getISOMetadata(isoMetadata);
906 if (isoMetadata.empty()) {
907 return false;
908 }
909 if (isoMetadata.size() > EMPTY_SIZE && isoMetadata[INDEX_ZERO] == EMPTY_SIZE) {
910 return ParseISOMetadata(isoMetadata.data() + INDEX_ONE, isoMetadata.size() - INDEX_ONE, metadata);
911 }
912 }
913 return false;
914 }
915 #endif
916
GetMetadata(SkCodec * codec,ImageHdrType type,HdrMetadata & metadata)917 bool HdrHelper::GetMetadata(SkCodec* codec, ImageHdrType type, HdrMetadata& metadata)
918 {
919 if (type <= ImageHdrType::SDR || codec == nullptr) {
920 return false;
921 }
922 switch (codec->getEncodedFormat()) {
923 case SkEncodedImageFormat::kJPEG: {
924 SkJpegCodec* jpegCodec = static_cast<SkJpegCodec*>(codec);
925 return GetJpegGainMapMetadata(jpegCodec, type, metadata);
926 }
927 case SkEncodedImageFormat::kHEIF: {
928 #ifdef HEIF_HW_DECODE_ENABLE
929 auto decoder = reinterpret_cast<HeifDecoder*>(codec->getHeifContext());
930 return GetHeifMetadata(decoder, type, metadata);
931 #else
932 return false;
933 #endif
934 }
935 default:
936 return false;
937 }
938 }
939
940 // LCOV_EXCL_START
941 /// pack jpeg base image vivid marker
PackVividPreInfo(vector<uint8_t> & bytes,uint32_t & offset,bool base,bool enhanceType)942 static void PackVividPreInfo(vector<uint8_t>& bytes, uint32_t& offset, bool base, bool enhanceType)
943 {
944 bytes[offset++] = 0x26; // itut35 country code
945 bytes[offset++] = 0x00;
946 bytes[offset++] = 0x04; // terminalProvideCode
947 bytes[offset++] = 0x00;
948 bytes[offset++] = 0x07; // terminalProvideOrientedCode
949 bytes[offset++] = 0x02; // extendFrameNumber
950 bytes[offset++] = base ? INDEX_ONE : INDEX_TWO; // fileType
951 bytes[offset++] = base ? INDEX_ZERO : INDEX_ONE; // metaType
952 bytes[offset++] = ((!base) && enhanceType) ? INDEX_ONE : INDEX_ZERO; // enhanceType
953 bytes[offset++] = INDEX_ZERO;
954 }
955 // LCOV_EXCL_STOP
956
GetBaseVividMarkerSize()957 uint32_t HdrJpegPackerHelper::GetBaseVividMarkerSize()
958 {
959 const uint32_t baseInfoMarkerLength =
960 JPEG_MARKER_TAG_SIZE + JPEG_MARKER_LENGTH_SIZE + ITUT35_TAG_SIZE +
961 VIVID_PRE_INFO_SIZE + UINT32_BYTE_COUNT + // offset size
962 UINT32_BYTE_COUNT; // gainmap length size
963 return baseInfoMarkerLength;
964 }
965
GetMpfMarkerSize()966 uint32_t HdrJpegPackerHelper::GetMpfMarkerSize()
967 {
968 return HDR_MULTI_PICTURE_APP_LENGTH;
969 }
970
971 // LCOV_EXCL_START
PackBaseVividMarker(uint32_t gainmapOffset,uint32_t preOffset,uint32_t appSize)972 vector<uint8_t> HdrJpegPackerHelper::PackBaseVividMarker(uint32_t gainmapOffset, uint32_t preOffset, uint32_t appSize)
973 {
974 const uint32_t baseInfoMarkerLength = GetBaseVividMarkerSize();
975 vector<uint8_t> bytes(baseInfoMarkerLength);
976 uint32_t index = 0;
977 bytes[index++] = JPEG_MARKER_PREFIX;
978 bytes[index++] = JPEG_MARKER_APP8;
979 // length does not contain marker tag size;
980 uint32_t markerDataLength = baseInfoMarkerLength - JPEG_MARKER_TAG_SIZE;
981 ImageUtils::Uint16ToBytes(markerDataLength, bytes, index);
982 ImageUtils::ArrayToBytes(ITUT35_TAG, ITUT35_TAG_SIZE, bytes, index);
983 PackVividPreInfo(bytes, index, true, false);
984 // set gainmap offset1 (gainmapOffset - current position offset)
985 ImageUtils::Uint32ToBytes(gainmapOffset - preOffset, bytes, index);
986 // set gainmap offset2 (gainmap size - app size)
987 ImageUtils::Uint32ToBytes(gainmapOffset - appSize, bytes, index);
988 return bytes;
989 }
990
PackBaseMpfMarker(uint32_t baseSize,uint32_t gainmapSize,uint32_t appOffset)991 vector<uint8_t> HdrJpegPackerHelper::PackBaseMpfMarker(uint32_t baseSize, uint32_t gainmapSize, uint32_t appOffset)
992 {
993 SingleJpegImage baseImage = {
994 .offset = 0,
995 .size = baseSize,
996 };
997 SingleJpegImage gainmapImage = {
998 .offset = baseSize - appOffset - JPEG_MARKER_TAG_SIZE - JPEG_MARKER_LENGTH_SIZE - MPF_TAG_SIZE,
999 .size = gainmapSize,
1000 };
1001 return JpegMpfPacker::PackHdrJpegMpfMarker(baseImage, gainmapImage);
1002 }
1003
PackBaseISOMarker()1004 vector<uint8_t> HdrJpegPackerHelper::PackBaseISOMarker()
1005 {
1006 // marker + isoGainmapTag + ISOPayload
1007 uint32_t isoBaseLength = UINT32_BYTE_COUNT + ISO_GAINMAP_TAG_SIZE + UINT32_BYTE_COUNT;
1008 vector<uint8_t> bytes(isoBaseLength);
1009 uint32_t index = 0;
1010 bytes[index++] = JPEG_MARKER_PREFIX;
1011 bytes[index++] = JPEG_MARKER_APP2;
1012 // length dose not contain marker
1013 uint32_t length = isoBaseLength - JPEG_MARKER_TAG_SIZE;
1014 ImageUtils::Uint16ToBytes(length, bytes, index); // set iso marker size
1015 ImageUtils::ArrayToBytes(ISO_GAINMAP_TAG, ISO_GAINMAP_TAG_SIZE, bytes, index);
1016 ImageUtils::Uint32ToBytes(EMPTY_SIZE, bytes, index); // set iso payload size
1017 return bytes;
1018 }
1019
PackHdrMediaTypeMarker(HdrMetadata & hdrMetadata)1020 vector<uint8_t> HdrJpegPackerHelper::PackHdrMediaTypeMarker(HdrMetadata& hdrMetadata)
1021 {
1022 // marker + hdrMediaTypeTag + TypeNumber
1023 uint32_t hdrMediaTypeLength = UINT32_BYTE_COUNT + HDR_MEDIA_TYPE_TAG_SIZE + UINT32_BYTE_COUNT;
1024 vector<uint8_t> bytes(hdrMediaTypeLength);
1025 uint32_t index = 0;
1026 bytes[index++] = JPEG_MARKER_PREFIX;
1027 bytes[index++] = JPEG_MARKER_APP11;
1028 // length dose not contain marker
1029 uint32_t length = hdrMediaTypeLength - JPEG_MARKER_TAG_SIZE;
1030 ImageUtils::Uint16ToBytes(length, bytes, index); // set iso marker size
1031 ImageUtils::ArrayToBytes(HDR_MEDIA_TYPE_TAG, HDR_MEDIA_TYPE_TAG_SIZE, bytes, index);
1032 ImageUtils::Uint32ToBytes(static_cast<uint32_t>(hdrMetadata.hdrMetadataType), bytes, index);
1033 return bytes;
1034 }
1035
PackExtendInfoMain(vector<uint8_t> & bytes,uint32_t & offset,HDRVividExtendMetadata & metadata)1036 static void PackExtendInfoMain(vector<uint8_t>& bytes, uint32_t& offset, HDRVividExtendMetadata& metadata)
1037 {
1038 ImageUtils::FloatToBytes(metadata.metaISO.enhanceClippedThreholdMinGainmap[INDEX_ZERO], bytes, offset);
1039 ImageUtils::FloatToBytes(metadata.metaISO.enhanceClippedThreholdMaxGainmap[INDEX_ZERO], bytes, offset);
1040 ImageUtils::FloatToBytes(metadata.metaISO.enhanceMappingGamma[INDEX_ZERO], bytes, offset);
1041 ImageUtils::FloatToBytes(metadata.metaISO.enhanceMappingBaselineOffset[INDEX_ZERO], bytes, offset);
1042 ImageUtils::FloatToBytes(metadata.metaISO.enhanceMappingAlternateOffset[INDEX_ZERO], bytes, offset);
1043
1044 ImageUtils::FloatToBytes(metadata.metaISO.enhanceClippedThreholdMinGainmap[INDEX_ONE], bytes, offset);
1045 ImageUtils::FloatToBytes(metadata.metaISO.enhanceClippedThreholdMaxGainmap[INDEX_ONE], bytes, offset);
1046 ImageUtils::FloatToBytes(metadata.metaISO.enhanceMappingGamma[INDEX_ONE], bytes, offset);
1047 ImageUtils::FloatToBytes(metadata.metaISO.enhanceMappingBaselineOffset[INDEX_ONE], bytes, offset);
1048 ImageUtils::FloatToBytes(metadata.metaISO.enhanceMappingAlternateOffset[INDEX_ONE], bytes, offset);
1049
1050 ImageUtils::FloatToBytes(metadata.metaISO.enhanceClippedThreholdMinGainmap[INDEX_TWO], bytes, offset);
1051 ImageUtils::FloatToBytes(metadata.metaISO.enhanceClippedThreholdMaxGainmap[INDEX_TWO], bytes, offset);
1052 ImageUtils::FloatToBytes(metadata.metaISO.enhanceMappingGamma[INDEX_TWO], bytes, offset);
1053 ImageUtils::FloatToBytes(metadata.metaISO.enhanceMappingBaselineOffset[INDEX_TWO], bytes, offset);
1054 ImageUtils::FloatToBytes(metadata.metaISO.enhanceMappingAlternateOffset[INDEX_TWO], bytes, offset);
1055 }
1056
PackTransformInfo(vector<uint8_t> & bytes,uint32_t & offset,uint8_t flag,vector<uint8_t> mapping)1057 static void PackTransformInfo(vector<uint8_t>& bytes, uint32_t& offset, uint8_t flag, vector<uint8_t> mapping)
1058 {
1059 if (flag == EMPTY_SIZE || flag != mapping.size()) {
1060 ImageUtils::Uint16ToBytes((uint16_t)EMPTY_SIZE, bytes, offset);
1061 return;
1062 }
1063 uint16_t transformSize = flag + UINT8_BYTE_COUNT;
1064 ImageUtils::Uint16ToBytes(transformSize, bytes, offset);
1065 bytes[offset++] = flag;
1066 if (memcpy_s(bytes.data() + offset, flag, mapping.data(), flag) != 0) {
1067 offset -= (UINT8_BYTE_COUNT + UINT16_BYTE_COUNT);
1068 ImageUtils::Uint16ToBytes((uint16_t)EMPTY_SIZE, bytes, offset);
1069 return;
1070 }
1071 offset += flag;
1072 }
1073
PackExtendInfoExtention(vector<uint8_t> & bytes,uint32_t & offset,const HDRVividExtendMetadata & metadata)1074 static void PackExtendInfoExtention(vector<uint8_t>& bytes, uint32_t& offset, const HDRVividExtendMetadata& metadata)
1075 {
1076 bytes[offset++] = COLOR_INFO_BYTES;
1077 bytes[offset++] = metadata.baseColorMeta.baseColorPrimary;
1078 bytes[offset++] = metadata.baseColorMeta.baseTransFunction;
1079 bytes[offset++] = metadata.baseColorMeta.baseColorModel;
1080 bytes[offset++] = COLOR_INFO_BYTES;
1081 bytes[offset++] = metadata.gainmapColorMeta.enhanceDataColorPrimary;
1082 bytes[offset++] = metadata.gainmapColorMeta.enhanceDataTransFunction;
1083 bytes[offset++] = metadata.gainmapColorMeta.enhanceDataColorModel;
1084 bytes[offset++] = COLOR_INFO_BYTES;
1085 bytes[offset++] = metadata.gainmapColorMeta.alternateColorPrimary;
1086 bytes[offset++] = metadata.gainmapColorMeta.alternateTransFunction;
1087 bytes[offset++] = metadata.gainmapColorMeta.alternateColorModel;
1088 bytes[offset++] = COLOR_INFO_BYTES;
1089 bytes[offset++] = metadata.gainmapColorMeta.combineColorPrimary;
1090 bytes[offset++] = metadata.gainmapColorMeta.combineTransFunction;
1091 bytes[offset++] = metadata.gainmapColorMeta.combineColorModel;
1092 PackTransformInfo(bytes, offset, metadata.baseColorMeta.baseMappingFlag, metadata.baseColorMeta.baseMapping);
1093 PackTransformInfo(bytes, offset, metadata.gainmapColorMeta.combineMappingFlag,
1094 metadata.gainmapColorMeta.combineMapping);
1095 }
1096 // LCOV_EXCL_STOP
1097
GetExtendMetadataSize(bool vividExtendFlag,const HDRVividExtendMetadata & metadata)1098 static uint16_t GetExtendMetadataSize(bool vividExtendFlag, const HDRVividExtendMetadata& metadata)
1099 {
1100 if (!vividExtendFlag) {
1101 return EMPTY_SIZE;
1102 }
1103 const uint8_t colorInfoNum = 4;
1104 uint16_t extendInfoExtentionSize = (COLOR_INFO_BYTES + UINT8_BYTE_COUNT) * colorInfoNum +
1105 UINT16_BYTE_COUNT + UINT16_BYTE_COUNT; // "baseTransformInfoSize" count + "EnhanceTransformInfoSize" count
1106 if (metadata.baseColorMeta.baseMappingFlag > EMPTY_SIZE) {
1107 // "mapping" + "mapping" bytes
1108 extendInfoExtentionSize += metadata.baseColorMeta.baseMappingFlag + UINT8_BYTE_COUNT;
1109 }
1110 if (metadata.gainmapColorMeta.combineMappingFlag > EMPTY_SIZE) {
1111 extendInfoExtentionSize += metadata.gainmapColorMeta.combineMappingFlag + UINT8_BYTE_COUNT;
1112 }
1113 uint16_t extendSize = UINT8_BYTE_COUNT + EXTEND_INFO_MAIN_SIZE + extendInfoExtentionSize;
1114 return extendSize;
1115 }
1116
PackExtendMetadata(vector<uint8_t> & bytes,uint32_t & index,HDRVividExtendMetadata & metadata)1117 static void PackExtendMetadata(vector<uint8_t>& bytes, uint32_t& index, HDRVividExtendMetadata& metadata)
1118 {
1119 uint16_t length = GetExtendMetadataSize(true, metadata);
1120 if (index + length > bytes.size()) {
1121 return;
1122 }
1123 ImageUtils::Uint16ToBytes(length, bytes, index);
1124 bytes[index++] = THREE_COMPONENTS;
1125 PackExtendInfoMain(bytes, index, metadata);
1126 PackExtendInfoExtention(bytes, index, metadata);
1127 }
1128
1129 // LCOV_EXCL_START
PackVividStaticMetadata(vector<uint8_t> & bytes,uint32_t & index,vector<uint8_t> & staticVec)1130 static bool PackVividStaticMetadata(vector<uint8_t>& bytes, uint32_t& index, vector<uint8_t>& staticVec)
1131 {
1132 #if defined(_WIN32) || defined(_APPLE) || defined(IOS_PLATFORM) || defined(ANDROID_PLATFORM)
1133 return false;
1134 #else
1135 HdrStaticMetadata staticMeta;
1136 uint32_t vecSize = sizeof(HdrStaticMetadata);
1137 if (memcpy_s(&staticMeta, vecSize, staticVec.data(), vecSize) != EOK) {
1138 return false;
1139 }
1140 ImageUtils::Uint16ToBytes(VIVID_STATIC_METADATA_SIZE_IN_IMAGE, bytes, index);
1141 ImageUtils::Uint16ToBytes((uint16_t)(staticMeta.smpte2086.displayPrimaryRed.x / SM_COLOR_SCALE), bytes, index);
1142 ImageUtils::Uint16ToBytes((uint16_t)(staticMeta.smpte2086.displayPrimaryRed.y / SM_COLOR_SCALE), bytes, index);
1143 ImageUtils::Uint16ToBytes((uint16_t)(staticMeta.smpte2086.displayPrimaryGreen.x / SM_COLOR_SCALE), bytes, index);
1144 ImageUtils::Uint16ToBytes((uint16_t)(staticMeta.smpte2086.displayPrimaryGreen.y / SM_COLOR_SCALE), bytes, index);
1145 ImageUtils::Uint16ToBytes((uint16_t)(staticMeta.smpte2086.displayPrimaryBlue.x / SM_COLOR_SCALE), bytes, index);
1146 ImageUtils::Uint16ToBytes((uint16_t)(staticMeta.smpte2086.displayPrimaryBlue.y / SM_COLOR_SCALE), bytes, index);
1147 ImageUtils::Uint16ToBytes((uint16_t)(staticMeta.smpte2086.whitePoint.x / SM_COLOR_SCALE), bytes, index);
1148 ImageUtils::Uint16ToBytes((uint16_t)(staticMeta.smpte2086.whitePoint.y / SM_COLOR_SCALE), bytes, index);
1149 ImageUtils::Uint32ToBytes((uint16_t)(staticMeta.smpte2086.maxLuminance), bytes, index);
1150 ImageUtils::Uint32ToBytes((uint16_t)(staticMeta.smpte2086.minLuminance / SM_LUM_SCALE), bytes, index);
1151 ImageUtils::Uint16ToBytes((uint16_t)staticMeta.cta861.maxContentLightLevel, bytes, index);
1152 ImageUtils::Uint16ToBytes((uint16_t)staticMeta.cta861.maxFrameAverageLightLevel, bytes, index);
1153 return true;
1154 #endif
1155 }
1156 // LCOV_EXCL_STOP
1157
PackVividMetadata(vector<uint8_t> & bytes,uint32_t & index,HdrMetadata & metadata)1158 static bool PackVividMetadata(vector<uint8_t>& bytes, uint32_t& index, HdrMetadata& metadata)
1159 {
1160 uint32_t dynamicMetadataSize = metadata.dynamicMetadata.size();
1161 const uint32_t metadataSize =
1162 UINT16_BYTE_COUNT + VIVID_STATIC_METADATA_SIZE_IN_IMAGE + UINT16_BYTE_COUNT + dynamicMetadataSize;
1163 PackVividPreInfo(bytes, index, false, false);
1164 ImageUtils::Uint16ToBytes(metadataSize, bytes, index);
1165 if (!PackVividStaticMetadata(bytes, index, metadata.staticMetadata)) {
1166 return false;
1167 }
1168 ImageUtils::Uint16ToBytes(dynamicMetadataSize, bytes, index);
1169 if (memcpy_s(bytes.data() + index, bytes.size() - index,
1170 metadata.dynamicMetadata.data(), metadata.dynamicMetadata.size()) != EOK) {
1171 return false;
1172 }
1173 index += metadata.dynamicMetadata.size();
1174 PackExtendMetadata(bytes, index, metadata.extendMeta);
1175 return true;
1176 }
1177
PackVividMetadataMarker(HdrMetadata & metadata)1178 std::vector<uint8_t> HdrJpegPackerHelper::PackVividMetadataMarker(HdrMetadata& metadata)
1179 {
1180 uint32_t dynamicMetadataSize = metadata.dynamicMetadata.size();
1181 // metadataSize + staticMetadataSize + staticMetadata + dynamicMetadataSize + dynamicMetadata
1182 const uint32_t metadataSize = UINT16_BYTE_COUNT + UINT16_BYTE_COUNT + VIVID_STATIC_METADATA_SIZE_IN_IMAGE +
1183 UINT16_BYTE_COUNT + dynamicMetadataSize;
1184 uint32_t extendInfoSize = GetExtendMetadataSize(false, metadata.extendMeta);
1185 uint32_t markerLength = UINT32_BYTE_COUNT + ITUT35_TAG_SIZE + VIVID_METADATA_PRE_INFO_SIZE +
1186 metadataSize;
1187 if (extendInfoSize != EMPTY_SIZE) {
1188 markerLength += (UINT16_BYTE_COUNT + extendInfoSize);
1189 }
1190 vector<uint8_t> bytes(markerLength);
1191 uint32_t index = 0;
1192 bytes[index++] = JPEG_MARKER_PREFIX;
1193 bytes[index++] = JPEG_MARKER_APP8;
1194 uint32_t storeLength = markerLength - JPEG_MARKER_TAG_SIZE;
1195 ImageUtils::Uint16ToBytes(storeLength, bytes, index);
1196 ImageUtils::ArrayToBytes(ITUT35_TAG, ITUT35_TAG_SIZE, bytes, index);
1197 if (!PackVividMetadata(bytes, index, metadata)) {
1198 IMAGE_LOGE("hdr image package metadata failed");
1199 return {};
1200 }
1201 return bytes;
1202 }
1203
PackISOExtendInfo(vector<uint8_t> & bytes,uint32_t & offset,ISOMetadata & metadata)1204 static void PackISOExtendInfo(vector<uint8_t>& bytes, uint32_t& offset, ISOMetadata& metadata)
1205 {
1206 ImageUtils::Int32ToBytes(
1207 (int32_t)(metadata.enhanceClippedThreholdMinGainmap[INDEX_ZERO] * DENOMINATOR), bytes, offset);
1208 ImageUtils::Uint32ToBytes(DENOMINATOR, bytes, offset);
1209 ImageUtils::Int32ToBytes(
1210 (int32_t)(metadata.enhanceClippedThreholdMaxGainmap[INDEX_ZERO] * DENOMINATOR), bytes, offset);
1211 ImageUtils::Uint32ToBytes(DENOMINATOR, bytes, offset);
1212 ImageUtils::Uint32ToBytes((uint32_t)(DENOMINATOR * metadata.enhanceMappingGamma[INDEX_ZERO]), bytes, offset);
1213 ImageUtils::Uint32ToBytes(DENOMINATOR, bytes, offset);
1214 ImageUtils::Int32ToBytes(
1215 (int32_t)(metadata.enhanceMappingBaselineOffset[INDEX_ZERO] * DENOMINATOR), bytes, offset);
1216 ImageUtils::Uint32ToBytes(DENOMINATOR, bytes, offset);
1217 ImageUtils::Int32ToBytes(
1218 (int32_t)(metadata.enhanceMappingAlternateOffset[INDEX_ZERO] * DENOMINATOR), bytes, offset);
1219 ImageUtils::Uint32ToBytes(DENOMINATOR, bytes, offset);
1220
1221 ImageUtils::Int32ToBytes(
1222 (int32_t)(metadata.enhanceClippedThreholdMinGainmap[INDEX_ONE] * DENOMINATOR), bytes, offset);
1223 ImageUtils::Uint32ToBytes(DENOMINATOR, bytes, offset);
1224 ImageUtils::Int32ToBytes(
1225 (int32_t)(metadata.enhanceClippedThreholdMaxGainmap[INDEX_ONE] * DENOMINATOR), bytes, offset);
1226 ImageUtils::Uint32ToBytes(DENOMINATOR, bytes, offset);
1227 ImageUtils::Uint32ToBytes((uint32_t)(DENOMINATOR * metadata.enhanceMappingGamma[INDEX_ONE]), bytes, offset);
1228 ImageUtils::Uint32ToBytes(DENOMINATOR, bytes, offset);
1229 ImageUtils::Int32ToBytes(
1230 (int32_t)(metadata.enhanceMappingBaselineOffset[INDEX_ONE] * DENOMINATOR), bytes, offset);
1231 ImageUtils::Uint32ToBytes(DENOMINATOR, bytes, offset);
1232 ImageUtils::Int32ToBytes(
1233 (int32_t)(metadata.enhanceMappingAlternateOffset[INDEX_ONE] * DENOMINATOR), bytes, offset);
1234 ImageUtils::Uint32ToBytes(DENOMINATOR, bytes, offset);
1235
1236 ImageUtils::Int32ToBytes(
1237 (int32_t)(metadata.enhanceClippedThreholdMinGainmap[INDEX_TWO] * DENOMINATOR), bytes, offset);
1238 ImageUtils::Uint32ToBytes(DENOMINATOR, bytes, offset);
1239 ImageUtils::Int32ToBytes(
1240 (int32_t)(metadata.enhanceClippedThreholdMaxGainmap[INDEX_TWO] * DENOMINATOR), bytes, offset);
1241 ImageUtils::Uint32ToBytes(DENOMINATOR, bytes, offset);
1242 ImageUtils::Uint32ToBytes((uint32_t)(DENOMINATOR * metadata.enhanceMappingGamma[INDEX_TWO]), bytes, offset);
1243 ImageUtils::Uint32ToBytes(DENOMINATOR, bytes, offset);
1244 ImageUtils::Int32ToBytes(
1245 (int32_t)(metadata.enhanceMappingBaselineOffset[INDEX_TWO] * DENOMINATOR), bytes, offset);
1246 ImageUtils::Uint32ToBytes(DENOMINATOR, bytes, offset);
1247 ImageUtils::Int32ToBytes(
1248 (int32_t)(metadata.enhanceMappingAlternateOffset[INDEX_TWO] * DENOMINATOR), bytes, offset);
1249 ImageUtils::Uint32ToBytes(DENOMINATOR, bytes, offset);
1250 }
1251
PackISOMetadataMarker(HdrMetadata & metadata)1252 vector<uint8_t> HdrJpegPackerHelper::PackISOMetadataMarker(HdrMetadata& metadata)
1253 {
1254 HDRVividExtendMetadata extendMeta = metadata.extendMeta;
1255 // flag(u8)+baseheadroomNumerator(u32)+baseheadroomDenomintor(u32)+altheadroom(u32)+altheadroomDenominator(u32)
1256 uint32_t isoInfoSize =
1257 UINT8_BYTE_COUNT + UINT32_BYTE_COUNT + UINT32_BYTE_COUNT + UINT32_BYTE_COUNT + UINT32_BYTE_COUNT;
1258 const uint32_t extendInfoMainParaNum = 10;
1259 const uint32_t isoExtendInfoSize = UINT32_BYTE_COUNT * extendInfoMainParaNum * THREE_COMPONENTS;
1260 // marker + isoGainmapTag + version + isoinfo + extendInfoMain
1261 uint32_t markerLength = UINT32_BYTE_COUNT + ISO_GAINMAP_TAG_SIZE + UINT32_BYTE_COUNT +
1262 isoInfoSize + isoExtendInfoSize;
1263 vector<uint8_t> bytes(markerLength);
1264 uint32_t index = 0;
1265 bytes[index++] = JPEG_MARKER_PREFIX;
1266 bytes[index++] = JPEG_MARKER_APP2;
1267 uint32_t storeLength = markerLength - JPEG_MARKER_TAG_SIZE;
1268 ImageUtils::Uint16ToBytes(storeLength, bytes, index);
1269 if (memcpy_s(bytes.data() + index, bytes.size() - index, ISO_GAINMAP_TAG, ISO_GAINMAP_TAG_SIZE) != EOK) {
1270 return {};
1271 }
1272 index += ISO_GAINMAP_TAG_SIZE;
1273 ImageUtils::Uint32ToBytes(extendMeta.metaISO.writeVersion, bytes, index);
1274 bytes[index] = 0x00;
1275 if (extendMeta.metaISO.useBaseColorFlag) {
1276 bytes[index] |= 0x40;
1277 }
1278 if (extendMeta.metaISO.gainmapChannelNum) {
1279 bytes[index] |= 0x80;
1280 }
1281 index++;
1282 uint32_t baseHeadroomNumerator = EMPTY_SIZE;
1283 if (extendMeta.metaISO.baseHeadroom > (float)EMPTY_SIZE) {
1284 baseHeadroomNumerator = (uint32_t)(extendMeta.metaISO.baseHeadroom * DENOMINATOR);
1285 }
1286 uint32_t baseHeadroomDenominator = DENOMINATOR;
1287 ImageUtils::Uint32ToBytes(baseHeadroomNumerator, bytes, index);
1288 ImageUtils::Uint32ToBytes(baseHeadroomDenominator, bytes, index);
1289 uint32_t altHeadroomNumerator = EMPTY_SIZE;
1290 uint32_t altHeadroomDenominator = 0x01;
1291 if (extendMeta.metaISO.alternateHeadroom > (float)EMPTY_SIZE) {
1292 altHeadroomNumerator = (uint32_t)(extendMeta.metaISO.alternateHeadroom * DENOMINATOR);
1293 altHeadroomDenominator = DENOMINATOR;
1294 }
1295 ImageUtils::Uint32ToBytes(altHeadroomNumerator, bytes, index);
1296 ImageUtils::Uint32ToBytes(altHeadroomDenominator, bytes, index);
1297 PackISOExtendInfo(bytes, index, extendMeta.metaISO);
1298 return bytes;
1299 }
1300
WriteJpegPreApp(sk_sp<SkData> & imageData,SkWStream & outputStream,uint32_t & index,uint32_t & jfifSize)1301 static bool WriteJpegPreApp(sk_sp<SkData>& imageData, SkWStream& outputStream, uint32_t& index, uint32_t& jfifSize)
1302 {
1303 const uint8_t* imageBytes = reinterpret_cast<const uint8_t*>(imageData->data());
1304 if (*imageBytes != JPEG_MARKER_PREFIX || *(imageBytes + INDEX_ONE) != JPEG_SOI) {
1305 IMAGE_LOGE("hdr encode, the spliced image is not a jpeg");
1306 return false;
1307 }
1308 uint32_t dataSize = imageData->size();
1309 outputStream.write(imageBytes, JPEG_MARKER_TAG_SIZE);
1310 index += JPEG_MARKER_TAG_SIZE;
1311 while (index < dataSize) {
1312 if (imageBytes[index] != JPEG_MARKER_PREFIX) {
1313 return false;
1314 }
1315 if ((imageBytes[index + INDEX_ONE] & 0xF0) != JPEG_MARKER_APP0) {
1316 return true;
1317 }
1318 uint16_t markerSize = (imageBytes[index + INDEX_TWO] << MOVE_ONE_BYTE) | imageBytes[index + INDEX_THREE];
1319 if (markerSize > dataSize) {
1320 return false;
1321 }
1322 outputStream.write(imageBytes + index, markerSize + JPEG_MARKER_TAG_SIZE);
1323 if (imageBytes[index + INDEX_ONE] == JPEG_MARKER_APP0) {
1324 jfifSize = markerSize + JPEG_MARKER_TAG_SIZE;
1325 }
1326 index += (markerSize + JPEG_MARKER_TAG_SIZE);
1327 }
1328 return false;
1329 }
1330
SpliceHdrStream(sk_sp<SkData> & baseImage,sk_sp<SkData> & gainmapImage,SkWStream & output,HdrMetadata & metadata)1331 uint32_t HdrJpegPackerHelper::SpliceHdrStream(sk_sp<SkData>& baseImage, sk_sp<SkData>& gainmapImage,
1332 SkWStream& output, HdrMetadata& metadata)
1333 {
1334 if (baseImage == nullptr || gainmapImage == nullptr) {
1335 return ERR_IMAGE_ENCODE_FAILED;
1336 }
1337 uint32_t offset = 0;
1338 uint32_t jfifSize = 0;
1339 if (!WriteJpegPreApp(baseImage, output, offset, jfifSize)) {
1340 return ERR_IMAGE_ENCODE_FAILED;
1341 }
1342 std::vector<uint8_t> gainmapMetadataPack = PackVividMetadataMarker(metadata);
1343 std::vector<uint8_t> gainmapISOMetadataPack = PackISOMetadataMarker(metadata);
1344 std::vector<uint8_t> gainmapHdrMediaTypeInfo = PackHdrMediaTypeMarker(metadata);
1345 uint32_t gainmapSize = gainmapImage->size() + gainmapMetadataPack.size() +
1346 gainmapISOMetadataPack.size() + gainmapHdrMediaTypeInfo.size();
1347 std::vector<uint8_t> baseISOInfo = PackBaseISOMarker();
1348 uint32_t baseVividApp8Size = GetBaseVividMarkerSize();
1349 uint32_t baseMpfApp2Size = GetMpfMarkerSize();
1350 uint32_t baseSize = baseImage->size() + baseISOInfo.size() + baseVividApp8Size + baseMpfApp2Size;
1351 uint32_t allAppSize = offset + baseISOInfo.size() + baseVividApp8Size + baseMpfApp2Size;
1352 std::vector<uint8_t> baseVividInfo = PackBaseVividMarker(baseSize, offset, allAppSize);
1353 std::vector<uint8_t> mpfInfo = PackBaseMpfMarker(baseSize, gainmapSize, offset + baseVividApp8Size);
1354 output.write(baseVividInfo.data(), baseVividInfo.size());
1355 output.write(mpfInfo.data(), mpfInfo.size());
1356 output.write(baseISOInfo.data(), baseISOInfo.size());
1357 const uint8_t* baseBytes = reinterpret_cast<const uint8_t*>(baseImage->data());
1358 output.write(baseBytes + offset, baseImage->size() - offset);
1359
1360 // write gainmap
1361 const uint8_t* gainmapBytes = reinterpret_cast<const uint8_t*>(gainmapImage->data());
1362 output.write(gainmapBytes, JPEG_MARKER_TAG_SIZE);
1363 output.write(gainmapISOMetadataPack.data(), gainmapISOMetadataPack.size());
1364 output.write(gainmapMetadataPack.data(), gainmapMetadataPack.size());
1365 output.write(gainmapHdrMediaTypeInfo.data(), gainmapHdrMediaTypeInfo.size());
1366 output.write(gainmapBytes + JPEG_MARKER_TAG_SIZE, gainmapImage->size() - JPEG_MARKER_TAG_SIZE);
1367 return SUCCESS;
1368 }
1369
PackIT35Info(HdrMetadata & metadata,std::vector<uint8_t> & info)1370 bool HdrHeifPackerHelper::PackIT35Info(HdrMetadata& metadata, std::vector<uint8_t>& info)
1371 {
1372 uint32_t dynamicMetadataSize = metadata.dynamicMetadata.size();
1373
1374 // metadataSize + staticMetadataSize + staticMetadata + dynamicMetadataSize + dynamicMetadata
1375 const uint32_t metadataSize = UINT16_BYTE_COUNT + UINT16_BYTE_COUNT + VIVID_STATIC_METADATA_SIZE_IN_IMAGE +
1376 UINT16_BYTE_COUNT + dynamicMetadataSize;
1377 uint32_t extendInfoSize = GetExtendMetadataSize(false, metadata.extendMeta);
1378 uint32_t infoLength = VIVID_METADATA_PRE_INFO_SIZE + metadataSize;
1379 if (extendInfoSize != EMPTY_SIZE) {
1380 infoLength += (UINT16_BYTE_COUNT + extendInfoSize);
1381 }
1382 info.resize(infoLength);
1383 uint32_t index = 0;
1384 if (!PackVividMetadata(info, index, metadata)) {
1385 IMAGE_LOGE("hdr image package metadata failed");
1386 return false;
1387 }
1388 return true;
1389 }
1390 }
1391 }