1 /*
2 * Copyright (c) 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
16 #include "bundle_resource_image_info.h"
17
18 #include <sstream>
19
20 #include "app_log_wrapper.h"
21 #ifdef BUNDLE_FRAMEWORK_GRAPHICS
22 #include "image_packer.h"
23 #endif
24
25 namespace OHOS {
26 namespace AppExecFwk {
27 namespace {
28 constexpr uint8_t BIT_SIX = 6;
29 constexpr uint8_t BIT_FOUR = 4;
30 constexpr uint8_t BIT_TWO = 2;
31 constexpr uint8_t BIT_ONE = 1;
32 constexpr int32_t LEN_THREE = 3;
33 const std::vector<char> g_codes = {
34 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
35 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
36 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
37 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
38 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
39 };
40 #ifdef BUNDLE_FRAMEWORK_GRAPHICS
41 const std::string FORMAT = "image/png";
42 #endif
43 const std::string IMAGE_HEADER_INFO = "data:image/png;base64,";
44 }
45
46 #ifdef BUNDLE_FRAMEWORK_GRAPHICS
ConvertToString(const std::shared_ptr<Media::PixelMap> pixelMap,std::string & imageInfo)47 bool BundleResourceImageInfo::ConvertToString(
48 const std::shared_ptr<Media::PixelMap> pixelMap, std::string &imageInfo)
49 {
50 APP_LOGD("start");
51 if (pixelMap == nullptr) {
52 APP_LOGE("pixelMap is nullptr");
53 return false;
54 }
55 Media::PackOption option;
56 option.format = FORMAT;
57 Media::ImagePacker packer;
58 std::stringstream outputStream;
59 auto errCode = packer.StartPacking(outputStream, option);
60 if (errCode != 0) {
61 APP_LOGE("StartPacking failed %{public}d", static_cast<int32_t>(errCode));
62 return false;
63 }
64 errCode = packer.AddImage(*pixelMap);
65 if (errCode != 0) {
66 APP_LOGE("AddImage failed %{public}d", static_cast<int32_t>(errCode));
67 return false;
68 }
69 int64_t packedSize = 0;
70 errCode = packer.FinalizePacking(packedSize);
71 if (errCode != 0) {
72 APP_LOGE("FinalizePacking failed %{public}d", static_cast<int32_t>(errCode));
73 return false;
74 }
75 std::string originalString = outputStream.str();
76 APP_LOGD("image size:%{public}d, packedSize:%{public}d originalString size:%{public}d",
77 pixelMap->GetByteCount(), static_cast<int32_t>(packedSize), static_cast<int32_t>(originalString.length()));
78 // to base64
79 if (!EncodeBase64(originalString, imageInfo)) {
80 APP_LOGE("EncodeBase64 failed");
81 return false;
82 }
83 APP_LOGD("end");
84 return true;
85 }
86
EncodeBase64(const std::string & originalData,std::string & dstData)87 bool BundleResourceImageInfo::EncodeBase64(
88 const std::string &originalData,
89 std::string &dstData)
90 {
91 APP_LOGD("start");
92 if (originalData.empty()) {
93 APP_LOGE("originalData is empty");
94 return false;
95 }
96 int32_t srcLen = static_cast<int32_t>(originalData.length() - 1);
97 std::string base64data = IMAGE_HEADER_INFO;
98 int32_t i = 0;
99 // encode in groups of every 3 bytes
100 for (i = 0; i < srcLen - LEN_THREE; i += LEN_THREE) {
101 unsigned char byte1 = static_cast<unsigned char>(originalData[i]);
102 unsigned char byte2 = static_cast<unsigned char>(originalData[i + BIT_ONE]);
103 unsigned char byte3 = static_cast<unsigned char>(originalData[i + BIT_TWO]);
104 base64data += g_codes[byte1 >> BIT_TWO];
105 base64data += g_codes[((byte1 & 0x3) << BIT_FOUR) | (byte2 >> BIT_FOUR)];
106 base64data += g_codes[((byte2 & 0xF) << BIT_TWO) | (byte3 >> BIT_SIX)];
107 base64data += g_codes[byte3 & 0x3F];
108 }
109 // Handle the case where there is one element left
110 if (srcLen % LEN_THREE == 1) {
111 unsigned char byte1 = static_cast<unsigned char>(originalData[i]);
112 base64data += g_codes[byte1 >> BIT_TWO];
113 base64data += g_codes[(byte1 & 0x3) << BIT_FOUR];
114 base64data += '=';
115 base64data += '=';
116 } else {
117 unsigned char byte1 = static_cast<unsigned char>(originalData[i]);
118 unsigned char byte2 = static_cast<unsigned char>(originalData[i + BIT_ONE]);
119 base64data += g_codes[byte1 >> BIT_TWO];
120 base64data += g_codes[((byte1 & 0x3) << BIT_FOUR) | (byte2 >> BIT_FOUR)];
121 base64data += g_codes[(byte2 & 0xF) << BIT_TWO];
122 base64data += '=';
123 }
124 dstData = base64data;
125 APP_LOGD("end");
126 return true;
127 }
128 #endif
129
ConvertToBase64(const std::unique_ptr<uint8_t[]> originalData,const size_t length,std::string & imageInfo)130 bool BundleResourceImageInfo::ConvertToBase64(
131 const std::unique_ptr<uint8_t[]> originalData, const size_t length, std::string &imageInfo)
132 {
133 APP_LOGD("start convert to base 64");
134 if ((originalData == nullptr) || (length == 0)) {
135 APP_LOGE("originalData is nullptr or length is 0");
136 return false;
137 }
138 std::string base64data = IMAGE_HEADER_INFO;
139 size_t i = 0;
140 // encode in groups of every 3 bytes
141 for (i = 0; i < length - LEN_THREE; i += LEN_THREE) {
142 base64data += g_codes[originalData[i] >> BIT_TWO];
143 base64data += g_codes[((originalData[i] & 0x3) << BIT_FOUR) | (originalData[i + BIT_ONE] >> BIT_FOUR)];
144 base64data += g_codes[((originalData[i + BIT_ONE] & 0xF) << BIT_TWO) | (originalData[i + BIT_TWO] >> BIT_SIX)];
145 base64data += g_codes[originalData[i + BIT_TWO] & 0x3F];
146 }
147 // Handle the case where there is one element left
148 if (length % LEN_THREE == 1) {
149 base64data += g_codes[originalData[i] >> BIT_TWO];
150 base64data += g_codes[(originalData[i] & 0x3) << BIT_FOUR];
151 base64data += '=';
152 base64data += '=';
153 } else {
154 base64data += g_codes[originalData[i] >> BIT_TWO];
155 base64data += g_codes[((originalData[i] & 0x3) << BIT_FOUR) | (originalData[i + BIT_ONE] >> BIT_FOUR)];
156 base64data += g_codes[(originalData[i + BIT_ONE] & 0xF) << BIT_TWO];
157 base64data += '=';
158 }
159 imageInfo = base64data;
160 APP_LOGD("end");
161 return true;
162 }
163 } // AppExecFwk
164 } // OHOS
165