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