BITMAPINFOHEADER.biSizeImage

本文探讨了在处理由特定软件生成的非标准位图(BMP)文件时遇到的问题,这些文件中的biSizeImage字段与实际计算出的大小不符。文章提供了解决方案,包括使用Windows自带的画图工具进行修复,并提醒开发者们在处理此类文件时需要注意内存分配问题。
typedef struct tagBITMAPINFOHEADER{
DWORD biSize;
LONG biWidth;
LONG biHeight;
WORD biPlanes;
WORD biBitCount;
DWORD biCompression;
DWORD biSizeImage;
LONG biXPelsPerMeter;
LONG biYPelsPerMeter;
DWORD biClrUsed;
DWORD biClrImportant;
} BITMAPINFOHEADER, *PBITMAPINFOHEADER;

以上是位图(Bitmap)结构中的一个重要部分:BITMAPINFOHEADER,其中 biSizeImage 如果不为 0 这代表位图中实际的像素数据字节数,同时位图像素数据的字节数也可以通过 biWidth biHeight biBitCount 计算得到。按照道理讲,如果指定了这个成员,那么它的值应该和计算所得是一致的。但是我在实际使用中发现,某些软件(比如 Photoshop[的某个版本?])生成的位图文件指定了这个值但是和计算所得并不一致(大),同时位图像素数据部分的末尾会添加相应字节的对齐数据(我猜想是为了对齐到 4 字节边界)。
对于这种情况,我们要如何处理呢?如果你仅仅是为了显示一副这样的“非标准”BMP 而你所使用的类库(函数库)恰好不能处理这样的格式,最简单的处理方案就是用 Windows 自带的《画图》把此图片稍作修改(其实只是让《画图》认为你做了修改就可以了,比如在某个点上使用铅笔工具用相同的颜色再点一下即可)然后重新保存一下就可以了。如果你自己就是类库(函数库)的作者,那么请留意这种情况的可能性。特别是配合 CreateDIBSection 使用并且让 CreateDIBSection 替你分配内存的话,那么请注意它替你分配的内存的长度是通过 biWidth biHeight biBitCount 计算得到,而不是 biSizeImage 指定的值,所以在后续的内存读写时注意不要越界。
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/ioctl.h> #include <linux/fb.h> #pragma pack(1) //定义bmp文件头部结构 typedef struct { unsigned short bfType; unsigned int bfSize; unsigned short bfReserved1; unsigned short bfReserved2; unsigned int bfOffBits; }BITMAPFILEHEADER; typedef struct { unsigned int biSize; int biWidth; int biHeight; unsigned short biPlanes; unsigned short biBitCount; unsigned int biCompression; unsigned int biSizeImage; int biXPelsPerMeter; int biYPelsPerMeter; unsigned int biClrUsed; unsigned int biClrImportant; }BITMAPINFOHEADER; #pragma pack() int main(int argc, char const *argv[]) { int width = 0; int height = 0; BITMAPFILEHEADER src1; BITMAPINFOHEADER src2; //打开源图片 FILE *srcbmp_fp = fopen(argv[1], "rb"); //读取原图片的图像信息 fread(&src1,1,14,srcbmp_fp);//文件头 fread(&src2,1,40,srcbmp_fp);//信息头 width = src2.biWidth; height = src2.biHeight; //打开新图片 FILE *newbmp_fp = fopen(argv[2], "wb"); //向新图片中写入54字节的图像信息 src1.bfSize = (src2.biHeight / 2) * (src2.biWidth / 2) * 3 + 54; src2.biWidth = src2.biWidth / 2; src2.biHeight = src2.biHeight / 2; src2.biSizeImage = src2.biSizeImage / 2; fwrite(&src1,1,14,newbmp_fp); fwrite(&src2,1,40,newbmp_fp); //打算每次从源图片读取一行像素点的颜色分量的大小 int line_size = width * 3; char *src_pbuf = (char *)calloc(1,line_size)//申请一行的缓冲区内存 //循环从源图片中读取一行数据,并写入到新图片中 int line_num = height; while(line_num-=2) { fread(src_pbuf,1,line_size,srcbmp_fp);//读取一行的数据 800 for (int i = 0; i < width; i+=2) { fwrite(src_pbuf,3,1,newbmp_fp); //012 345 678 91011 } } return 0; }
06-13
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值