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