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

BMP文件格式解析

位图文件(Bitmap-File,BMP)格式是Windows采用的图像文件存储格式,在Windows环境下运行的所有图像处理软件都支持这种格式。BMP位图文件默认的文件扩展名是bmp或者dib。BMP文件大体上分为四个部分:

位图文件头主要包括:

typedef struct tagBITMAPFILEHEADER {
WORD bfType; /* 说明文件的类型 */
DWORD bfSize; /* 说明文件的大小,用字节为单位 */
WORD bfReserved1; /* 保留,设置为0 */
WORD bfReserved2; /* 保留,设置为0 */
DWORD bfOffBits; /* 说明从BITMAPFILEHEADER结构开始到实际的图像数据之间的字节偏移量 */
} BITMAPFILEHEADER;

位图信息头主要包括:

typedef struct tagBITMAPINFOHEADER {
DWORD biSize; /* 说明结构体所需字节数 */
LONG biWidth; /* 以像素为单位说明图像的宽度 */
LONG biHeight; /* 以像素为单位说明图像的高速 */
WORD biPlanes; /* 说明位面数,必须为1 */
WORD biBitCount; /* 说明位数/像素,1、2、4、8、24 */
DWORD biCompression; /* 说明图像是否压缩及压缩类型BI_RGB,BI_RLE8,BI_RLE4,BI_BITFIELDS */
DWORD biSizeImage; /* 以字节为单位说明图像大小,必须是4的整数倍*/
LONG biXPelsPerMeter; /*目标设备的水平分辨率,像素/米 */
LONG biYPelsPerMeter; /*目标设备的垂直分辨率,像素/米 */
DWORD biClrUsed; /* 说明图像实际用到的颜色数,如果为0,则颜色数为2的biBitCount次方 */
DWORD biClrImportant; /*说明对图像显示有重要影响的颜色索引的数目,如果是0,表示都重要。*/
} BITMAPINFOHEADER;

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

typedef struct tagRGBQUAD {
BYTE rgbBlue; /*指定蓝色分量*/
BYTE rgbGreen; /*指定绿色分量*/
BYTE rgbRed; /*指定红色分量*/
BYTE rgbReserved; /*保留,指定为0*/
} RGBQUAD;

紧跟在调色板之后的是图像数据字节阵列。对于用到调色板的位图,图像数据就是该像素颜色在调色板中的索引值(逻辑色)。对于真彩色图,图像数据就是实际的R、G、B值。图像的每一扫描行由表示图像像素的连续的字节组成,每一行的字节数取决于图像的颜色数目和用像素表示的图像宽度。规定每一扫描行的字节数必需是4的整倍数,也就是DWORD对齐的。扫描行是由底向上存储的,这就是说,阵列中的第一个字节表示位图左下角的像素,而最后一个字节表示位图右上角的像素。

读取BMP文件,提取RGB数据的流程

流程如下图所示:

在这里需要注意的的是,根据BMP每像素所占的比特数不同(8,16,32 bpp),分为不同的处理方法,如下图所示。

下面看看16bpp的BMP文件操作:

R,G,B在16bit中所占的位数如下图所示

for (Loop = 0;Loop < height * width;Loop +=2)
{
       *rgbDataOut = (Data[Loop]&0x1F)<<3;
       *(rgbDataOut + 1) = ((Data[Loop]&0xE0)>>2) + 			((Data[Loop+1]&0x03)<<6);
       *(rgbDataOut + 2) = (Data[Loop+1]&0x7C)<<1;
       rgbDataOut +=3;
}

1-8bpp的BMP文件操作:

int shiftCnt = 1;
while (mask)
{
unsigned char index = mask == 0xFF ? Data[Loop] : ((Data[Loop] & mask)>>(8 - shiftCnt * info_h.biBitCount));
* rgbDataOut = pRGB[index].rgbBlue;
* (rgbDataOut+1) = pRGB[index].rgbGreen;
* (rgbDataOut+2) = pRGB[index].rgbRed;
if(info_h.biBitCount == 8)	mask = 0;
Else 	mask >>= info_h.biBitCount;
rgbDataOut+=3;
shiftCnt ++;
}

BMP转换为YUV

RGB到色差信号的转换如下所示:
Y=0.2990R+0.5870G+0.1140B
R-Y=0.7010R-0.5870G-0.1140B
B-Y=-0.2990R-0.5870G+0.8860B

为了使色差信号的动态范围控制在0.5之间,需要进行归一化,对色差信号引入压缩系数。归一化后的色差信号为:

U=-0.1684R-0.3316G+0.5B
V=0.5R-0.4187G-0.0813B

YUV文件的格式

转换后的YUV数据需要存成YUV文件(在这里是YUV420P格式)。YUV文件的格式很简单,先连续存Y,然后U,然后V,如图所示。

BMP 转 YUV程序下载地址:http://download.csdn.net/detail/leixiaohua1020/6469807

BMP 转 YUV (BMP2YUV)的更多相关文章

  1. 使用ffmpeg将BMP图片编码为x264视频文件,将H264视频保存为BMP图片,yuv视频文件保存为图片的代码

    ffmpeg开源库,实现将bmp格式的图片编码成x264文件,并将编码好的H264文件解码保存为BMP文件. 实现将视频文件yuv格式保存的图片格式的測试,图像格式png,jpg, gif等等測试均O ...

  2. 基于ZedBoard的Webcam设计(一):USB摄像头(V4L2接口)的图片采集【转】

    转自:http://www.cnblogs.com/surpassal/archive/2012/12/19/zed_webcam_lab1.html 一直想把USB摄像头接到Zedboard上,搭建 ...

  3. 14、USB摄像头(V4L2接口)的图片采集

    参考网站http://www.cnblogs.com/surpassal/archive/2012/12/19/zed_webcam_lab1.html 一.一些知识 1.V4L和V4L2. V4L是 ...

  4. MFC下用sdl 显示bmp、rgb、yuv

    #include <libsdl/SDL.h>//#include "SDL.h"#ifdef TEST_VGA16 /* Define this if you wan ...

  5. yuv转bmp

    #ifdef _INTERFACE_H #error _INTERFACE_H has be exsisted #else #define _INTERFACE_H #include "st ...

  6. yuv420转rgb 及 rgb转bmp保存

    /// <summary> /// 将一桢 YUV 格式的图像转换为一桢 RGB 格式图像. /// </summary> /// <param name="y ...

  7. EmguCV(OpenCV)实现高效显示视频(YUV)叠加包括汉字

    视频处理中,往往需要在上面增加文字包括汉字英文字母数字标点等,Emgu.CV/opencv 绘图 线面文字包括中文 这篇里也有相关介绍,但是这篇里根据逐像素修改rgb值的方法效率太低 查了很多资料,基 ...

  8. 最简单的视音频播放示例2:GDI播放YUV, RGB

    前一篇文章对“Simplest Media Play”工程作了概括性介绍.后续几篇文章打算详细介绍每个子工程中的几种技术.在记录Direct3D,OpenGL这两种相对复杂的技术之前,打算先记录一种和 ...

  9. RGB图像数据字符叠加,图像压缩(ijl库),YUV转RGB

    jackyhwei 发布于 2010-01-01 12:02 点击:3218次  来自:CSDN.NET 一些非常有用的图像格式转换及使用的源代码,包括RGB图像数据字符叠加,图像压缩(ijl库),Y ...

随机推荐

  1. Universal-Image-Loader 图片异步加载类库的使用

    这个图片异步加载并缓存的类已经被很多开发者所使用,是最常用的几个开源库之一,主流的应用,随便反编译几个火的项目,都可以见到它的身影. 可是有的人并不知道如何去使用这库如何进行配置,网上查到的信息对于刚 ...

  2. JBOSS EAP 6 系列四 EJB实现——调用(贯穿始终的模块)

    本文主要介绍在JBOSS EAP 6.2(或者JBOSS AS7)中模块是如何贯穿EJB实现的始终.延续上一博文<认识模块的使用>的话题继续聊JBOSS做为模块申明式容器的这一特性在EJB ...

  3. iOS中NSTimer的invalidate调用之后

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 免责申明:本博客提供的所有翻译文章原稿均来自互联网,仅供学习交 ...

  4. COM原理与实现之一

    COM原理与实现之一 COM组件其实是一种特殊的对象体系,遵循一个统一的标准,使到各个软件都可以通过某种方法访问这个对象的方法,也就可以做到组件调用.COM就是统一的标准--通过接口来调用COM组件. ...

  5. iOS中 最新微信支付/最全的微信支付教程详解 韩俊强的博客

    每日更新关注:http://weibo.com/hanjunqiang  新浪微博! 亲们, 首先让我们来看一下微信支付的流程吧. 1. 注册微信开放平台,创建应用获取appid,appSecret, ...

  6. 05 Activity知识

    1.Activity          >概念:活动面板   应用程序组件  可以绘制Ui界面  可以和用户进行交互     默认展示全屏  其他情况 界面比其他窗口小  悬浮在其他窗口上方   ...

  7. there was no endpoint listening at net.pipe://localhost/PreviewProcessingService/ReportProcessing

    当你在开发reporting service报表时,进行报表的preview时报下图中的错误,以下方法可以让你直接跳过这个错误,继续查看报表的运行结果. 直接选择你需要运行查看的报表右击run就可以, ...

  8. debian 安装jdk

    JDK下载http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-javase6- ...

  9. 06_NoSQL数据库之Redis数据库:Redis的高级应用之登录授权和主从复制

     Redis高级实用特征 安全性(登录授权和登录后使用auth授权) 设置客户端连接后进行任何其他指定前需要使用的密码. 警告:因为redis速度相当快,所以在一台比较好的服务器下,一个外部的用户 ...

  10. UNIX环境高级编程——线程

    线程包含了表示进程内执行环境必需的信息,其中包括进程中标示线程的线程ID.一组寄存器值.栈.调度优先级和策略.信号屏蔽字.errno变量以及线程私有数据. 进程的所有信息对该进程的所有线程都是共享的, ...