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
LoadPicToBuffer(const int8_t * fileName,OsdLogo * videoLogo,OsdColorFmt enFmt,uint8_t ** outBuf,uint32_t * stride)114 static int32_t LoadPicToBuffer(const int8_t *fileName, OsdLogo *videoLogo, OsdColorFmt enFmt,
115 uint8_t **outBuf, uint32_t *stride)
116 {
117 FILE *file = NULL;
118 OsdBitMapFileHeader bmpFileHeader;
119 OsdBitMapInfo bmpInfo;
120 uint32_t h;
121 uint64_t byteNum;
122 char realPath[PATH_MAX] = {0};
123
124 if (GetBmpInfo(fileName, &bmpFileHeader, &bmpInfo) < 0) {
125 return DISPLAY_FAILURE;
126 }
127 if (CheckBmpInfo(&bmpInfo) != DISPLAY_SUCCESS) {
128 /* only support 1555.8888 888 bitmap */
129 HDF_LOGE("%s: bitmap format not supported", __func__);
130 return DISPLAY_FAILURE;
131 }
132 videoLogo->bpp = bmpInfo.header.bitCnt / EIGHT_BITS_PER_PIXEL;
133 if (realpath((char*)fileName, realPath) == NULL) {
134 printf("%s: file %s does not exist\n", __func__, fileName);
135 return DISPLAY_FAILURE;
136 }
137 if ((file = fopen((const char*)realPath, "rb")) == NULL) {
138 HDF_LOGE("%s: Open file failure: %s", __func__, fileName);
139 return DISPLAY_FAILURE;
140 }
141 videoLogo->width = bmpInfo.header.width;
142 videoLogo->height = ((bmpInfo.header.height > 0) ? bmpInfo.header.height :
143 (-bmpInfo.header.height));
144 *stride = videoLogo->width * videoLogo->bpp;
145 h = videoLogo->height;
146 if ((*stride % FOUR_BITS_PER_PIXEL) != 0) {
147 *stride = (*stride & 0xfffc) + FOUR_BITS_PER_PIXEL;
148 }
149 /* RGB8888 or RGB1555 */
150 *outBuf = (uint8_t*)malloc(videoLogo->height * (*stride));
151 if (*outBuf == NULL) {
152 HDF_LOGE("%s: not enough memory to malloc", __func__);
153 fclose(file);
154 return DISPLAY_FAILURE;
155 }
156 fseek(file, bmpFileHeader.offBits, 0);
157 byteNum = h * (*stride);
158 if (byteNum > UINT32_MAX) {
159 HDF_LOGE("%s: buffer size is beyond param's limit", __func__);
160 fclose(file);
161 free(*outBuf);
162 *outBuf = NULL;
163 return DISPLAY_FAILURE;
164 }
165 if (fread((*outBuf), 1, byteNum, file) != byteNum) {
166 HDF_LOGE("%s: fread %u*%u error", __func__, h, *stride);
167 fclose(file);
168 free(*outBuf);
169 *outBuf = NULL;
170 return DISPLAY_FAILURE;
171 }
172 if (enFmt >= OSD_COLOR_FMT_RGB888) {
173 videoLogo->stride = videoLogo->width * FOUR_BITS_PER_PIXEL;
174 } else {
175 videoLogo->stride = videoLogo->width * TWO_BITS_PER_PIXEL;
176 }
177 fclose(file);
178 return DISPLAY_SUCCESS;
179 }
180
LoadRgbData(OsdLogo * videoLogo,OsdColorFmt enFmt,uint32_t stride,uint8_t * origBuf)181 static void LoadRgbData(OsdLogo *videoLogo, OsdColorFmt enFmt, uint32_t stride, uint8_t *origBuf)
182 {
183 uint16_t i;
184 uint16_t j;
185 uint8_t *start = NULL;
186 uint16_t *dst = NULL;
187 uint32_t h;
188 OsdColor c;
189
190 h = videoLogo->height;
191 for (i = 0; i < videoLogo->height; i++) {
192 for (j = 0; j < videoLogo->width; j++) {
193 /* start color convert */
194 start = origBuf + ((h - 1) - i) * stride + j * videoLogo->bpp;
195 dst = (uint16_t*)(videoLogo->picBuffer + i * videoLogo->stride + j * TWO_OFFSET);
196 c.r = *(start);
197 c.g = *(start + ONE_OFFSET);
198 c.b = *(start + TWO_OFFSET);
199 *dst = OsdMakeColorU16(c.r, c.g, c.b, g_osdCompInfo[enFmt]);
200 }
201 }
202 }
203
LoadData(OsdLogo * videoLogo,OsdColorFmt enFmt,uint32_t stride,uint8_t * origBuf)204 static int32_t LoadData(OsdLogo *videoLogo, OsdColorFmt enFmt, uint32_t stride, uint8_t *origBuf)
205 {
206 int32_t ret;
207 uint16_t i;
208 uint16_t j;
209 uint32_t h;
210
211 (void)enFmt;
212 h = videoLogo->height;
213 for (i = 0; i < videoLogo->height; i++) {
214 for (j = 0; j < videoLogo->width; j++) {
215 ret = memcpy_s((videoLogo->picBuffer + i * videoLogo->stride + j * FOUR_BITS_PER_PIXEL), videoLogo->len,
216 (origBuf + ((h - 1) - i) * stride + j * videoLogo->bpp), videoLogo->bpp);
217 if (ret != EOK) {
218 HDF_LOGE("%s: file: %s, line: %d, memcpy_s failure", __func__, __FILE__, __LINE__);
219 return DISPLAY_FAILURE;
220 }
221 *(videoLogo->picBuffer + i * videoLogo->stride + j * FOUR_BITS_PER_PIXEL + THREE_BITS_PER_PIXEL) = 0xff;
222 }
223 }
224 return DISPLAY_SUCCESS;
225 }
226
Copy3BitsByFmt(OsdLogo * videoLogo,OsdColorFmt enFmt,uint32_t stride,uint8_t * origBuf)227 static int32_t Copy3BitsByFmt(OsdLogo *videoLogo, OsdColorFmt enFmt, uint32_t stride, uint8_t *origBuf)
228 {
229 int32_t ret = DISPLAY_SUCCESS;
230
231 switch (enFmt) {
232 case OSD_COLOR_FMT_RGB444:
233 case OSD_COLOR_FMT_RGB555:
234 case OSD_COLOR_FMT_RGB565:
235 case OSD_COLOR_FMT_RGB1555:
236 case OSD_COLOR_FMT_RGB4444:
237 /* start color convert */
238 LoadRgbData(videoLogo, enFmt, stride, origBuf);
239 break;
240 case OSD_COLOR_FMT_RGB888:
241 case OSD_COLOR_FMT_RGB8888:
242 ret = LoadData(videoLogo, enFmt, stride, origBuf);
243 break;
244 default:
245 HDF_LOGE("%s: file: %s, line: %d, no such format", __func__, __FILE__, __LINE__);
246 return DISPLAY_FAILURE;
247 }
248 return ret;
249 }
250
Copy2BitsAnd4Bits(OsdLogo * videoLogo,uint32_t stride,uint8_t * origBuf)251 static int32_t Copy2BitsAnd4Bits(OsdLogo *videoLogo, uint32_t stride, uint8_t *origBuf)
252 {
253 int32_t ret;
254 uint16_t i;
255 uint16_t j;
256 uint8_t *pRGBBuf;
257
258 pRGBBuf = videoLogo->picBuffer;
259 for (i = 0; i < videoLogo->height; i++) {
260 for (j = 0; j < videoLogo->width; j++) {
261 ret = memcpy_s((pRGBBuf + i * videoLogo->stride + j * videoLogo->bpp), videoLogo->len,
262 (origBuf + ((videoLogo->height - 1) - i) * stride + j * videoLogo->bpp), videoLogo->bpp);
263 if (ret != EOK) {
264 HDF_LOGE("%s: file: %s, line: %d, memcpy_s failure", __func__, __FILE__, __LINE__);
265 return DISPLAY_FAILURE;
266 }
267 }
268 }
269 return DISPLAY_SUCCESS;
270 }
271
LoadBMPEx(const int8_t * fileName,OsdLogo * videoLogo,OsdColorFmt enFmt)272 static int32_t LoadBMPEx(const int8_t *fileName, OsdLogo *videoLogo, OsdColorFmt enFmt)
273 {
274 int32_t ret;
275 uint32_t stride;
276 uint8_t *origBmpBuf = NULL;
277
278 ret = LoadPicToBuffer(fileName, videoLogo, enFmt, &origBmpBuf, &stride);
279 if (ret != DISPLAY_SUCCESS) {
280 HDF_LOGE("%s: LoadPicToBuffer failure", __func__);
281 return DISPLAY_FAILURE;
282 }
283 if (videoLogo->bpp == THREE_BITS_PER_PIXEL) {
284 ret = Copy3BitsByFmt(videoLogo, enFmt, stride, origBmpBuf);
285 if (ret != DISPLAY_SUCCESS) {
286 HDF_LOGE("%s: Copy3BitsByFmt failure", __func__);
287 }
288 } else if ((videoLogo->bpp == TWO_BITS_PER_PIXEL) || (videoLogo->bpp == FOUR_BITS_PER_PIXEL)) {
289 ret = Copy2BitsAnd4Bits(videoLogo, stride, origBmpBuf);
290 if (ret != DISPLAY_SUCCESS) {
291 HDF_LOGE("%s: Copy2BitsAnd4Bits failure", __func__);
292 free(origBmpBuf);
293 return ret;
294 }
295 }
296 free(origBmpBuf);
297 return DISPLAY_SUCCESS;
298 }
299
LoadImageEx(const int8_t * fileName,OsdLogo * videoLogo,OsdColorFmt enFmt)300 static int32_t LoadImageEx(const int8_t *fileName, OsdLogo *videoLogo, OsdColorFmt enFmt)
301 {
302 char *ext = strrchr((const char *)fileName, '.');
303
304 if (ext == NULL) {
305 HDF_LOGE("%s: LoadImageEx error", __func__);
306 return DISPLAY_FAILURE;
307 }
308
309 ext = ext + 1;
310 if (strcmp(ext, "bmp") == 0) {
311 if (LoadBMPEx(fileName, videoLogo, enFmt) != 0) {
312 HDF_LOGE("%s: LoadBMPEx error", __func__);
313 return DISPLAY_FAILURE;
314 }
315 } else {
316 HDF_LOGE("%s: not supported image file", __func__);
317 return DISPLAY_FAILURE;
318 }
319
320 return DISPLAY_SUCCESS;
321 }
322
CreateSurfaceByBitMap(const int8_t * fileName,OsdSurface * pstSurface,uint8_t * virAddr,uint32_t len)323 int32_t CreateSurfaceByBitMap(const int8_t *fileName, OsdSurface *pstSurface, uint8_t *virAddr, uint32_t len)
324 {
325 OsdLogo stLogo;
326
327 if (fileName == NULL) {
328 HDF_LOGE("%s: fileName is null", __func__);
329 return DISPLAY_FAILURE;
330 }
331 if (pstSurface == NULL) {
332 HDF_LOGE("%s: pstSurface is null", __func__);
333 return DISPLAY_FAILURE;
334 }
335 if (virAddr == NULL) {
336 HDF_LOGE("%s: virAddr is null", __func__);
337 return DISPLAY_FAILURE;
338 }
339 (void)memset_s(&stLogo, sizeof(OsdLogo), 0, sizeof(OsdLogo));
340 stLogo.picBuffer = virAddr;
341 stLogo.len = len;
342 if (LoadImageEx(fileName, &stLogo, pstSurface->colorFmt) < 0) {
343 HDF_LOGE("%s: load bmp error", __func__);
344 return DISPLAY_FAILURE;
345 }
346 pstSurface->height = stLogo.height;
347 pstSurface->width = stLogo.width;
348 pstSurface->stride = stLogo.stride;
349 return DISPLAY_SUCCESS;
350 }
351