#include #include #include #include #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; }