Files
SDK_SG200x_V2/middleware/v2/sample/common/loadbmp.c
carbon 0545e9dc6d init version 2024-05-07
commit d1edce71135cc6d98c0a4b5729774542b676e769
Author: sophgo-forum-service <forum_service@sophgo.com>
Date:   Fri Mar 15 16:07:33 2024 +0800

    [fix] recommend using ssh method to clone repo.
    [fix] fix sensor driver repo branch name.
2024-05-07 19:36:36 +08:00

399 lines
9.7 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include "loadbmp.h"
/*
* The compression types supported by BMP are listed below :
* 0 - no compression
* 1 - 8 bit run length encoding
* 2 - 4 bit run length encoding
* 3 - RGB bitmap with mask
* Compression encodings for BMP files
*/
#ifndef BI_RGB
#define BI_RGB 0
#define BI_RLE8 1
#define BI_RLE4 2
#define BI_BITFIELDS 3
#endif
OSD_COMP_INFO s_OSDCompInfo[OSD_COLOR_FMT_BUTT] = {
{ 0, 4, 4, 4 }, /*RGB444*/
{ 4, 4, 4, 4 }, /*ARGB4444*/
{ 0, 5, 5, 5 }, /*RGB555*/
{ 0, 5, 6, 5 }, /*RGB565*/
{ 1, 5, 5, 5 }, /*ARGB1555*/
{ 0, 0, 0, 0 }, /*RESERVED*/
{ 0, 8, 8, 8 }, /*RGB888*/
{ 8, 8, 8, 8 } /*ARGB8888*/
};
CVI_U16 OSD_MAKECOLOR_U16(CVI_U8 r, CVI_U8 g, CVI_U8 b, OSD_COMP_INFO compinfo)
{
CVI_U8 r1, g1, b1;
CVI_U16 pixel = 0;
CVI_U32 tmp = 15;
r1 = g1 = b1 = 0;
r1 = r >> (8 - compinfo.rlen);
g1 = g >> (8 - compinfo.glen);
b1 = b >> (8 - compinfo.blen);
while (compinfo.alen) {
pixel |= (1 << tmp);
tmp--;
compinfo.alen--;
}
pixel |= (b1 | (g1 << compinfo.blen) | (r1 << (compinfo.blen + compinfo.glen)));
return pixel;
}
CVI_U16 OSD_MAKECOLOR_U16_A(CVI_U8 a, CVI_U8 r, CVI_U8 g, CVI_U8 b, OSD_COMP_INFO compinfo)
{
CVI_U8 a1, r1, g1, b1;
CVI_U16 pixel = 0;
a1 = r1 = g1 = b1 = 0;
a1 = a >> (8 - compinfo.alen);
r1 = r >> (8 - compinfo.rlen);
g1 = g >> (8 - compinfo.glen);
b1 = b >> (8 - compinfo.blen);
pixel = (b1 | (g1 << compinfo.blen) | (r1 << (compinfo.blen + compinfo.glen))
| (a1 << (compinfo.rlen + compinfo.glen + compinfo.blen)));
return pixel;
}
CVI_U8 find_bitshift(CVI_U32 mask)
{
CVI_U8 j;
for (j = 0; !((mask >> j) & 1) && j < 32; ++j)
;
return j;
}
CVI_S32 GetBmpInfo(const char *filename, OSD_BITMAPFILEHEADER *pBmpFileHeader, OSD_BITMAPINFO *pBmpInfo)
{
FILE *pFile;
CVI_U16 bfType;
if (filename == NULL) {
printf("OSD_LoadBMP: filename=NULL\n");
return -1;
}
pFile = fopen((char *)filename, "rb");
if (pFile == NULL) {
printf("Open file failed:%s!\n", filename);
return -1;
}
fread(&bfType, 1, sizeof(bfType), pFile);
if (bfType != 0x4d42) {
printf("not bitmap file\n");
fclose(pFile);
return -1;
}
/* Bitmap File Header */
fread(pBmpFileHeader, 1, sizeof(OSD_BITMAPFILEHEADER), pFile);
/* BITMAPInfo - Defines the dimension and color information for a DIBs */
fread(pBmpInfo, 1, sizeof(OSD_BITMAPINFO), pFile);
fclose(pFile);
printf("bmp width(%d) height(%d) bpp(%d) compression(%d)\n"
, pBmpInfo->bmiHeader.biWidth, pBmpInfo->bmiHeader.biHeight, pBmpInfo->bmiHeader.biBitCount
, pBmpInfo->bmiHeader.biCompression);
if (pBmpInfo->bmiHeader.biCompression == 3)
printf("bitmask a(%#x) r(%#x) g(%#x) b(%#x)\n", pBmpInfo->bitfield.a_mask
, pBmpInfo->bitfield.r_mask, pBmpInfo->bitfield.g_mask, pBmpInfo->bitfield.b_mask);
return 0;
}
int LoadBMP(const char *filename, OSD_LOGO_T *pVideoLogo, OSD_COLOR_FMT_E enFmt, CVI_BOOL update_logo)
{
FILE *pFile;
CVI_U16 i, j;
CVI_U32 w, h;
CVI_U16 Bpp;
OSD_BITMAPFILEHEADER bmpFileHeader;
OSD_BITMAPINFO bmpInfo;
CVI_U8 *pOrigBMPBuf;
CVI_U8 *pRGBBuf;
CVI_U32 stride;
CVI_U8 r, g, b, a;
CVI_U8 *pStart;
CVI_U16 *pDst;
CVI_U32 pxl;
CVI_U8 color_shifts[4] = { 0 };
if (filename == NULL) {
printf("OSD_LoadBMP: filename=NULL\n");
return -1;
}
if (GetBmpInfo(filename, &bmpFileHeader, &bmpInfo) < 0) {
return -1;
}
Bpp = bmpInfo.bmiHeader.biBitCount / 8;
switch (bmpInfo.bmiHeader.biCompression) {
case BI_RGB:
printf("Non-compressed bitmap file!\n");
break;
case BI_RLE4:
case BI_RLE8:
printf("only support non-compressed or bitfile bitmap file!\n");
return -1;
case BI_BITFIELDS:
printf("Bitfile bitmap file!\n");
if ((Bpp != 2) && (Bpp != 4)) {
printf("Compression(3):RGB bitmap bitfiled format bpp(%d) not supported!\n", Bpp);
return -1;
}
printf("bitmask a(%#x) r(%#x) g(%#x) b(%#x)\n", bmpInfo.bitfield.a_mask
, bmpInfo.bitfield.r_mask, bmpInfo.bitfield.g_mask, bmpInfo.bitfield.b_mask);
color_shifts[0] = find_bitshift(bmpInfo.bitfield.a_mask);
color_shifts[1] = find_bitshift(bmpInfo.bitfield.r_mask);
color_shifts[2] = find_bitshift(bmpInfo.bitfield.g_mask);
color_shifts[3] = find_bitshift(bmpInfo.bitfield.b_mask);
}
if (bmpInfo.bmiHeader.biHeight < 0) {
printf("bmpInfo.bmiHeader.biHeight < 0\n");
return -1;
}
if (bmpInfo.bmiHeader.biHeight < 0) {
printf("bmpInfo.bmiHeader.biHeight < 0\n");
return -1;
}
pFile = fopen((char *)filename, "rb");
if (pFile == NULL) {
printf("Open file failed:%s!\n", filename);
return -1;
}
w = bmpInfo.bmiHeader.biWidth;
h = ((bmpInfo.bmiHeader.biHeight > 0) ? bmpInfo.bmiHeader.biHeight : (-bmpInfo.bmiHeader.biHeight));
stride = w * Bpp;
/* ALIGN for 32. */
if (stride % 4) {
stride = (stride & 0xfffc) + 4;
}
if (update_logo) {
pVideoLogo->width = w;
pVideoLogo->height = h;
pVideoLogo->stride = (enFmt == OSD_COLOR_FMT_8BIT_MODE) ? w :
(enFmt >= OSD_COLOR_FMT_RGB888) ? w << 2 : w << 1;
}
/* RGB8888 or RGB1555 or 8BIT_MODE_index */
pOrigBMPBuf = (CVI_U8 *)malloc(h * stride);
if (pOrigBMPBuf == NULL) {
printf("not enough memory to malloc!\n");
fclose(pFile);
return -1;
}
pRGBBuf = pVideoLogo->pRGBBuffer;
if (h > pVideoLogo->height) {
printf("Bitmap's height(%d) is bigger than canvas's height(%d). Load bitmap error!\n", h,
pVideoLogo->height);
free(pOrigBMPBuf);
fclose(pFile);
return -1;
}
if (w > pVideoLogo->width) {
printf("Bitmap's width(%d) is bigger than canvas's width(%d). Load bitmap error!\n", w,
pVideoLogo->width);
free(pOrigBMPBuf);
fclose(pFile);
return -1;
}
fseek(pFile, bmpFileHeader.bfOffBits, 0);
if (fread(pOrigBMPBuf, 1, h * stride, pFile) != (h * stride)) {
printf("fread (%d*%d)error!line:%d\n", h, stride, __LINE__);
perror("fread:");
}
for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
if (Bpp == 3) {
switch (enFmt) {
case OSD_COLOR_FMT_RGB444:
case OSD_COLOR_FMT_RGB555:
case OSD_COLOR_FMT_RGB565:
case OSD_COLOR_FMT_RGB1555:
case OSD_COLOR_FMT_RGB4444:
/* start color convert */
pStart = pOrigBMPBuf + ((h - 1) - i) * stride + j * Bpp;
pDst = (CVI_U16 *)(pRGBBuf + i * pVideoLogo->stride + j * 2);
b = *(pStart);
g = *(pStart + 1);
r = *(pStart + 2);
*pDst = OSD_MAKECOLOR_U16(r, g, b, s_OSDCompInfo[enFmt]);
break;
case OSD_COLOR_FMT_RGB888:
case OSD_COLOR_FMT_RGB8888:
memcpy(pRGBBuf + i * pVideoLogo->stride + j * 4,
pOrigBMPBuf + ((h - 1) - i) * stride + j * Bpp, Bpp);
*(pRGBBuf + i * pVideoLogo->stride + j * 4 + 3) = 0xff; /*alpha*/
break;
default:
printf("file(%s), line(%d), no such format!\n", __FILE__, __LINE__);
break;
}
} else if ((Bpp == 2) || (Bpp == 4)) {
pStart = pOrigBMPBuf + ((h - 1) - i) * stride + j * Bpp;
pDst = (CVI_U16 *)(pRGBBuf + i * pVideoLogo->stride + j * 2);
pxl = *(CVI_U32 *)pStart;
a = (pxl & bmpInfo.bitfield.a_mask) >> color_shifts[0];
r = (pxl & bmpInfo.bitfield.r_mask) >> color_shifts[1];
g = (pxl & bmpInfo.bitfield.g_mask) >> color_shifts[2];
b = (pxl & bmpInfo.bitfield.b_mask) >> color_shifts[3];
if (i == 0 && j == 0) {
printf("Func: %s, line:%d.\n", __func__, __LINE__);
printf("Bpp: %d, bmp stride: %d, Canvas stride: %d, h:%d, w:%d.\n",
Bpp, stride, pVideoLogo->stride, i, j);
}
*pDst = OSD_MAKECOLOR_U16_A(a, r, g, b, s_OSDCompInfo[enFmt]);
} else if (Bpp == 1) {
//For OSD_COLOR_FMT_8BIT_MODE case
memcpy(pRGBBuf + i * pVideoLogo->stride + j * 1,
pOrigBMPBuf + ((h - 1) - i) * stride + j * Bpp, Bpp);
} else
printf("Error Bpp: %d in Func: %s, line:%d\n", Bpp, __func__, __LINE__);
}
}
free(pOrigBMPBuf);
pOrigBMPBuf = NULL;
fclose(pFile);
return 0;
}
char *GetExtName(char *filename)
{
char *pret = NULL;
CVI_U32 fnLen;
if (filename == NULL) {
printf("filename can't be null!");
return NULL;
}
fnLen = strlen(filename);
while (fnLen) {
pret = filename + fnLen;
if (*pret == '.')
return (pret + 1);
fnLen--;
}
return pret;
}
int LoadImageEx(const char *filename, OSD_LOGO_T *pVideoLogo, OSD_COLOR_FMT_E enFmt)
{
char *ext = GetExtName((char *)filename);
if (ext == CVI_NULL) {
printf("LoadImageEx error!\n");
return -1;
}
if (strcmp(ext, "bmp") == 0) {
if (LoadBMP(filename, pVideoLogo, enFmt, CVI_TRUE) != 0) {
printf("OSD_LoadBMP error!\n");
return -1;
}
} else {
printf("not supported image file!\n");
return -1;
}
return 0;
}
int LoadCanvasEx(const char *filename, OSD_LOGO_T *pVideoLogo, OSD_COLOR_FMT_E enFmt)
{
char *ext = GetExtName((char *)filename);
if (ext == CVI_NULL) {
printf("LoadCanvasEx error!\n");
return -1;
}
if (strcmp(ext, "bmp") == 0) {
if (LoadBMP(filename, pVideoLogo, enFmt, CVI_FALSE) != 0) {
printf("OSD_LoadBMP error!\n");
return -1;
}
} else {
printf("not supported image file!\n");
return -1;
}
return 0;
}
CVI_S32 CreateSurfaceByBitMap(const CVI_CHAR *pszFileName, OSD_SURFACE_S *pstSurface, CVI_U8 *pu8Virt)
{
OSD_LOGO_T stLogo;
stLogo.pRGBBuffer = pu8Virt;
if (LoadImageEx(pszFileName, &stLogo, pstSurface->enColorFmt) < 0) {
printf("load bmp error!\n");
return -1;
}
pstSurface->u16Height = stLogo.height;
pstSurface->u16Width = stLogo.width;
pstSurface->u16Stride = stLogo.stride;
return 0;
}
CVI_S32 CreateSurfaceByCanvas(const CVI_CHAR *pszFileName, OSD_SURFACE_S *pstSurface, CVI_U8 *pu8Virt
, CVI_U32 u32Width, CVI_U32 u32Height, CVI_U32 u32Stride)
{
OSD_LOGO_T stLogo;
stLogo.pRGBBuffer = pu8Virt;
stLogo.width = u32Width;
stLogo.height = u32Height;
stLogo.stride = u32Stride;
if (LoadCanvasEx(pszFileName, &stLogo, pstSurface->enColorFmt) < 0) {
printf("load bmp error!\n");
return -1;
}
pstSurface->u16Height = u32Height;
pstSurface->u16Width = u32Width;
pstSurface->u16Stride = u32Stride;
return 0;
}