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