本文介绍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. 十六进制字符串转化为十进制值strtoul函数

    eg: NSString *strtest =@"7fffffff"; NSUInteger val = strtoul([[strtest substringWithRange: ...

  2. springMVC源码分析--DispatcherServlet请求获取及处理

    在之前的博客springMVC源码分析--容器初始化(二)DispatcherServlet中我们介绍过DispatcherServlet,是在容器初始化过程中出现的,我们之前也说过Dispatche ...

  3. maven项目管理

    systemPath方式 有些不通用的包,maven仓库没有,只能通过本地包依赖,就像下面方式: 在需要依赖的项目建lib文件夹,如下: 然后在pom.xml项目管理文件里面加入本地依赖,如下 这种情 ...

  4. 求链表倒数第n个元素

    提示:设置一前一后两个指针,一个指针步长为1,另一个指针步长为n,当一个指针走到链表尾端时, 另一指针指向的元素即为链表倒数第n个元素. #include <stdio.h> #inclu ...

  5. Android简易实战教程--第二十九话《创建图片副本》

    承接第二十八话加载大图片,本篇介绍如何创建一个图片的副本. 安卓中加载的原图是无法对其修改的,因为默认权限是只读的.但是通过创建副本,就可以对其做一些修改,绘制等了. 首先创建一个简单的布局.一个放原 ...

  6. Hibernate查询,返回new对象(注意这个新定义的类要有构造函数),使用sql带条件分页查询并且把结果显示到一个对象的集里面的解决方案

     IIndexDao package com.ucap.netcheck.dao; import com.ucap.netcheck.combination.beans.IndexCombinat ...

  7. ffplay播放器移植VC的工程:ffplay for MFC

    本文介绍一个自己做的FFPLAY移植到VC下的开源工程:ffplayfor MFC.本工程将ffmpeg项目中的ffplay播放器(ffplay.c)移植到了VC的环境下.并且使用MFC做了一套简单的 ...

  8. iOS中 喷枪打字动画的实现

    实现原理比较简单,这里不做过多介绍. #import "ViewController.h" @interface ViewController () @property (weak ...

  9. >/dev/null 2>&1

    >/dev/null 2>&1 大部分在 crontab 计划任务中都会年到未尾带 >/dev/null 2>&1,是什么意思呢? > 是重定向 /dev ...

  10. Cocos2D:塔防游戏制作之旅(十五)

    Yes,貌似添加了好多的代码啊 ;] ,在你添加更多代码时,你可能注意到一些Xcode中的一些警告.首先你先忽略这些警告,我们先添加少量最终缺失的部分,然后再来解释上面代码做了什么! 在Enemy.m ...