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