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