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 30OsdCompInfo 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 41static 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 63int32_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 92static 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 114static 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 133static 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 185static 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 208static 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 231static 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 255static 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 276static 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 304static 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 327int32_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