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