1 /*
2 * Copyright (c) 2022-2023 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 "ans_image_util.h"
16 #include "ans_log_wrapper.h"
17 #include "image_packer.h"
18 #include "image_source.h"
19
20 namespace OHOS {
21 namespace Notification {
22 const std::string AnsImageUtil::IMAGE_FORMAT_PNG {"image/png"};
23 const uint8_t AnsImageUtil::IMAGE_QUALITY {100};
24 const uint8_t AnsImageUtil::SHIFT_FOUR {4};
25 const uint8_t AnsImageUtil::NUM_TEN {10};
26 const size_t AnsImageUtil::TWO_TIMES {2};
27 const uint32_t AnsImageUtil::DEFAULT_SIZE {25 * 1024 * 1024};
28
PackImage(const std::shared_ptr<Media::PixelMap> & pixelMap,const std::string & format)29 std::string AnsImageUtil::PackImage(const std::shared_ptr<Media::PixelMap> &pixelMap, const std::string &format)
30 {
31 if (!pixelMap || format.empty()) {
32 ANS_LOGW("invalid parameters");
33 return {};
34 }
35
36 Media::ImagePacker imagePacker;
37 Media::PackOption option;
38 option.format = format;
39 option.quality = IMAGE_QUALITY;
40 option.numberHint = 1;
41
42 std::set<std::string> formats;
43 auto ret = imagePacker.GetSupportedFormats(formats);
44 if (ret) {
45 ANS_LOGE("Failed to GetSupportedFormats, ret : %{public}u", ret);
46 return {};
47 }
48
49 auto size = static_cast<uint32_t>(pixelMap->GetByteCount());
50 ANS_LOGD("size of pixelMap : %{public}u", size);
51 if (size < DEFAULT_SIZE) {
52 size = DEFAULT_SIZE;
53 }
54 auto pbuf = new (std::nothrow) uint8_t [size];
55 if (pbuf == nullptr) {
56 ANS_LOGE("create buffer failed");
57 return {};
58 }
59
60 imagePacker.StartPacking(pbuf, size, option);
61 imagePacker.AddImage(*pixelMap);
62 int64_t packedSize {0};
63 imagePacker.FinalizePacking(packedSize);
64 ANS_LOGD("packed size : %{public}" PRId64, packedSize);
65
66 std::string pixelMapStr(reinterpret_cast<char*>(pbuf), static_cast<size_t>(packedSize));
67 delete [] pbuf;
68 pbuf = nullptr;
69
70 return BinToHex(pixelMapStr);
71 }
72
UnPackImage(const std::string & pixelMapStr,const std::string & format)73 std::shared_ptr<Media::PixelMap> AnsImageUtil::UnPackImage(const std::string &pixelMapStr, const std::string &format)
74 {
75 if (pixelMapStr.empty()) {
76 return {};
77 }
78
79 auto binStr = HexToBin(pixelMapStr);
80
81 uint32_t errorCode {0};
82 Media::SourceOptions opts;
83 opts.formatHint = format;
84 auto imageSource = Media::ImageSource::CreateImageSource(
85 reinterpret_cast<const uint8_t*>(binStr.data()),
86 static_cast<uint32_t>(binStr.length()),
87 opts, errorCode);
88 if (errorCode || !imageSource) {
89 ANS_LOGE("create imageSource failed");
90 return {};
91 }
92
93 Media::DecodeOptions decodeOpts;
94 auto pixelMap = imageSource->CreatePixelMap(decodeOpts, errorCode);
95 if (errorCode || !pixelMap) {
96 ANS_LOGE("Failed to create pixelMap.");
97 return {};
98 }
99
100 return pixelMap;
101 }
102
PackImage2File(const std::shared_ptr<Media::PixelMap> & pixelMap,const std::string & outFilePath,const std::string & format)103 bool AnsImageUtil::PackImage2File(
104 const std::shared_ptr<Media::PixelMap> &pixelMap,
105 const std::string &outFilePath,
106 const std::string &format)
107 {
108 if (!pixelMap || outFilePath.empty() || format.empty()) {
109 ANS_LOGW("invalid parameters");
110 return false;
111 }
112
113 Media::ImagePacker imagePacker;
114 Media::PackOption option;
115 option.format = format;
116 option.quality = IMAGE_QUALITY;
117 option.numberHint = 1;
118
119 std::set<std::string> formats;
120 auto ret = imagePacker.GetSupportedFormats(formats);
121 if (ret) {
122 ANS_LOGE("image packer get supported format failed, ret : %{public}u", ret);
123 return false;
124 }
125
126 imagePacker.StartPacking(outFilePath, option);
127 imagePacker.AddImage(*pixelMap);
128 int64_t packedSize {0};
129 imagePacker.FinalizePacking(packedSize);
130 ANS_LOGI("packed size : %{public}" PRId64, packedSize);
131 return true;
132 }
133
CreatePixelMap(const std::string & inFilePath,const std::string & format)134 std::shared_ptr<Media::PixelMap> AnsImageUtil::CreatePixelMap(const std::string &inFilePath, const std::string &format)
135 {
136 if (inFilePath.empty() || format.empty()) {
137 ANS_LOGW("invalid parameters");
138 return {};
139 }
140
141 uint32_t errorCode {0};
142 Media::SourceOptions opts;
143 opts.formatHint = format;
144 auto imageSource = Media::ImageSource::CreateImageSource(inFilePath, opts, errorCode);
145 if (errorCode || !imageSource) {
146 ANS_LOGE("create imageSource failed");
147 return {};
148 }
149
150 std::set<std::string> formats;
151 auto ret = imageSource->GetSupportedFormats(formats);
152 if (ret) {
153 ANS_LOGE("image packer get supported format failed, ret : %{public}u", ret);
154 return {};
155 }
156
157 Media::DecodeOptions decodeOpts;
158 auto pixelMap = imageSource->CreatePixelMap(decodeOpts, errorCode);
159 if (errorCode || !pixelMap) {
160 ANS_LOGE("create pixelMap failed");
161 return {};
162 }
163
164 return pixelMap;
165 }
166
BinToHex(const std::string & strBin)167 std::string AnsImageUtil::BinToHex(const std::string &strBin)
168 {
169 if (strBin.empty()) {
170 return {};
171 }
172
173 std::string strHex;
174 strHex.resize(strBin.size() * TWO_TIMES);
175 for (size_t i = 0; i < strBin.size(); i++) {
176 uint8_t cTemp = strBin[i];
177 for (size_t j = 0; j < TWO_TIMES; j++) {
178 uint8_t cCur = (cTemp & 0x0f);
179 if (cCur < NUM_TEN) {
180 cCur += '0';
181 } else {
182 cCur += ('a' - NUM_TEN);
183 }
184 strHex[TWO_TIMES * i + 1 - j] = cCur;
185 cTemp >>= SHIFT_FOUR;
186 }
187 }
188
189 return strHex;
190 }
191
HexToBin(const std::string & strHex)192 std::string AnsImageUtil::HexToBin(const std::string &strHex)
193 {
194 if (strHex.size() % TWO_TIMES != 0) {
195 return {};
196 }
197
198 std::string strBin;
199 strBin.resize(strHex.size() / TWO_TIMES);
200 for (size_t i = 0; i < strBin.size(); i++) {
201 uint8_t cTemp = 0;
202 for (size_t j = 0; j < TWO_TIMES; j++) {
203 char cCur = strHex[TWO_TIMES * i + j];
204 uint8_t value = static_cast<uint8_t>(cTemp << SHIFT_FOUR);
205 if (cCur >= '0' && cCur <= '9') {
206 value += (cCur - '0');
207 } else if (cCur >= 'a' && cCur <= 'f') {
208 value += (cCur - 'a' + NUM_TEN);
209 } else if (cCur >= 'A' && cCur <= 'F') {
210 value += (cCur - 'A' + NUM_TEN);
211 } else {
212 return {};
213 }
214 cTemp = static_cast<uint8_t>(value);
215 }
216 strBin[i] = cTemp;
217 }
218
219 return strBin;
220 }
221 } // namespace Notification
222 } // namespace OHOS
223