一、BMP文件的组成结构

BMP(全称Bitmap)是Windows操作系统中的标准图像文件格式,可以分成两类:设备相关位图(DDB)和设备无关位图(DIB),使用广泛。它采用位映射存储格式,除了图像深度可选以外,在绝大多数应用中不采用其他任何压缩,因此,BMP文件所占用的空间很大。BMP文件的图像深度可选lbit、4bit、8bit、16bit及24bit。图像的扫描方式是按从左到右、从下到上的顺序。由于BMP文件格式是Windows环境中交换与图有关的数据的一种标准,因此在Windows环境中运行的图形图像软件都支持BMP图像格式。

典型的BMP图像文件组成
位图头文件数据结构,它包含BMP图像文件的类型、显示内容等信息
位图信息数据结构,它包含有BMP图像的宽、高、压缩方法,以及定义颜色等信息

调色板,这个部分是可选的;

有些位图需要调色板,有些位图,比如真彩色图(24位的BMP)就不需要调色板

位图数据,这部分的内容根据BMP位图使用的位数不同而不同,在24位图中直接使用RGB,而其他的小于24位的使用调色板中颜色索引值。

1. 位图文件头主要包括:

2.位图信息头主要包括:

3.调色板实际上是一个数组,它所包含的元素与位图所具有的颜色数相同,决定于biClrUsed和biBitCount字段。数组中每个元素的类型是一个RGBQUAD结构。真彩色无调色板部分。

4.紧跟在调色板之后的是图像数据字节阵列。对于用到调色板的位图,图像数据就是该像素颜色在调色板中的索引值(逻辑色)。对于真彩色图,图像数据就是实际的R、G、B值。

图像的每一扫描行由表示图像像素的连续的字节组成,每一行的字节数取决于图像的颜色数目和用像素表示的图像宽度。规定每一扫描行的字节数必须是4的整倍数,也就是DWORD对齐的。

扫描行是由底向上存储的,这就是说,阵列中的第一个字节表示位图左下角的像素,而最后一个字节表示位图右上角的像素。

注:本次实验以24bit的真彩色图像为例,故不需要调色板。

二、字节序

不同的计算机系统采用不同的字节序存储数据,同样一个4字节的32位整数,在内存中存储的方式不同。字节序分为小尾字节序(Little Endian)和大尾字节序(Big Endian)。Intel处理器大多数使用小尾字节序,Motorola处理器大多数使用大尾(Big Endian)字节序。

小尾就是低位字节排放在内存的低端,高位字节排放在内存的高端,即所谓的“低位在前,高位在后”。大尾就是高位字节排放在内存的低端,低位字节排放在内存的高端,即所谓的“高位在前,低位在后”。TCP/IP各层协议将字节序定义为大尾,因此TCP/IP协议中使用的字节序通常称之为网络字节序。

BMP文件存储数据时,图像的扫描方式是按从左到右、从下到上的顺序。而RGB文件存储数据时,图像的扫描方式是按从左到右、从上到下的顺序。因此在将BMP文件格式转化为RGB文件格式时,要注意“倒叙读写”的问题。

//从24bit的bmp提取rgb数据时 倒序转正序写入缓存区for (int i = 0; i < height; i++){for (int j = 0; j < width * 3; j++){*(rgb + (height - 1 - i) * width * 3 + j) = *tmp_rgb;tmp_rgb++;}}

三、实验核心代码

1. 头文件head.h定义

#pragma once
#include<windows.h>
#define uchar unsigned charint rgb2yuv(int x_dim, int y_dim, void* bmp, void* y_out, void* u_out, void* v_out);
int bmp2rgb(int width, int height, FILE* bmpFile, unsigned char* rgb);
void InitLookupTable();

在<windows.h> 头文件中,定义BITMAPFILEHEADER 结构体。

2.main函数定义变量,指针和输出文件。

//定义变量BITMAPFILEHEADER FILE_header;BITMAPINFOHEADER INFO_header;//缓冲buffer,用来存储数据,完成读写操作FILE* bmpFile;FILE* yuvFile;uchar* rgbBuf;uchar* yBuf;uchar* uBuf;uchar* vBuf;//存储图片宽和高int FWidth;int FHeight;//创建指向图片的指针const int picNum = 7;const char* bmpFileName[picNum] = { "djr0.bmp","djr1.bmp","djr2.bmp","djr3.bmp","djr4.bmp","djr5.bmp","djr6.bmp" };const char* yuvFileName = "result.yuv";//创建新的输出文件fopen_s(&yuvFile, yuvFileName, "wb");

3.逐个对bmp图片进行转换处理

(1)打开后根据文件头读取判断

     //打开每个bmp文件fopen_s(&bmpFile, bmpFileName[i], "rb");//读取bmp文件头if (fread(&FILE_header, sizeof(BITMAPFILEHEADER), 1, bmpFile) != 1){cout << "read file header error!" << endl;exit(0);}else {cout << "read file header success!" << endl;}//判断是否是bmp文件类型if (FILE_header.bfType != 0x4D42) //此处是bmp的小端模式的数据{cout << "not the bmpFile!" << endl;exit(0);}else {cout << "this is a bmp file!" << endl;}

(2)根据bmp信息头,直接调用结构体实例,读取rgb数据

        //读取bmp信息头if (fread(&INFO_header, sizeof(BITMAPINFOHEADER), 1, bmpFile) != 1){cout << "read info header error!" << endl;exit(0);}else {cout << "read info header success!" << endl;}//通过结构体实例的成员函数,来调用参数FWidth = INFO_header.biWidth;FHeight = INFO_header.biHeight;//给操作指针分配内存空间rgbBuf = (uchar*)malloc(FWidth * FHeight * 3);yBuf = (uchar*)malloc(FWidth * FHeight);uBuf = (uchar*)malloc(FWidth * FHeight / 4);vBuf = (uchar*)malloc(FWidth * FHeight / 4);//读取bmp文件的rgb数据bmp2rgb(FWidth, FHeight, bmpFile, rgbBuf);//测试rgb数据是否传输成功//fwrite(rgbBuf, 1, FHeight * FWidth * 3, yuvFile);

如果直接用YUVplayer打开传输的rgb文件,是无法正常显示图片。

(3)倒序读取后的rgb,转换成yuv数据。

int rgb2yuv(int width, int height, void* bmp, void* y_out, void* u_out, void* v_out)
{//变量定义static int init_Done = 0;uchar* r, * g, * b;uchar* y, * u, * v;uchar* y_buf, * u_buf, * v_buf;uchar* sub_u_buf, * sub_v_buf;uchar* s_u, * s_v;uchar* cu1, * cu2, * cv1, * cv2;long size;//定义查找表算if (init_Done == 0){InitLookupTable();init_Done = 1;}//操作指针分配内存空间size = width * height;y_buf = (uchar*)y_out;sub_u_buf = (uchar*)u_out;sub_v_buf = (uchar*)v_out;u_buf = (uchar*)malloc(size * sizeof(uchar));v_buf = (uchar*)malloc(size * sizeof(uchar));//rgb2yuvb = (uchar*)bmp;y = y_buf;u = u_buf;v = v_buf;for (long i = 0; i < size; i++){g = b + 1;r = b + 2;*y = (uchar)(RGBYUV02990[*r] + RGBYUV05870[*g] + RGBYUV01140[*b]);*u = (uchar)(-RGBYUV01684[*r] - RGBYUV03316[*g] + (*b) / 2 + 128);*v = (uchar)((*r) / 2 - RGBYUV04187[*g] - RGBYUV00813[*b] + 128);  //限定yuv的范围,防止溢出if (*y < 16) *y = 16;if (*y > 235) *y = 235;if (*u < 16) *u = 16;if (*u > 240) *u = 240;if (*v < 16) *v = 16;if (*v > 240) *v = 240;b += 3;y++;u++;v++;}//转换后的数组是4:4:4格式,采样成4:2:2格式   for (long j = 0; j < height / 2; j++){s_u = sub_u_buf + j * width / 2;s_v = sub_v_buf + j * width / 2;//在没采样的数据中操作位置的指针cu1 = u_buf + 2 * j * width;cv1 = v_buf + 2 * j * width;cu2 = u_buf + (2 * j + 1) * width;cv2 = v_buf + (2 * j + 1) * width;//使用均值进行赋值for (long i = 0; i < width / 2; i++){*s_u = (*cu1 + *(cu1 + 1) + *cu2 + *(cu2 + 1)) / 4;*s_v = (*cv1 + *(cv1 + 1) + *cv2 + *(cv2 + 1)) / 4;s_u++;s_v++;cu1 += 1;cv1 += 2;cu2 += 2;cv2 += 2;}}//释放临时变量free(u_buf);free(v_buf);return 0;
}

其中定义了查找表,采用部分查找表法,可以提高运行效率

static float RGBYUV02990[256], RGBYUV05870[256], RGBYUV01140[256];
static float RGBYUV01684[256], RGBYUV03316[256];
static float RGBYUV04187[256], RGBYUV00813[256];void InitLookupTable()
{int i;for (i = 0; i < 256; i++) RGBYUV02990[i] = (float)0.2990 * i;for (i = 0; i < 256; i++) RGBYUV05870[i] = (float)0.5870 * i;for (i = 0; i < 256; i++) RGBYUV01140[i] = (float)0.1140 * i;for (i = 0; i < 256; i++) RGBYUV01684[i] = (float)0.1684 * i;for (i = 0; i < 256; i++) RGBYUV03316[i] = (float)0.3316 * i;for (i = 0; i < 256; i++) RGBYUV04187[i] = (float)0.4187 * i;for (i = 0; i < 256; i++) RGBYUV00813[i] = (float)0.0813 * i;
}

4.设置每个画面出现的帧数,循环写入文件

//命令行中设置每幅图循环次数int k;cout << "Enter the number of picture cycles:" << endl;cin >> k;
        //每幅图循环k次for (int i = 0; i < k; i++){fwrite(yBuf, 1, FWidth * FHeight, yuvFile);fwrite(uBuf, 1, (FWidth * FHeight) / 4, yuvFile);fwrite(vBuf, 1, (FWidth * FHeight) / 4, yuvFile);}//cout << "write yuvFile success!" << endl;

5.释放空间,关闭文件

        free(rgbBuf);free(yBuf);free(uBuf);free(vBuf);fclose(bmpFile);

四、实验结果

格式转换——bmp 2 yuv相关推荐

  1. 图像文件的读写和转换——BMP转YUV

    文章目录 数据压缩实验(二) 一.BMP文件格式分析 二.YUV文件格式分析 1.概述 2.YUV采样 Planar平面格式 RGB转YUV 三.实验过程 1.实验思路 2.实验代码 四.实验结果 数 ...

  2. vs2010用c语言实现数据转换成图片,数据压缩第二次实验报告——用C语言实现bmp to yuv的图片格式转化...

    实验目标 实验主要要求将图片格式从BMP到YUV的转化,并生成含有至少五幅图片不少于200帧的图像流. 实验原理 一.BMP图像简介: 典型的BMP图像文件由四部分组成(部分摘自360百科对BMP的定 ...

  3. BMP 转 YUV (BMP2YUV)

    本文介绍BMP 转 YUV.其实这是以前"数据压缩"实验课上的内容,前几天有人问我相关的问题,突然发现自己有一段时间没有接触BMP也有些生疏了,因此翻出资料总结一下. BMP文件格 ...

  4. YUV视频格式到RGB32格式转换的速度优化 上篇(转)

    YUV视频格式到RGB32格式转换的速度优化 上篇                     HouSisong@GMail.com    2007.10.30   tag: YUV,YCbCr,YUV ...

  5. 【DSP开发】【VS开发】YUV与RGB格式转换

    [视频处理]YUV与RGB格式转换 YUV格式具有亮度信息和色彩信息分离的特点,但大多数图像处理操作都是基于RGB格式. 因此当要对图像进行后期处理显示时,需要把YUV格式转换成RGB格式. RGB与 ...

  6. 图片格式转换大小调整工具_如何轻松快速地将图片转换到JPG/JPEG/PNG/BMP/TIFF

    万兴优转可用作为图片转换器,帮助您批量更改图片格式,且不会丢失任何质量.例如,您可以将PNG转换到JPG或其他格式,反之亦然.您还可以通过更改图片宽度和高度来调整图片大小,或者通过裁剪,旋转,添加效果 ...

  7. c语言bmp转换jpeg_PDF格式转换工具

    Cisdem PDF Converter OCR for Mac是一款Mac平台的PDF格式转换工具,可以帮助我们将PDF格式的文件转换成Word, Text, Excel, ePub, Keynot ...

  8. 转 把GIF图片转换成单个连续的图片 转 tif 等任意多帧图片转换bmp 或者gif等格式...

    为什么80%的码农都做不了架构师?>>>    转 把GIF图片转换成单个连续的图片 转 tif 等任意多帧图片转换bmp 或者gif等格式 using System; using ...

  9. bmp,jpg,png,tif,wmf,emf与eps图片格式转换

    wmf/emf是两种Microsoft Windows的图形文件格式.它是一个矢量图格式,但是也允许包含位图.本质上,一个WMF文件保存一系列可以用来重建图片的Windows GDI命令.在某种程度上 ...

最新文章

  1. 优达同学波士顿房价预测
  2. Outlook for Mac v15.36(170606)发布:新增收藏夹功能
  3. ehlib 用法记录
  4. CSS控制鼠标的箭头
  5. React拾遗:Render Props及其使用场景
  6. python web开发 JavaScript基础
  7. mysql查找无根节点sql_SQL 双亲节点查找所有子节点的实现方法
  8. D3D学习摘记(I)上
  9. java 8.0_java8_java8下载64位v8.0 官方版下载-无限下载
  10. windows 无法安装到这个磁盘,选中的磁盘具有MBR分区表,在EFI系统上,windows只能安装在GPT磁盘上
  11. 结构体别名typedef struct LNode{}LNode,*Linklist疑惑解答
  12. 人脸识别技术和人脸识别特征
  13. 【数据分析day04】美国2012年总统候选人政治献金数据分析
  14. Spring Boot+Spring Security:注解:@PreAuthorize,@PostAuthorize, @Secured, EL实现方法安全 - 第20篇
  15. 房地产估值法研究报告_房地产估值方法
  16. type c 网卡 外接网卡 禁用后 不见 消失 找不到 的解决办法
  17. windwos操作系统有snmp服务器,windows服务器snmp v3
  18. cuteftp向服务器传输文件没有权限
  19. iOS企业版app部署到自己的服务器
  20. 揭秘国漫《武动乾坤》制作幕后 动作戏竟然真人演

热门文章

  1. 【已解决】error: conflicting declaration ‘typedef struct LZ4_stream_t LZ4_stream_t’ typedef struct { long
  2. 如何理解电容电流超前电压90度
  3. 计算机的定点运算器原理,计算机组成原理定点运算器的组成和结构.doc
  4. C语言倒序输出/C语言倒置输出
  5. Browser Security Plus 企业网络过滤工具
  6. 整理的一篇iOS面试题大全
  7. 彻底关闭华为手机系统更新教程!防止系统自动更新!最详细教程!
  8. karas 实现lstm 文本分类
  9. Echart在Openlayers的应用-航班的炫光特效
  10. 算法09——patA1033 加油站问题(贪心)