研究了下位图的格式,下面是从网上找到的一个说明文档(中文的,真好~~):
下载地址:
http://space.ednchina.com/Upload/Blog/2007/10/15/894e6ebb-8cf5-4125-96e7-2b2e524a9905.pdf
自己编了个生成位图文件的程序,只看这个文档还不能完全搞透位图,编程中就遇到了一些问题,现在总结一下,希望对大家有用:
1、位图中头的信息是按小字节序存储的,注意编译器如果是大字节序的需要字节顺序调整才可以。
2、位图中图象信息的第一个像素在图象中是左下角的像素,先最下一行从左往右,然后上面一行。
3、文档中有这样的说法:像素数据的长度(按字节计)要是4的倍数,这个4的倍数是怎么体现的呢?
首先,这个规定并不是可遵守不可遵守的,一旦不遵守,图象水平方向上像素数是4的倍数还好,不然肯定会出错。
这个4的倍数该怎么理解呢?我的像素怎么排?是不是每个像素占4个字节?
经过实际用画图板制作各种尺寸的图象得到下面的结论:
每个像素只占3个字节,水平方向上所有像素连续排列,
统计水平方向像素所占的字节数(像素数*3),如果得到的结果是4的倍数,就继续下一行数据,
如果不是4的倍数,在最后一个像素数据后面补0,使这一行的总字节数等于4的倍数,然后开始下一行数据
如:
3*5的图象:
水平方向有3个像素,像素占的字节数为9,不是4的倍数,在第三个像素数据后面补3个0,使这一行的总字节数为12,补完0,开始下一行数据。
5*3的图象:
水平方向有5个像素,像素占的字节数为15,不是4的倍数,在第五个像素后面补1个0,使此行的总字节数为16,继续下一行数据。
以下是写的程序(使用的编译器是winTC)
#include <stdio.h>
#define PIXEL_X 81 //水平像素数
#define PIXEL_Y 73 //垂直像素数
#define WIDTH_BYTES ((long)((((long)PIXEL_X*3)&0xfffffffe) + 4) ) // 每行像素的数据总数,必须是4的倍数
#define LENGTH_TAIL ((long)(4-(long)(PIXEL_X*3)%4)) // 定义水平方向上填充0的个数,小于等于3,填充的0称做"尾巴"
#define BIG 1
#define SMALL 0
enum cmprs_type
{
BI_RGB,
BI_RLE8,
BI_RLE4,
BI_BITFIELDES
};
struct ST_ImgFileHead //total 14(0xE) bytes
{ //offset,size(byte)
char format[2]; // 0x00 , 0x2; 固定为"BM"
long file_size; // 0x02 , 0x4; 整个文件大小;注意是大字节序还是小字节序,实际BMP格式中是小字节序
long reserved; // 0x06 , 0x4; 保留,必须为0
long data_ofst; // 0x0A , 0x4; 图象数据的偏移,看后面的图象信息头的多少定,图象信息头大小为0x28则本字段值为0x36,本字段的值实际上为"图象信息头长度+14+调色板信息长度"
};
struct ST_ImgInfHead //total 40(0x28) bytes; 图象信息头
{
long img_inf_size; // 0x0E , 0x4; 图象信息头的大小,基本上是0x28,但也不一定,读取位图的时候这个值最好读出来
long width; // 0x12 , 0x4; 位图宽度,以像素为单位
long height; // 0x16 , 0x4; 位图高度,以像素为单位
int planes; // 0x1A , 0x2; 位图位平面数,固定为1
int pixel_bit_width; // 0x1C , 0x2; 像素位宽: 1,4,8,16,24,32可选
long compression; // 0x1E , 0x4; 压缩方式,从枚举的压缩方式中选一种
long img_size; // 0x22 , 0x4; 图象数据大小,以字节为单位,必须是4的倍数
long h_resolution; // 0x26 , 0x4; 水平分辨率,用像素/米表示
long v_resolution; // 0x2A , 0x4; 垂直分辨率,用像素/米表示
long colors; // 0x2E , 0x4; 位图使用的颜色数
long important; // 0x32 , 0x4; 指定重要的颜色数,该域的值为颜色总数或者0时表示所有颜色都一样重要
};
//char palette[]; //压缩方式选择BI_RGB,没有颜色表
struct ST_Pixel
{
char blue;
char green;
char red;
};
struct ST_MatrixPixelX
{
struct ST_Pixel pixel_data[PIXEL_X];
char tail_data[LENGTH_TAIL];
};
struct ST_Img
{
struct ST_ImgFileHead file_head;
struct ST_ImgInfHead inf_head;
struct ST_MatrixPixelX matrix[PIXEL_Y];
};
void Endian_Check()
{
int i = 0x1234;
if(*((char *)&i) == 0x12)
return(BIG); //大字节序
else
{
if(*((char *)&i) == 0x34)
return(SMALL); //小字节序
else
{
printf("Error");
}
}
getch();
}
void Endian_Regulator(char *data, char data_size) //调整字节顺序
{
char temp;
char i;
char t,size_temp;
size_temp = data_size-1;
for( i=0;i<=(size_temp>>1);i++ )
{
//printf("[data+%d] = %x\n",i,*(data+i));
//printf("[data+%d-%d] = %x\n",size_temp,i,*(data+size_temp-i));
temp = *(data+i);
*(data+i) = *(data + size_temp -i);
*(data + size_temp -i) = temp;
//printf("[data+%d] = %x\n",i,*(data+i));
//printf("[data+%d-%d] = %x\n\n",size_temp,i,*(data+size_temp-i));
//getch();
}
}
main()
{
FILE *fp;
char *pimg;
long x,y;
long i;
struct ST_Img img1;
img1.file_head.format[0] = 'B';
img1.file_head.format[1] = 'M';
img1.file_head.file_size = 0x36+WIDTH_BYTES*PIXEL_Y;
img1.file_head.reserved = 0;
img1.file_head.data_ofst = 0x36;
img1.inf_head.img_inf_size = 0x28;
img1.inf_head.width = PIXEL_X;
img1.inf_head.height = PIXEL_Y;
img1.inf_head.planes = 1;
img1.inf_head.pixel_bit_width = 24;
img1.inf_head.compression = BI_RGB;
img1.inf_head.img_size = WIDTH_BYTES*PIXEL_Y;
img1.inf_head.colors = 0x1000000;
img1.inf_head.important = 0;
for(y=0;y<IXEL_Y;y++) //图象点从左下角向右,从下到上排列,数组坐标是[y][x]
{
for(x=0;x<IXEL_X;x++)
{
//img1.matrix[y].pixel_data[x].red = y*3;
//img1.matrix[y].pixel_data[x].green = 0;
//img1.matrix[y].pixel_data[x].blue = 0;
if(x<=PIXEL_X/3)
{
img1.matrix[y].pixel_data[x].red = y*3;
img1.matrix[y].pixel_data[x].green = 0;
img1.matrix[y].pixel_data[x].blue = 0;
}
else
{
if((x>IXEL_X/3) && (x<=(PIXEL_X*2)/3))
{
img1.matrix[y].pixel_data[x].red = 0;
img1.matrix[y].pixel_data[x].green = y*3;
img1.matrix[y].pixel_data[x].blue = 0;
}
else
{
if(x>(PIXEL_X*2)/3)
{
img1.matrix[y].pixel_data[x].red = 0;
img1.matrix[y].pixel_data[x].green = 0;
img1.matrix[y].pixel_data[x].blue = y*3;
}
}
}
}
for(x=0;x<LENGTH_TAIL;x++)
{
img1.matrix[y].tail_data[x] = 0; //填充尾巴"0"
}
}
pimg = &img1;
fp = fopen("test.bmp","wb+");
for(i=0;i<img1.file_head.file_size;i++)
{
fputc(*(pimg++),fp); //把图象结构体写入文件
}
fclose(fp);
}
转载
|