BMP转YUV
来源:互联网 发布:linux export 编辑:程序博客网 时间:2024/05/19 23:16
一、实验原理
(1)文件头 BITMAP_FILE_HEADER,包含如下内容
typedef struct tagBITMAPFILEHEADER { //0x00~0x01,说明文件的类型 WORD bfType; //0x02~0x05,说明文件的大小,用字节B为单位 DWORD bfSize; //0x06~0x07,保留,设置为0 WORD bfReserved1; //0x08~0x09,保留,设置为0 WORD bfReserved2; //0x0a~0x0d,说明从BITMAP_FILE_HEADER结构开始到实际的图像数据之间的字节偏移量 DWORD bfOffBits;} BITMAPFILEHEADER;
(2)信息头BITMAP_INFO_HEADER,包含如下内容
typedef struct tagBITMAPINFOHEADER { //0x0e~0x11,说明当前结构体所需字节数 DWORD biSize; //0x12~0x15,以像素为单位说明图像的宽度 LONG biWidth; //0x16~0x19,以像素为单位说明图像的高度 LONG biHeight; //0x1a~0x1b,说明位面数,必须为1 WORD biPlanes; //0x1c~0x1d,说明图像的位深度 WORD biBitCount; //0x1e~0x21,说明图像是否压缩及压缩类型 DWORD biCompression; //0x22~0x25,以字节为单位说明图像大小,必须是4的整数倍 DWORD biSizeImage; //0x26~0x29,目标设备的水平分辨率,像素/米 LONG biXPelsPerMeter; //0x2a~0x2d,目标设备的垂直分辨率,像素/米 LONG biYPelsPerMeter; //0x2e~0x31,说明图像实际用到的颜色数,如果为0,则颜色数为2的biBitCount次方 DWORD biClrUsed; //0x32~0x35,说明对图像显示有重要影响的颜色索引的数目,如果是0,表示都重要。 DWORD biClrImportant;} BITMAPINFOHEADER;
(3)bmp图片基本信息
-
0x22~0x25,BMP图像大小biSizeImage可由下式计算
其中,cx,cy表示水平和垂直方向的像素数。
另外,BMP文件的末尾两个字节是保留位,无论图像是什么这两个字节都为0,因此最后计算结果还要加上2字节。图像大小biSizeImage+字节偏移量bfOffBits=文件大小bfSize。
二、程序过程
(1)——–main_bmp2yuv.cpp——–
int main(int argc, char** argv){ //设置命令行参数 char* bmpFileName = argv[1]; char* yuvFileName = argv[2]; //打开文件 FILE* bmpFile = fopen(bmpFileName, "rb"); if (bmpFile == NULL) { printf("Cannot open the BMP file.\n"); exit(1); } else { printf("The BMP file is %s\n", bmpFileName); } FILE* yuvFile = fopen(yuvFileName, "wb"); if (yuvFile == NULL) { printf("Cannot open the YUV file.\n"); exit(1); } else { printf("The YUV file is %s\n", yuvFileName); } //读取BMP文件头,信息头,读取错误时的处理代码 BITMAPFILEHEADER file_header; BITMAPINFOHEADER info_header; if (fread(&file_header, sizeof(BITMAPFILEHEADER), 1, bmpFile) != 1) if (file_header.bfType != 0x4D42) { printf("Not BMP file.\n"); exit(1); } if (fread(&info_header, sizeof(BITMAPINFOHEADER), 1, bmpFile) != 1) { printf("read info header error!"); exit(0); }//结束读取BMP文件头 //读取图像尺寸 int width = info_header.biWidth; int height = info_header.biHeight; //开辟缓冲区 buf u_int8_t* yBuf = (u_int8_t*)malloc(height*width); u_int8_t* uBuf = (u_int8_t*)malloc(height*width / 4); u_int8_t* vBuf = (u_int8_t*)malloc(height*width / 4); u_int8_t* rgbBuf = (u_int8_t*)malloc(height*width * 3); if (yBuf == NULL || uBuf == NULL || vBuf == NULL || rgbBuf == NULL) { printf("Not enough memory\n"); exit(1); } //BMP与RGB的转换,得到RGB数据 if (BMP2RGB(file_header, info_header, bmpFile, rgbBuf)) { printf("BMP2RGB error\n"); exit(1); } //RGB与YUV的转换,得到YUV数据 int flip = 0; /*读取到的图像数据是倒序存放的,flip=0保证了RGB2YUV可以正确地对其转换*/ if (RGB2YUV(width, height, rgbBuf, yBuf, uBuf, vBuf, flip)) { printf("RGB2YUV error\n"); exit(1); } //将yuv按顺序写入yuvfile文件 fwrite(yBuf, 1, width * height, yuvFile); fwrite(uBuf, 1, (width * height) / 4, yuvFile); fwrite(vBuf, 1, (width * height) / 4, yuvFile); //打印宽高,方便yuv观看程序打开 printf("width is %i", width); printf("\n"); printf("heightis %i", height); printf("\n"); //清理内存 free(rgbBuf); free(yBuf); free(uBuf); free(vBuf); fclose(bmpFile); fclose(yuvFile); return 0;}
特别:
因为bmp文件是倒序存储的。所以在读文件是应该从最后一行开始读,开始设置(!flip)=1,则执行以下条件
if (!flip) { for (j = 0; j < y_dim; j ++) { y = y_buffer + (y_dim - j - 1) * x_dim; u = u_buffer + (y_dim - j - 1) * x_dim; v = v_buffer + (y_dim - j - 1) * x_dim; for (i = 0; i < x_dim; i ++) { g = b + 1; r = b + 2; *y = (unsigned char)( RGBYUV02990[*r] + RGBYUV05870[*g] + RGBYUV01140[*b]); *u = (unsigned char)(- RGBYUV01684[*r] - RGBYUV03316[*g] + (*b)/2 + 128); *v = (unsigned char)( (*r)/2 - RGBYUV04187[*g] - RGBYUV00813[*b] + 128); b += 3; y ++; u ++; v ++; } } }
重点解释:假设图片是5*3的像素矩阵最后一行的地址为y_buffer+(3-1)*5
抽象成宽高分别x_dim、y_dim的循环则为:
y = y_buffer + (y_dim - j - 1) * x_dim;u = u_buffer + (y_dim - j - 1) * x_dim;v = v_buffer + (y_dim - j - 1) * x_dim;
(2)BMP2RGB()函数
1.rgb的位数为24(8,8,8)
//确定像素的实际点阵数 w = (info_h.biWidth*info_h.biBitCount + 31) / 32 * 4;//w为实际一行的字节数 h = info_h.biHeight;//h为列数 //开辟实际字节数量的缓冲区,读数据,一次读取一个字节 u_int8_t* dataBuf = (u_int8_t*)malloc(w*h); /*使用文件头的字节偏移属性bfOffBits 直接把文件指针定位到像素值数据的起始 */ fseek(pFile, file_h.bfOffBits, 0); fread(dataBuf, 1, w*h, pFile); unsigned char* data = dataBuf; unsigned char* rgb = rgbBuf; //开始写入rgb int i, j; for (j = 0; j < h; j++)//j控制行循环 { for (i = 0; i < w; i += 3)//i控制列循环 { *rgb = data[i + w*j];//B *(rgb + 1) = data[i + w*j + 1];//G *(rgb + 2) = data[i + w*j + 2];//R rgb += 3; } } //释放内存 free(dataBuf); return 0;}
实验结果:rgb的位数为24
- 补充说明
- fopen()vs2013提示安全错误解决办法:打开文件的属性页,单击“预处理器”将“_CRT_SECURE_NO_WARNINGS”复制在“预处理器定义中’,然后确定再单击应用即可。
0 0
- BMP转YUV
- BMP转yuV
- yuv转bmp说明
- yuv转rgb写入bmp
- BMP 转 YUV (BMP2YUV)
- BMP 转 YUV (BMP2YUV)
- BMP 转 YUV (BMP2YUV)
- yuv转bmp说明2
- BMP 转 YUV (BMP2YUV)+ YUV 转RGB
- bmp转YUV RGB转YUV HM学习
- BMP 转 YUV (BMP2YUV)+ YUV 转RGB
- 一个yuv转bmp的程序
- bmp转yuv格式的视频
- 数据压缩原理与应用 BMP转YUV
- 数据压缩实验报告2-bmp转yuv
- 数据压缩实验二:BMP转YUV
- test_02:BMP to YUV
- bmp和yuv格式
- 把数据量大导出 放入多个excel 然后压缩成zip文件,导出
- 手机无法连接Tomcat服务器——菜鸟坑
- A星算法
- Maven管理SSM框架的pom.xml文件配置(自动下载所依赖的jar包)
- 运行adb devices的时候出现adb server version (31) doesn't match this client (39);
- BMP转YUV
- js学习记录10
- Android笔记——Button点击事件的几种写法
- Java常用加密算法工具类
- Setting MySQL INNODB Compression KEY_BLOCK_SIZE
- C-socket编程-多进程版并发服务器
- vue仿163musicPC端
- spring源码学习之:xml配置文件标签自定义
- Android-taskAffinity