1 /*
2 * Copyright (c) 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 "loadbmp_test.h"
17 #include <stdio.h>
18 #include <stdint.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <limits.h>
22 #include <sys/types.h>
23 #include <unistd.h>
24 #include "securec.h"
25 #include "hdf_log.h"
26 #include "display_type.h"
27
28 #define EOK 0
29
30 OsdCompInfo g_osdCompInfo[OSD_COLOR_FMT_BUTT] = {
31 {0, 4, 4, 4}, /* RGB444 */
32 {4, 4, 4, 4}, /* ARGB4444 */
33 {0, 5, 5, 5}, /* RGB555 */
34 {0, 5, 6, 5}, /* RGB565 */
35 {1, 5, 5, 5}, /* ARGB1555 */
36 {0, 0, 0, 0}, /* RESERVED */
37 {0, 8, 8, 8}, /* RGB888 */
38 {8, 8, 8, 8} /* ARGB8888 */
39 };
40
OsdMakeColorU16(uint8_t r,uint8_t g,uint8_t b,OsdCompInfo compinfo)41 static uint16_t OsdMakeColorU16(uint8_t r, uint8_t g, uint8_t b, OsdCompInfo compinfo)
42 {
43 uint8_t r1;
44 uint8_t g1;
45 uint8_t b1;
46 uint16_t pixel = 0;
47 uint32_t tmp = 15; // 16bit color
48
49 r1 = g1 = b1 = 0;
50 r1 = r >> (EIGHT_BITS_PER_PIXEL - compinfo.rLen);
51 g1 = g >> (EIGHT_BITS_PER_PIXEL - compinfo.gLen);
52 b1 = b >> (EIGHT_BITS_PER_PIXEL - compinfo.bLen);
53 while (compinfo.aLen != 0) {
54 pixel |= (1 << tmp);
55 tmp--;
56 compinfo.aLen--;
57 }
58
59 pixel |= (r1 | (g1 << compinfo.bLen) | (b1 << (compinfo.bLen + compinfo.gLen)));
60 return pixel;
61 }
62
GetBmpInfo(const int8_t * fileName,OsdBitMapFileHeader * bmpFileHeader,OsdBitMapInfo * bmpInfo)63 int32_t GetBmpInfo(const int8_t *fileName, OsdBitMapFileHeader *bmpFileHeader, OsdBitMapInfo *bmpInfo)
64 {
65 FILE *file = NULL;
66 uint16_t bfType = 0;
67 char realPath[PATH_MAX] = {0};
68
69 if (realpath((char*)fileName, realPath) == NULL) {
70 printf("%s: file %s does not exist\n", __func__, fileName);
71 return DISPLAY_FAILURE;
72 }
73 if ((file = fopen((const char*)realPath, "rb")) == NULL) {
74 HDF_LOGE("%s: Open file failure: %s", __func__, fileName);
75 return DISPLAY_FAILURE;
76 }
77
78 (void)fread(&bfType, 1, sizeof(bfType), file);
79 if (bfType != BITMAP_FILE) {
80 HDF_LOGE("%s: not bitmap file", __func__);
81 fclose(file);
82 return DISPLAY_FAILURE;
83 }
84
85 (void)fread(bmpFileHeader, 1, sizeof(OsdBitMapFileHeader), file);
86 (void)fread(bmpInfo, 1, sizeof(OsdBitMapInfo), file);
87 fclose(file);
88
89 return DISPLAY_SUCCESS;
90 }
91
CheckBmpInfo(const OsdBitMapInfo * bmpInfo)92 static int32_t CheckBmpInfo(const OsdBitMapInfo *bmpInfo)
93 {
94 uint16_t bpp;
95
96 bpp = bmpInfo->header.bitCnt / EIGHT_BITS_PER_PIXEL;
97 if (bpp < INVALID_BITS) {
98 /* only support 1555.8888 888 bitmap */
99 HDF_LOGE("%s: bitmap format not supported", __func__);
100 return DISPLAY_FAILURE;
101 }
102
103 if (bmpInfo->header.compress != 0) {
104 HDF_LOGE("%s: not support compressed bitmap file", __func__);
105 return DISPLAY_FAILURE;
106 }
107 if (bmpInfo->header.height == 0) {
108 HDF_LOGE("%s: bmpInfo.header.height is 0", __func__);
109 return DISPLAY_FAILURE;
110 }
111 return DISPLAY_SUCCESS;
112 }
113
OpenPicFile(const int8_t * fileName,OsdBitMapFileHeader * fileHeader,OsdBitMapInfo * info)114 static FILE * OpenPicFile(const int8_t *fileName, OsdBitMapFileHeader *fileHeader, OsdBitMapInfo *info)
115 {
116 char realPath[PATH_MAX] = {0};
117 if (GetBmpInfo(fileName, fileHeader, info) < 0) {
118 return NULL;
119 }
120 if (CheckBmpInfo(info) != DISPLAY_SUCCESS) {
121 /* only support 1555.8888 888 bitmap */
122 HDF_LOGE("%s: bitmap format not supported", __func__);
123 return NULL;
124 }
125 if (realpath((char*)fileName, realPath) == NULL) {
126 printf("%s: file %s does not exist\n", __func__, fileName);
127 return NULL;
128 }
129
130 return fopen((const char*)realPath, "rb");
131 }
132
LoadPicToBuffer(const int8_t * fileName,OsdLogo * videoLogo,OsdColorFmt enFmt,uint8_t ** outBuf,uint32_t * stride)133 static int32_t LoadPicToBuffer(const int8_t *fileName, OsdLogo *videoLogo, OsdColorFmt enFmt,
134 uint8_t **outBuf, uint32_t *stride)
135 {
136 FILE *file = NULL;
137 OsdBitMapFileHeader bmpFileHeader;
138 OsdBitMapInfo bmpInfo;
139 uint64_t byteNum;
140
141 file = OpenPicFile(fileName, &bmpFileHeader, &bmpInfo);
142 if (file == NULL) {
143 HDF_LOGE("%s: Open file failure: %s", __func__, fileName);
144 return DISPLAY_FAILURE;
145 }
146 videoLogo->bpp = bmpInfo.header.bitCnt / EIGHT_BITS_PER_PIXEL;
147 videoLogo->width = bmpInfo.header.width;
148 videoLogo->height = ((bmpInfo.header.height > 0) ? bmpInfo.header.height :
149 (-bmpInfo.header.height));
150 *stride = videoLogo->width * videoLogo->bpp;
151 if ((*stride % FOUR_BITS_PER_PIXEL) != 0) {
152 *stride = (*stride & 0xfffc) + FOUR_BITS_PER_PIXEL;
153 }
154
155 byteNum = videoLogo->height * (*stride);
156 if (byteNum > UINT32_MAX) {
157 HDF_LOGE("%s: buffer size is beyond param's limit", __func__);
158 fclose(file);
159 return DISPLAY_FAILURE;
160 }
161 /* RGB8888 or RGB1555 */
162 *outBuf = (uint8_t*)malloc(byteNum);
163 if (*outBuf == NULL) {
164 HDF_LOGE("%s: not enough memory to malloc", __func__);
165 fclose(file);
166 return DISPLAY_FAILURE;
167 }
168 fseek(file, bmpFileHeader.offBits, 0);
169 if (fread((*outBuf), 1, byteNum, file) != byteNum) {
170 HDF_LOGE("%s: fread %u*%u error", __func__, videoLogo->height, *stride);
171 fclose(file);
172 free(*outBuf);
173 *outBuf = NULL;
174 return DISPLAY_FAILURE;
175 }
176 if (enFmt >= OSD_COLOR_FMT_RGB888) {
177 videoLogo->stride = videoLogo->width * FOUR_BITS_PER_PIXEL;
178 } else {
179 videoLogo->stride = videoLogo->width * TWO_BITS_PER_PIXEL;
180 }
181 fclose(file);
182 return DISPLAY_SUCCESS;
183 }
184
LoadRgbData(OsdLogo * videoLogo,OsdColorFmt enFmt,uint32_t stride,uint8_t * origBuf)185 static void LoadRgbData(OsdLogo *videoLogo, OsdColorFmt enFmt, uint32_t stride, uint8_t *origBuf)
186 {
187 uint16_t i;
188 uint16_t j;
189 uint8_t *start = NULL;
190 uint16_t *dst = NULL;
191 uint32_t h;
192 OsdColor c;
193
194 h = videoLogo->height;
195 for (i = 0; i < videoLogo->height; i++) {
196 for (j = 0; j < videoLogo->width; j++) {
197 /* start color convert */
198 start = origBuf + ((h - 1) - i) * stride + j * videoLogo->bpp;
199 dst = (uint16_t*)(videoLogo->picBuffer + i * videoLogo->stride + j * TWO_OFFSET);
200 c.r = *(start);
201 c.g = *(start + ONE_OFFSET);
202 c.b = *(start + TWO_OFFSET);
203 *dst = OsdMakeColorU16(c.r, c.g, c.b, g_osdCompInfo[enFmt]);
204 }
205 }
206 }
207
LoadData(OsdLogo * videoLogo,OsdColorFmt enFmt,uint32_t stride,uint8_t * origBuf)208 static int32_t LoadData(OsdLogo *videoLogo, OsdColorFmt enFmt, uint32_t stride, uint8_t *origBuf)
209 {
210 int32_t ret;
211 uint16_t i;
212 uint16_t j;
213 uint32_t h;
214
215 (void)enFmt;
216 h = videoLogo->height;
217 for (i = 0; i < videoLogo->height; i++) {
218 for (j = 0; j < videoLogo->width; j++) {
219 ret = memcpy_s((videoLogo->picBuffer + i * videoLogo->stride + j * FOUR_BITS_PER_PIXEL), videoLogo->len,
220 (origBuf + ((h - 1) - i) * stride + j * videoLogo->bpp), videoLogo->bpp);
221 if (ret != EOK) {
222 HDF_LOGE("%s: file: %s, line: %d, memcpy_s failure", __func__, __FILE__, __LINE__);
223 return DISPLAY_FAILURE;
224 }
225 *(videoLogo->picBuffer + i * videoLogo->stride + j * FOUR_BITS_PER_PIXEL + THREE_BITS_PER_PIXEL) = 0xff;
226 }
227 }
228 return DISPLAY_SUCCESS;
229 }
230
Copy3BitsByFmt(OsdLogo * videoLogo,OsdColorFmt enFmt,uint32_t stride,uint8_t * origBuf)231 static int32_t Copy3BitsByFmt(OsdLogo *videoLogo, OsdColorFmt enFmt, uint32_t stride, uint8_t *origBuf)
232 {
233 int32_t ret = DISPLAY_SUCCESS;
234
235 switch (enFmt) {
236 case OSD_COLOR_FMT_RGB444:
237 case OSD_COLOR_FMT_RGB555:
238 case OSD_COLOR_FMT_RGB565:
239 case OSD_COLOR_FMT_RGB1555:
240 case OSD_COLOR_FMT_RGB4444:
241 /* start color convert */
242 LoadRgbData(videoLogo, enFmt, stride, origBuf);
243 break;
244 case OSD_COLOR_FMT_RGB888:
245 case OSD_COLOR_FMT_RGB8888:
246 ret = LoadData(videoLogo, enFmt, stride, origBuf);
247 break;
248 default:
249 HDF_LOGE("%s: file: %s, line: %d, no such format", __func__, __FILE__, __LINE__);
250 return DISPLAY_FAILURE;
251 }
252 return ret;
253 }
254
Copy2BitsAnd4Bits(OsdLogo * videoLogo,uint32_t stride,uint8_t * origBuf)255 static int32_t Copy2BitsAnd4Bits(OsdLogo *videoLogo, uint32_t stride, uint8_t *origBuf)
256 {
257 int32_t ret;
258 uint16_t i;
259 uint16_t j;
260 uint8_t *pRGBBuf;
261
262 pRGBBuf = videoLogo->picBuffer;
263 for (i = 0; i < videoLogo->height; i++) {
264 for (j = 0; j < videoLogo->width; j++) {
265 ret = memcpy_s((pRGBBuf + i * videoLogo->stride + j * videoLogo->bpp), videoLogo->len,
266 (origBuf + ((videoLogo->height - 1) - i) * stride + j * videoLogo->bpp), videoLogo->bpp);
267 if (ret != EOK) {
268 HDF_LOGE("%s: file: %s, line: %d, memcpy_s failure", __func__, __FILE__, __LINE__);
269 return DISPLAY_FAILURE;
270 }
271 }
272 }
273 return DISPLAY_SUCCESS;
274 }
275
LoadBMPEx(const int8_t * fileName,OsdLogo * videoLogo,OsdColorFmt enFmt)276 static int32_t LoadBMPEx(const int8_t *fileName, OsdLogo *videoLogo, OsdColorFmt enFmt)
277 {
278 int32_t ret;
279 uint32_t stride;
280 uint8_t *origBmpBuf = NULL;
281
282 ret = LoadPicToBuffer(fileName, videoLogo, enFmt, &origBmpBuf, &stride);
283 if (ret != DISPLAY_SUCCESS) {
284 HDF_LOGE("%s: LoadPicToBuffer failure", __func__);
285 return DISPLAY_FAILURE;
286 }
287 if (videoLogo->bpp == THREE_BITS_PER_PIXEL) {
288 ret = Copy3BitsByFmt(videoLogo, enFmt, stride, origBmpBuf);
289 if (ret != DISPLAY_SUCCESS) {
290 HDF_LOGE("%s: Copy3BitsByFmt failure", __func__);
291 }
292 } else if ((videoLogo->bpp == TWO_BITS_PER_PIXEL) || (videoLogo->bpp == FOUR_BITS_PER_PIXEL)) {
293 ret = Copy2BitsAnd4Bits(videoLogo, stride, origBmpBuf);
294 if (ret != DISPLAY_SUCCESS) {
295 HDF_LOGE("%s: Copy2BitsAnd4Bits failure", __func__);
296 free(origBmpBuf);
297 return ret;
298 }
299 }
300 free(origBmpBuf);
301 return DISPLAY_SUCCESS;
302 }
303
LoadImageEx(const int8_t * fileName,OsdLogo * videoLogo,OsdColorFmt enFmt)304 static int32_t LoadImageEx(const int8_t *fileName, OsdLogo *videoLogo, OsdColorFmt enFmt)
305 {
306 char *ext = strrchr((const char *)fileName, '.');
307
308 if (ext == NULL) {
309 HDF_LOGE("%s: LoadImageEx error", __func__);
310 return DISPLAY_FAILURE;
311 }
312
313 ext = ext + 1;
314 if (strcmp(ext, "bmp") == 0) {
315 if (LoadBMPEx(fileName, videoLogo, enFmt) != 0) {
316 HDF_LOGE("%s: LoadBMPEx error", __func__);
317 return DISPLAY_FAILURE;
318 }
319 } else {
320 HDF_LOGE("%s: not supported image file", __func__);
321 return DISPLAY_FAILURE;
322 }
323
324 return DISPLAY_SUCCESS;
325 }
326
CreateSurfaceByBitMap(const int8_t * fileName,OsdSurface * pstSurface,uint8_t * virAddr,uint32_t len)327 int32_t CreateSurfaceByBitMap(const int8_t *fileName, OsdSurface *pstSurface, uint8_t *virAddr, uint32_t len)
328 {
329 OsdLogo stLogo;
330
331 if (fileName == NULL) {
332 HDF_LOGE("%s: fileName is null", __func__);
333 return DISPLAY_FAILURE;
334 }
335 if (pstSurface == NULL) {
336 HDF_LOGE("%s: pstSurface is null", __func__);
337 return DISPLAY_FAILURE;
338 }
339 if (virAddr == NULL) {
340 HDF_LOGE("%s: virAddr is null", __func__);
341 return DISPLAY_FAILURE;
342 }
343 (void)memset_s(&stLogo, sizeof(OsdLogo), 0, sizeof(OsdLogo));
344 stLogo.picBuffer = virAddr;
345 stLogo.len = len;
346 if (LoadImageEx(fileName, &stLogo, pstSurface->colorFmt) < 0) {
347 HDF_LOGE("%s: load bmp error", __func__);
348 return DISPLAY_FAILURE;
349 }
350 pstSurface->height = stLogo.height;
351 pstSurface->width = stLogo.width;
352 pstSurface->stride = stLogo.stride;
353 return DISPLAY_SUCCESS;
354 }
355