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