【数据压缩】实验二——BMP序列转YUV文件

(一)实验目的

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

(二)实验内容

  1. 在图像处理软件中自行生成多个BMP文件,至少含5个不同的场景画面,要求带含有班级、学号后四位和本人姓名(缩写或昵称均可)的logo。(基本要求为24bit的BMP,进阶要求为支持小于24bit的BMP。)
  2. 编写将第一步所生成的多个BMP文件转化为YUV文件,要求可在命令行中设置每个画面出现的帧数。最后形成的YUV文件应至少包含200帧。重点掌握函数定义、缓冲区分配、倒序读写、结构体的操作。
  3. 对整个程序进行调试,并将生成的YUV文件用播放软件观看,验证是否正确。

(三)实验步骤

思路方面理解起来很简单,理清BMP文件数据中的四层结构,分别是位图文件头、位图信息头、调色板、实际的位图数据。从位图信息头中提取图像宽高、实际的位图数据所在数据,然后从BMP中读取实际的位图数据,进而索引调色板数组得到每一数据的实际物理意义,即查找得到各位图数据代表了什么颜色(顺序是BGR),进而采用下列转化公式,将RGB转化为YUV

Y=0.30R+0.59G+0.11B, U=0.493(B-Y), V=0.877(R-Y)

  1. BMP文件的组成结构
    1)BMP(全称Bitmap)是Window操作系统中的标准图像文件格式,可以分成两类:设备相关位图(DDB)和设备无关位图(DIB),使用非常广。它采用位映射存储格式,除了图像深度可选以外,不采用其他任何压缩,因此,BMP文件所占用的空间很大。
    2)BMP文件的图像深度可选1bit、4bit、8bit及24bit。BMP文件存储数据时,图像的扫描方式是按从左到右、从下到上的顺序。 由于BMP文件格式是Windows环境中交换与图有关的数据的一种标准,因此在Windows环境中运行的图形图像软件都支持BMP图像格式。
结构 说明
位图头文件数据结构 包含BMP图像文件的类型、显示内容等信息
位图信息数据结构 包含有BMP图像的宽、高、压缩方法,以及定义颜色等信息
调色板 这个部分是可选的,有些位图需要调色板,有些位图,比如真彩色图(24位的BMP)就不需要调色板
位图数据 这部分的内容根据BMP位图使用的位数不同而不同,在24位图中直接使用RGB,而其他的小于24位的使用调色板中颜色索引值
(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;

(四)关键代码

用结构体组织复杂数据;
结构成员的值个别地传给函数处理。

  1. 前序工作
    这里以生成多帧YUV播放视频为例,首先设置命令行参数

argv[1]=potter argv[2]=5,第一个参数代表文件名的共同部分,第二个代表图片张数(也就是视频的帧数),目的是方便读取图一所示的文件

至于YUV文件,文件名直接使用argv[1]:potter.yuv

  1. 主函数分析
    主函数的思路就是整个实验的思路:
    1)读取BMP文件;
    2) 抽取BMP文件头和信息头信息,用结构体File_header盛放文件头数据,用结构体Info_header盛放信息头数据;
    3)调用ReadRGB 函数,从bmp文件中读取RGB信息;
    4)最后调用RGB2YUV函数,将rgb数据转为yuv;
    5)写YUV文件
int main(int argc,char**argv)
{
   
    BITMAPFILEHEADERFile_header;
    BITMAPINFOHEADERInfo_header;
    FILE*bmpFile;
    FILE*yuvFile;
 
    unsignedchar*rgbBuffer, *yBuffer, *uBuffer, *vBuffer;
    charname__[20];
    //连接成字符串:potter.yuv,方便文件写入磁盘
    strcpy_s(name__, argv[1]);
    strcat_s(name__, 20, ".yuv");
    fopen_s(&yuvFile,name__ , "wb");
    if(!yuvFile)
    {
   
        printf("yuvfile open error!\n");
        exit(0);
    }
    for (inti = 1; i <= atoi(argv[2]); ++i){
   
        charstr[20];
        charname_[20];
        //将“potter”“序号”“.bmp”连接成文件名,再用fopen函数打开文件
        strcpy_s(name_, argv[1]);
        _itoa_s(i, str, 20, 10);
        strcat_s(name_, 20, str);
        strcat_s(name_, 20,".bmp");
        fopen_s(&bmpFile,name_ , "rb");
        if(!bmpFile)
        {
   
            printf("bmpfile open error!\n");
            exit(0);
        }
 
        //读取位图文件头
        if(fread(&File_header, sizeof(BITMAPFILEHEADER), 1, bmpFile) != 1)
        {
   
            printf("readfile header error!\n");
            exit(0);
        }
 
        //判断文件类型
        if(File_header.bfType != 0x4D42)
        {
   
            printf("Notbmp file!\n")
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值