1 /*
2 * Copyright (C) 2021 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 #include "icc_profile_info.h"
16
17 #include <algorithm>
18 #include <cstdio>
19 #include <cstddef>
20 #include <unistd.h>
21
22 #include "image_log.h"
23 #include "securec.h"
24 #include "jerror.h"
25
26 #undef LOG_DOMAIN
27 #define LOG_DOMAIN LOG_TAG_DOMAIN_ID_PLUGIN
28
29 #undef LOG_TAG
30 #define LOG_TAG "IccProfile"
31
32 namespace OHOS {
33 namespace ImagePlugin {
34 namespace {
35 static constexpr uint32_t ICC_MARKER = JPEG_APP0 + 2;
36 static constexpr uint32_t ICC_MARKER_HEADER_SIZE = 14;
37 static constexpr uint8_t ICC_SIGNATURE[] = {
38 'I', 'C', 'C', '_', 'P', 'R', 'O', 'F', 'I', 'L', 'E', '\0',
39 }; // Corresponding hexadecimal: { 0x49, 0x43, 0x43, 0x5F, 0x50, 0x52, 0x4F, 0x46, 0x49, 0x4C, 0x45, 0x00 }
40 }
41
ICCProfileInfo()42 ICCProfileInfo::ICCProfileInfo(): isSupportICCProfile_(false)
43 {
44 }
45
~ICCProfileInfo()46 ICCProfileInfo::~ICCProfileInfo()
47 {
48 }
49 #ifdef IMAGE_COLORSPACE_FLAG
GetICCData(j_decompress_ptr cinfo)50 sk_sp<SkData> ICCProfileInfo::GetICCData(j_decompress_ptr cinfo)
51 {
52 IMAGE_LOGI("%{public}s begin", __func__);
53 unsigned char *icc_profile = NULL;
54 unsigned int icc_data_len = 0;
55 bool isReadIccProfile = false;
56 sk_sp<SkData> data;
57 isReadIccProfile = jpeg_read_icc_profile(cinfo, &icc_profile, &icc_data_len);
58 if (isReadIccProfile) {
59 // copy ICC profile data
60 data = SkData::MakeWithCopy(icc_profile, icc_data_len);
61 } else {
62 IMAGE_LOGE("ERROR: jpeg_read_icc_profile failed!");
63 }
64
65 // clean up
66 free(icc_profile);
67 return data;
68 }
69
ParsingICCProfile(j_decompress_ptr cinfo)70 uint32_t ICCProfileInfo::ParsingICCProfile(j_decompress_ptr cinfo)
71 {
72 IMAGE_LOGI("%{public}s begin", __func__);
73
74 // read icc data to skdata
75 sk_sp<SkData> profile = GetICCData(cinfo);
76 skcms_ICCProfile parsed;
77 uint32_t parseResult = OHOS::Media::ERR_IMAGE_DENCODE_ICC_FAILED;
78 sk_sp<SkColorSpace> skColorSpace = nullptr;
79 if (profile != nullptr && skcms_Parse(profile->data(), profile->size(), &parsed)) {
80 skColorSpace = SkColorSpace::Make(parsed);
81 if (skColorSpace != nullptr) {
82 isSupportICCProfile_ = true;
83 }
84 } else {
85 skColorSpace = SkColorSpace::MakeRGB(SkNamedTransferFn::k2Dot2, SkNamedGamut::kAdobeRGB);
86 isSupportICCProfile_ = false;
87 }
88 if (skColorSpace != nullptr) {
89 parseResult = OHOS::Media::SUCCESS;
90 } else {
91 IMAGE_LOGE("ERROR: ParsingICCProfile skColorSpace is Null!");
92 }
93 grColorSpace_ = OHOS::ColorManager::ColorSpace(skColorSpace);
94 return parseResult;
95 }
96
getGrColorSpace()97 OHOS::ColorManager::ColorSpace ICCProfileInfo::getGrColorSpace()
98 {
99 return grColorSpace_;
100 }
101
IsSupportICCProfile()102 bool ICCProfileInfo::IsSupportICCProfile()
103 {
104 return isSupportICCProfile_;
105 }
106
PackingICCProfile(j_compress_ptr cinfo,const SkImageInfo & info)107 uint32_t ICCProfileInfo::PackingICCProfile(j_compress_ptr cinfo, const SkImageInfo& info)
108 {
109 IMAGE_LOGI("%{public}s begin", __func__);
110 uint32_t packingResult = OHOS::Media::ERR_IMAGE_ENCODE_ICC_FAILED;
111
112 // write colorspace to SKData
113 sk_sp<SkData> icc = icc_from_color_space(info);
114
115 if (icc) {
116 // get a contiguous block of profile memory with the icc signature
117 sk_sp<SkData> jpegMarkerData =
118 SkData::MakeUninitialized(ICC_MARKER_HEADER_SIZE + icc->size());
119 uint8_t* ptrMaker = static_cast<uint8_t*>(jpegMarkerData->writable_data());
120 (void)memcpy_s(ptrMaker, sizeof(*ptrMaker), ICC_SIGNATURE, sizeof(ICC_SIGNATURE));
121 ptrMaker += sizeof(ICC_SIGNATURE);
122 // first marker
123 *ptrMaker++ = 1;
124 // total markers
125 *ptrMaker++ = 1;
126 (void)memcpy_s(ptrMaker, sizeof(*ptrMaker), icc->data(), icc->size());
127 jpeg_write_marker(cinfo, ICC_MARKER, jpegMarkerData->bytes(), jpegMarkerData->size());
128 packingResult = OHOS::Media::SUCCESS;
129 } else {
130 IMAGE_LOGE("ERROR: PackingICCProfile icc profile is Null!");
131 }
132 return packingResult;
133 }
134 #endif
135 } // namespace ImagePlugin
136 } // namespace OHOS
137