1 /*
2 * Copyright (c) 2020-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
16 #include "imgdecode/image_load.h"
17 #include "gfx_utils/file.h"
18 #include "gfx_utils/graphic_log.h"
19 #include "gfx_utils/mem_api.h"
20
21 namespace {
22 const uint8_t BITMAP_ZIP_LEN = 3;
23 const uint8_t BITMAP_MID_BIT = 1;
24 const uint8_t BITMAP_LOW_BIT = 2;
25 const uint32_t BITMAP_ZIP24_FLAG = 0x456789;
26 const uint32_t BITMAP_ZIP_FLAG = 0x23456789;
27 const uint32_t BITMAP_ALPHA_MASK = 0xFF000000;
28 const uint32_t BITMAP_MAXCON_PIXNUM = 0xCB100;
29 const uint32_t MOVE_HIGH = 16;
30 const uint32_t MOVE_LOW = 8;
31 } // namespace
32
33 namespace OHOS {
CreateImage(ImageInfo & imageInfo)34 bool ImageLoad::CreateImage(ImageInfo& imageInfo)
35 {
36 uint32_t bytePerPixel = 4;
37 ImageHeader& imageHeader = imageInfo.header;
38
39 switch (imageHeader.colorMode) {
40 case ARGB8888:
41 bytePerPixel = 4; // 4 bytes per pixel
42 break;
43 case RGB888:
44 bytePerPixel = 3; // 3 bytes per pixel
45 break;
46 case RGB565:
47 bytePerPixel = 2; // 2 bytes per pixel
48 break;
49 default:
50 GRAPHIC_LOGE("CreateImage invalid colorMode.");
51 return false;
52 }
53
54 imageInfo.dataSize = imageHeader.width * imageHeader.height * bytePerPixel;
55 imageInfo.data = static_cast<uint8_t*>(ImageCacheMalloc(imageInfo));
56 if (imageInfo.data == nullptr) {
57 GRAPHIC_LOGE("ImageCacheMalloc error.");
58 return false;
59 }
60
61 return true;
62 }
63
UncompressImageInZip(ImageInfo & imageInfo,uint8_t * buffer,uint32_t size)64 bool ImageLoad::UncompressImageInZip(ImageInfo& imageInfo, uint8_t* buffer, uint32_t size)
65 {
66 if (!CreateImage(imageInfo)) {
67 GRAPHIC_LOGE("Create image error.");
68 return false;
69 }
70
71 if (imageInfo.header.colorMode == RGB888) {
72 return Unzip24Image(buffer, size, imageInfo);
73 } else {
74 return UnzipImage(buffer, size, imageInfo);
75 }
76 }
77
UnzipImage(uint8_t * imageBuffer,uint32_t size,ImageInfo & imageInfo)78 bool ImageLoad::UnzipImage(uint8_t* imageBuffer, uint32_t size, ImageInfo& imageInfo)
79 {
80 if ((imageBuffer == nullptr) || (size == 0)) {
81 GRAPHIC_LOGE("imageHeader is null.");
82 return false;
83 }
84
85 uint32_t* source = reinterpret_cast<uint32_t*>(imageBuffer);
86 uint32_t* sourceEnd = reinterpret_cast<uint32_t*>(imageBuffer + size);
87 uint32_t* dest = nullptr;
88 uint32_t* destEnd = nullptr;
89
90 dest = reinterpret_cast<uint32_t*>(const_cast<uint8_t*>(imageInfo.data));
91 destEnd = reinterpret_cast<uint32_t*>(const_cast<uint8_t*>(imageInfo.data) + imageInfo.dataSize);
92
93 while ((source < sourceEnd) && (dest < destEnd)) {
94 if (*source != BITMAP_ZIP_FLAG) {
95 *dest++ = *source++;
96 } else {
97 source++;
98 uint32_t value = *source++;
99 uint32_t count = *source++;
100 if (destEnd < count + dest) {
101 break;
102 }
103
104 while (count--) {
105 *dest++ = value;
106 }
107 }
108 }
109
110 if (dest == destEnd) {
111 return true;
112 }
113 ImageCacheFree(imageInfo);
114 imageInfo.data = nullptr;
115 return false;
116 }
117
Unzip24Image(uint8_t * imageBuffer,uint32_t size,ImageInfo & imageInfo)118 bool ImageLoad::Unzip24Image(uint8_t* imageBuffer, uint32_t size, ImageInfo& imageInfo)
119 {
120 if ((imageBuffer == nullptr) || (size == 0)) {
121 GRAPHIC_LOGE("imageHeader is null.");
122 return false;
123 }
124
125 uint8_t* source = reinterpret_cast<uint8_t*>(imageBuffer);
126 uint8_t* sourceEnd = reinterpret_cast<uint8_t*>(imageBuffer + size);
127 uint32_t* dest = reinterpret_cast<uint32_t*>(const_cast<uint8_t*>(imageInfo.data));
128 uint32_t* destEnd = reinterpret_cast<uint32_t*>(const_cast<uint8_t*>(imageInfo.data) + imageInfo.dataSize);
129 while ((source < sourceEnd) && (dest < destEnd)) {
130 // Little endian
131 uint32_t value = ((*source)) + (*(source + BITMAP_MID_BIT) << MOVE_LOW)
132 + (*(source + BITMAP_LOW_BIT) << MOVE_HIGH);
133 source = source + BITMAP_ZIP_LEN;
134 if (value != BITMAP_ZIP24_FLAG) {
135 *dest = value | BITMAP_ALPHA_MASK;
136 dest++;
137 } else {
138 value = ((*source)) + (*(source + BITMAP_MID_BIT) << MOVE_LOW) + (*(source + BITMAP_LOW_BIT) << MOVE_HIGH);
139 source = source + BITMAP_ZIP_LEN;
140
141 uint32_t count = ((*source)) + (*(source + BITMAP_MID_BIT) << MOVE_LOW)
142 + (*(source + BITMAP_LOW_BIT) << MOVE_HIGH);
143 source = source + BITMAP_ZIP_LEN;
144
145 if (count > BITMAP_MAXCON_PIXNUM) {
146 *dest = BITMAP_ZIP24_FLAG | BITMAP_ALPHA_MASK;
147 dest++;
148 *dest = value | BITMAP_ALPHA_MASK;
149 dest++;
150 *dest = count | BITMAP_ALPHA_MASK;
151 dest++;
152 continue;
153 }
154 if (static_cast<uintptr_t>(destEnd - dest) < static_cast<uintptr_t>(count)) {
155 break;
156 }
157 while (count--) {
158 *dest = value | BITMAP_ALPHA_MASK;
159 dest++;
160 }
161 }
162 }
163
164 if (dest == destEnd) {
165 return true;
166 }
167 ImageCacheFree(imageInfo);
168 imageInfo.data = nullptr;
169 return false;
170 }
171
UnZip2ImageInfo(ImageInfo & imageInfo,uint8_t * buffer,uint32_t size)172 bool ImageLoad::UnZip2ImageInfo(ImageInfo& imageInfo, uint8_t* buffer, uint32_t size)
173 {
174 switch (imageInfo.header.compressMode) {
175 case COMPRESS_MODE__ZIP_ALG:
176 return UncompressImageInZip(imageInfo, buffer, size);
177 default:
178 return false;
179 }
180 }
181
GetImageInfo(int32_t fd,uint32_t size,ImageInfo & imageInfo)182 bool ImageLoad::GetImageInfo(int32_t fd, uint32_t size, ImageInfo& imageInfo)
183 {
184 if (size == 0) {
185 return false;
186 }
187
188 uint8_t* buffer = reinterpret_cast<uint8_t*>(UIMalloc(size));
189 if (buffer == nullptr) {
190 return false;
191 }
192
193 if (read(fd, buffer, size) != static_cast<int32_t>(size)) {
194 UIFree(buffer);
195 GRAPHIC_LOGE("SeekImageFile error.");
196 return false;
197 }
198 bool ret = UnZip2ImageInfo(imageInfo, buffer, size);
199 UIFree(buffer);
200 return ret;
201 }
202 } // namespace OHOS
203