bmp 转YUV420数据组 C语言实现

本文介绍了如何使用C语言将BMP图像数据转换为YUV420格式,并详细讲解了BMP图像格式及转换过程。提供了一套完整的程序流程,包括读取BMP位图、RGB转YUV函数、YUV文件存储和YUV转数组的函数。代码可在CSDN上下载。
摘要由CSDN通过智能技术生成

需求:需要将BMP中的数据转换成YUV420之后,再输出到数组中去;


一、BMP图像数据格式详解

    1.1 简介
BMP(Bitmap-File)图形文件是Windows采用的图形文件格式,在Windows环境下运行的所有图象处理软件都支持BMP图象文件格式。Windows系统内部各图像绘制操作都是以BMP为基础的。Windows 3.0以前的BMP图文件格式与显示设备有关,因此把这种BMP图象文件格式称为设备相关位图DDB(device-dependent bitmap)文件格式。Windows 3.0以后的BMP图象文件与显示设备无关,因此把这种BMP图象文件格式称为设备无关位图DIB(device-independent bitmap)格式(注:Windows 3.0以后,在系统中仍然存在DDB位图,象BitBlt()这种函数就是基于DDB位图的,只不过如果你想将图像以BMP格式保存到磁盘文件中时,微软极力推荐你以DIB格式保存),目的是为了让Windows能够在任何类型的显示设备上显示所存储的图象。BMP位图文件默认的文件扩展名是BMP或者bmp(有时它也会以.DIB或.RLE作扩展名)。
 
  1.2.BMP格式结构
BMP文件的数据按照从文件头开始的先后顺序分为四个部分:
◆ 位图文件头(bmp file header):  提供文件的格式、大小等信息
◆ 位图信息头(bitmap information):提供图像数据的尺寸、位平面数、压缩方式、颜色索引等信息
◆ 调色板(color palette):可选,如使用索引来表示图像,调色板就是索引与其对应的颜色的映射表
◆ 位图数据(bitmap data):图像数据区
 
BMP图片文件数据表如下:

 

数据段名称 大小(byte) 开始地址 结束地址
位图文件头(bitmap-file header)
14 0000h 000Dh
位图信息头(bitmap-information header)
40 000Eh 0035h
调色板(color table)
由biBitCount决定 0036h 未知
图片点阵数据(bitmap data)
由图片大小和颜色定 未知 未知

 

 
  1.3.BMP文件头
BMP文件头结构体定义如下:
typedef struct tagBITMAPFILEHEADER
{ 
UINT16 bfType;        //2Bytes,必须为"BM",即0x424D 才是Windows位图文件
DWORD bfSize;         //4Bytes,整个BMP文件的大小
UINT16 bfReserved1;  //2Bytes,保留,为0
UINT16 bfReserved2;  //2Bytes,保留,为0
DWORD bfOffBits;     //4Bytes,文件起始位置到图像像素数据的字节偏移量
} BITMAPFILEHEADER;


 
BMP文件头数据表如下:

 

变量名 地址偏移 大小 作用说明
bfType 0000h 2Bytes
文件标识符,必须为"BM",即0x424D 才是Windows位图文件
‘BM’:Windows 3.1x, 95, NT,…  ‘BA’:OS/2 Bitmap Array  ‘CI’:OS/2 Color Icon   
‘CP’:OS/2 Color Pointer   ‘IC’:OS/2 Icon   
‘PT’:OS/2 Pointer
因为OS/2系统并没有被普及开,所以在编程时,你只需判断第一个标识“BM”就行
bfSize 0002h 4Bytes 整个BMP文件的大小(以位B为单位)
以下是一段简单的 Linux 下 BMP YUV420 的 C 语言代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #define BMP_HEADER_SIZE 54 void bmp_to_yuv420(char *bmp_file, char *yuv_file, int width, int height) { FILE *bmp_fp = fopen(bmp_file, "rb"); if (bmp_fp == NULL) { printf("Failed to open BMP file.\n"); return; } FILE *yuv_fp = fopen(yuv_file, "wb"); if (yuv_fp == NULL) { printf("Failed to create YUV file.\n"); fclose(bmp_fp); return; } // BMP header unsigned char bmp_header[BMP_HEADER_SIZE]; fread(bmp_header, sizeof(unsigned char), BMP_HEADER_SIZE, bmp_fp); // Image data int image_size = width * height * 3; unsigned char *image_data = (unsigned char *)malloc(image_size * sizeof(unsigned char)); fread(image_data, sizeof(unsigned char), image_size, bmp_fp); // YUV data int y_size = width * height; int u_size = y_size / 4; int v_size = y_size / 4; unsigned char *yuv_data = (unsigned char *)malloc((y_size + u_size + v_size) * sizeof(unsigned char)); // Convert BMP to YUV int i, j, k, l; for (i = 0; i < height; i++) { for (j = 0; j < width; j++) { int index = i * width + j; int y_index = i * width + j; int u_index = (i / 2) * (width / 2) + (j / 2) + y_size; int v_index = (i / 2) * (width / 2) + (j / 2) + y_size + u_size; unsigned char r = image_data[index * 3]; unsigned char g = image_data[index * 3 + 1]; unsigned char b = image_data[index * 3 + 2]; // Y component yuv_data[y_index] = (unsigned char)(0.299 * r + 0.587 * g + 0.114 * b); // U component if (i % 2 == 0 && j % 2 == 0) { int u_sum = 0; for (k = i; k < i + 2; k++) { for (l = j; l < j + 2; l++) { int u_index = (k / 2) * (width / 2) + (l / 2) + y_size; u_sum += image_data[(k * width + l) * 3 + 1]; } } yuv_data[u_index] = (unsigned char)(u_sum / 4); } // V component if (i % 2 == 0 && j % 2 == 0) { int v_sum = 0; for (k = i; k < i + 2; k++) { for (l = j; l < j + 2; l++) { int v_index = (k / 2) * (width / 2) + (l / 2) + y_size + u_size; v_sum += image_data[(k * width + l) * 3 + 2]; } } yuv_data[v_index] = (unsigned char)(v_sum / 4); } } } // Write YUV file fwrite(yuv_data, sizeof(unsigned char), y_size + u_size + v_size, yuv_fp); // Cleanup free(image_data); free(yuv_data); fclose(bmp_fp); fclose(yuv_fp); } int main() { bmp_to_yuv420("input.bmp", "output.yuv", 640, 480); return 0; } ``` 这段代码会将输入的 BMP 文件换为 YUV420 格式,并将结果保存到指定的 YUV 文件中。需要注意的是,这段代码仅适用于 24 位真彩色 BMP 图像。如果要处理其他类型的 BMP 图像,需要对代码进行适当的修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值