此代码的功能是传入BMP格式的数据,传出提取的RGB数据。BMP图像支持8bit、16bit、24bit、32bit的格式,得到的都是24bit的RGB格式图像,如果想得到YUV格式的图像,可以将得到RGB再转为YUV格式。RGB转YUV格式参考博客《C语言实现RGB packet格式转YUV(NV21)格式》。
//BMP图片的压缩方式 #define BI_RGB (0) #define BI_BITFIELDS (3) //RGB555的掩码 #define RGB555_RED_MASK (31744) #define RGB555_GREEN_MASK (992) #define RGB555_BLUE_MASK (31) //RGB565的掩码 #define RGB565_RED_MASK (63488) #define RGB565_GREEN_MASK (2016) #define RGB565_BLUE_MASK (31) //BMP图片的像素位数 #define BMP_8_BIT (8) #define BMP_16_BIT (16) #define BMP_24_BIT (24) #define BMP_32_BIT (32) //16位BMP图片从文件头到图像数据的偏移量 #define BMP_16_BIT_BI_BITFIELDS_OFFSET (66) #define BMP_16_BIT_BI_RGB_OFFSET (54) //8位BMP图片调色板的大小 #define BMP_8_BIT_OFFSET (1024) //BMP图片的文件头,固定14字节 #define BMP_FILE_HEADER_LENGTH (14) #define isNull(ptr) (NULL == (ptr)) #define isNotNull(ptr) (NULL != (ptr)) // BMP 文件头 typedef struct { //unsigned short bfType; // 2 unsigned long bfSize; // 4 unsigned short bfReserved1; unsigned short bfReserved2; unsigned long bfOffBits; } ClBitMapFileHeader; //BMP图片的信息头 typedef struct InfoHeader { unsigned int bisize; //信息头的大小,一般是40 int biWidth; //位图的宽 int biHeight; //位图的高 unsigned short biPlanes; //固定值1 unsigned short biBitCount; //每个像素的位数 unsigned int biCompression; //压缩方式,BI_RGB(0)为不压缩, BI_BITFIELDS(3)用于16位、32位位图 unsigned int biSizeImage; //位图全部像素占用的字节 int biXpelsPerMeter; //水平分辨率 int biYPelsPerMeter; //垂直分辨率 unsigned int biClrUsed; //位图使用的颜色数。0代表颜色数为2的biBitCount次方 unsigned int biClrImportant; //重要的颜色数,0代表所有颜色都重要 }BmpInfoHeader; /* *函数功能:将bmp图片传入,输出BGR图像,图像方向是正的 *传参: pSrcData(in) ——输入bmp图像数据 * pDstData(out) ——输出BGR图像 * pWidth(out) ——bmp图像的宽 * pHeight (out) ——bmp图像的高 * *返回值:成功返回0,失败返回-1 */ int BMPExtractBGR(char* pSrcData, char* pDstData, unsigned int *pWidth, unsigned int *pHeight) { BmpInfoHeader BmpInfoHeader; unsigned int width, height; int i, j; int offSet; int RGB24 = 0; unsigned short RGB16 = 0; int count = 0; ClBitMapFileHeader fHeader; if(isNull(pSrcData) || isNull(pDstData)) { printf("input parameter invalid\n"); return -1; } //根据前两个字节,判断是不是BMP图片 if ((pSrcData[0] != 'B') || (pSrcData[1] != 'M')) { printf( "not a bmp picture.\n"); return -1; } //获取文件头,要跳过前两个字节 memcpy(&fHeader, pSrcData + 2, sizeof(ClBitMapFileHeader)); //获取信息头 memcpy(&BmpInfoHeader, pSrcData + BMP_FILE_HEADER_LENGTH, sizeof(BmpInfoHeader)); width = BmpInfoHeader.biWidth; height = BmpInfoHeader.biHeight; //将宽高信息传递出去 *pWidth = width; *pHeight = height; printf("biBitCount = %d, bisize = %d, wxh=%dx%d, bfOffBits=%d, bfSize=%d\n", \ BmpInfoHeader.biBitCount, BmpInfoHeader.bisize, width, height, fHeader.bfOffBits, fHeader.bfSize); //判断BMP图片像素的位数 if(BmpInfoHeader.biBitCount == BMP_24_BIT) { offSet = fHeader.bfOffBits;//文件头到BGR数据的偏移量 j = 0; //读取文件的BRG数据 for(i = height - 1; i >= 0; i-- ) { memcpy(pDstData + j * width * 3, pSrcData + offSet + i * width * 3, width * 3); j++; } } else if(BmpInfoHeader.biBitCount == BMP_8_BIT) { offSet = BMP_FILE_HEADER_LENGTH + BmpInfoHeader.bisize + BMP_8_BIT_OFFSET; for(i = height - 1; i >= 0; i --) { for(j = 0; j < width; j++) { memcpy(pDstData + count * 3, pSrcData + BMP_FILE_HEADER_LENGTH + BmpInfoHeader.bisize + 4 * (int)pSrcData[offSet + i * width + j], 3); count++; } } } else if(BmpInfoHeader.biBitCount == BMP_16_BIT) { if(BmpInfoHeader.biCompression == BI_BITFIELDS) { //根据掩码判断是RGB555 if((*((int *)(pSrcData + 54)) == RGB555_RED_MASK) && (*((int *)(pSrcData + 58)) == RGB555_GREEN_MASK) \ && (*((int *)(pSrcData + 62)) == RGB555_BLUE_MASK)) { //提取BGR数据 for(i = height - 1; i >= 0; i--) { for(j = 0; j < width; j++) { RGB24 = 0; RGB16 = *((unsigned short *)(pSrcData + BMP_16_BIT_BI_BITFIELDS_OFFSET + 2 * (i * width + j))); RGB24 |= ((RGB16 & RGB555_RED_MASK) << 9) | ((RGB16 & RGB555_GREEN_MASK) << 6) | ((RGB16 & RGB555_BLUE_MASK) << 3); memcpy(pDstData + count * 3, &RGB24, 3); count++; } } } //根据掩码判断是RGB565 else if((*((int *)(pSrcData + 54)) == RGB565_RED_MASK) && (*((int *)(pSrcData + 58)) == RGB565_GREEN_MASK) \ && (*((int *)(pSrcData + 62)) == RGB565_BLUE_MASK)) { for(i = height - 1; i >= 0; i--) { for(j = 0; j < width; j++) { RGB24 = 0; RGB16 = *((unsigned short *)(pSrcData + BMP_16_BIT_BI_BITFIELDS_OFFSET + 2 * (i * width + j))); RGB24 |= ((RGB16 & RGB565_RED_MASK) << 8) | ((RGB16 & RGB565_GREEN_MASK) << 5) | ((RGB16 & RGB565_BLUE_MASK) << 3); memcpy(pDstData + count * 3, &RGB24, 3); count++; } } } } else if(BmpInfoHeader.biCompression == BI_RGB) { //提取BGR数据 for(i = height - 1; i >= 0; i--) { for(j = 0; j < width; j++) { RGB24 = 0; RGB16 = *((unsigned short *)(pSrcData + BMP_16_BIT_BI_RGB_OFFSET + 2 * (i * width + j))); RGB24 |= ((RGB16 & RGB555_RED_MASK) << 9) | ((RGB16 & RGB555_GREEN_MASK) << 6) | ((RGB16 & RGB555_BLUE_MASK) << 3); memcpy(pDstData + count * 3, &RGB24, 3); count++; } } } } else if(BmpInfoHeader.biBitCount == BMP_32_BIT) { offSet = BMP_FILE_HEADER_LENGTH + BmpInfoHeader.bisize;//文件头到BGR数据的偏移量 count = 0; for(i = height - 1; i >= 0; i--) { for(j = 0; j < width; j++) { memcpy(pDstData + 3 *count, pSrcData + offSet + 4 *(i * width + j), 3); count++; } } } else { printf("not support bmp format\n"); return -1; } return 0; }
(1)BMPExtractBGR()函数功能是从BMP图像中提取出BGR数据,并将图像旋转180度,具体参数含义见注释;
(2)BMPExtractBGR()函数支持8bit、16bit、24bit、32bit的BMP图像格式;
(3)想要能直接编译成可执行程序的源码,可在我的资源里下载,该源码可直接将bmp格式转换成bgr格式
;
(3)需要完善的地方:上面的BMPExtractBGR()函数代码太多,可以将8bit、16bit、24bit、32bit的BMP格式分别拆分成单个函数,我不想花时间再调试,如果是要移植到公司的项目中,切记要拆分,不然函数代码这么长会被批斗的。
(1)在BMP的文件头中前两个字节是’BM’,是BMP图片的特征值,本来在文件头ClBitMapFileHeader结构体中应该用short变量去表示这两个字节,但实际在文件头结构体中将bfType变量注释掉,因为2个字节是没有对齐的,如果不注释掉则会因为结构体的变量对齐导致数据错位;
(2)文件头ClBitMapFileHeader结构体中使用了long型变量,long在32位机器中是4字节,在64位机器中是8字节,上面的代码只能在32位的机器上运行,在64位机器上运行会出错;
这一次的节点更新覆盖了日本、欧洲、加拿大、香港、韩国、美国、新加坡等地区,最高速度可达21.5 M/S。只需复制下方的Clash/v2ray订阅链接,在客户端添加后即可正常使用。
摘要: 大家好,今天小编关注到一个比较有意思的话题,就是关于宠物领养合同有法律效应吗的问题,于是小编就整理了5个相关介绍宠物领养合同有法律效应吗的解答,让我们一起看看吧。签订领养宠物协议靠
这一次的节点更新覆盖了韩国、美国、加拿大、香港、日本、新加坡、欧洲等地区,最高速度可达19.6 M/S。只需复制下方的Clash/v2ray订阅链接,在客户端添加后即可正常使用。
摘要: 大家好,今天小编关注到一个比较有意思的话题,就是关于中国动物疫苗生产企业排名榜的问题,于是小编就整理了2个相关介绍中国动物疫苗生产企业排名榜的解答,让我们一起看看吧。辉瑞和科兴是哪
此代码的功能是传入BMP格式的数据,传出提取的RGB数据。BMP图像支持8bit、16bit、24bit、32bit的格式,得到的都是24bit的RGB格式图像,如果想得到YUV格式的图像,可以将得到
这一次的节点更新覆盖了加拿大、新加坡、香港、日本、韩国、欧洲、美国等地区,最高速度可达18.7 M/S。只需复制下方的Clash/v2ray订阅链接,在客户端添加后即可正常使用。
摘要: 今天给各位分享佳雯宠物医院环城西路店的知识,其中也会对佳雯宠物医院环城东路分院怎么样进行解释,如果能碰巧解决你现在面临的问题,别忘了关注本站,现在开始吧!本文目录一览:1、佳雯宠.
这一次的节点更新覆盖了欧洲、香港、韩国、日本、美国、加拿大、新加坡等地区,最高速度可达18.5 M/S。只需复制下方的Clash/v2ray订阅链接,在客户端添加后即可正常使用。
这一次的节点更新覆盖了日本、欧洲、加拿大、美国、韩国、新加坡、香港等地区,最高速度可达22.4 M/S。只需复制下方的Clash/v2ray订阅链接,在客户端添加后即可正常使用。
这一次的节点更新覆盖了香港、新加坡、加拿大、日本、美国、欧洲、韩国等地区,最高速度可达20.6 M/S。只需复制下方的Clash/v2ray订阅链接,在客户端添加后即可正常使用。