编程实现将BMP序列转YUV文件

一、实验目的

1.理解图像文件的基本组成。
2.掌握结构体作为复杂数据对象的用法。进一步熟悉由问题到程序的解决方案,并掌握
编程细节:如内存分配、倒序读写、字节序、文件读写过程等。

二、实验原理

1、BMP概述

  • 位图文件(Bitmap-File,BMP)格式是Windows采用的图像文件存储格式,其位图文件默认的文件扩展名是bmp或者dib。
  • BMP格式分析如下:
数据段名称 含义 大小
位图文件头 (BITMAPFFILEHEADER) 提供文件类型、大小等信息 14字节
位图信息头(BITMAPINFOHEADER) 提供图像的尺寸、位面数、压缩方式、颜色索引等信息 40字节
调色板(Palette) 可选。实际上为一个数组,包含元素与位图颜色数相同 由颜色索引数决定
位图数据(ImageData) 图像数据 由图像尺寸决定

(1)位图文件头

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

(2)位图信息头

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;

(3)调色板

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

(4)位图数据

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

2、从BMP中提取RGB数据流程

在这里插入图片描述

注意,根据每像素位数的不同,具体操作也不同:

像素位数 具体操作
8bit以下 构造调色板,位与移位取像素数据查调色板,写RGB缓冲区
16bit 位与移位取像素数据转换为8bit/彩色分量,写RGB缓冲区
24/32bit 直接取像素数据,写RGB缓冲区

3、RGB转YUV的实现

  • Y=0.30R+0.59G+0.11B
  • U=0.493(B-Y)
  • V=0.877(R-Y)
  • 具体代码见我的文章彩色空间转换

三、实验步骤

1.将图片转换成相同大小且宽高均为4的整数倍的BMP文件(至少五张)在这里插入图片描述
2.根据需要创建头文件与源文件
在这里插入图片描述

3.分析BMP文件数据中的结构,读取BMP文件,提取RGB数据写入缓冲区
4.实现RGB到YUV的转换
5.生成yuvout.yuv文件,并用YUVviewerPlus查看
在这里插入图片描述

6.关闭文件,释放缓冲区

四、实验代码

1.bmp2yuv.h

#include <stdio.h>
#include<math.h>
#include <malloc.h>
#include<windows.h>

void BMP2RGB(FILE* pFile, BITMAPFILEHEADER& file_h, BITMAPINFOHEADER& info_h, unsigned char* rgbDataOut);

int RGB2YUV(int x_dim, int y_dim, void* bmp, void* y_out, void* u_out, void* v_out, int flip);

bool MakePalette(FILE* pFile, BITMAPFILEHEADER& file_h, BITMAPINFOHEADER& info_h, RGBQUAD* pRGB_out);
bool WriteYUV(unsigned char* Y, unsigned char* U, unsigned char* V, unsigned long size, FILE* outFile);

void InitLookupTable();//部分查找表

2.bmp2yuv.cpp

(1)准备工作

#include <stdio.h>
#include<math.h>
#include <malloc.h>
#include<windows.h>
#include "bmp2yuv.h"
#include "stdlib.h"

#define u_int8_t	unsigned __int8
#define u_int		unsigned __int32
#define u_int32_t	unsigned __int32

static float RGBYUV02990[256], RGBYUV05870[256], RGBYUV01140[256];
static float RGBYUV01684[256], RGBYUV03316[256];
static float RGBYUV04187[256], RGBYUV00813[256];

(2)BMP文件中提取RGB数据

void BMP2RGB(FILE* pFile, BITMAPFILEHEADER& file_h, BITMAPINFOHEADER& info_h, unsigned char* rgbDataOut)

{
   

	u_int32_t w, h, width, height;
	u_int i, j;
	unsigned char* dataBuf, * Data;

	//判断像素的实际点阵数,保证图像大小为4字节的整数倍

	if (((info_h.biWidth / 8 * info_h.biBitCount) % 4) == 0)
		w = info_h.biWidth;
	else
		w = (info_h.biWidth * info_h.biBitCount + 31) / 32 * 4;

	if ((info_h.biHeight % 2) == 0)
		h = info_h.biHeight;
	else
		h = info_h.biHeight + 1;

	width = w / 8 * info_h.biBitCount;//width为实际一行的字节数
	heig
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值