BMP编程实践1:C语言实现bmp位图分析与创建

前言

        本次实验使用的BMP图片是256位的灰度图片。

        本次实验分两步,第一个源码是读图片信息,第二个源码是生成图片。这种操作适用于已知一个图片的格式,然后生成一个和它一样的图片的格式,例如给带屏的单片机截屏,保存图片。

       

一 BMP图片头解析

         位图文件可看成由 4 个部分组成:位图文件头(BITMAPFILEHEADER)、位图信息头(BITMAPINFOHEADER)、调色板(Palette)也叫彩色表(color table)和定义位图的字节阵列,下面会逐个介绍。

第一部分

第一部分为位图文件头 BITMAPFILEHEADER ,是一个结构,其定义如下:
typedef uint16_t WORD;
typedef uint32_t DWORD;
typedef struct tagBITMAPFILEHEADER{
    WORD bfType;//2
    DWORD bfSize;//4
    WORD bfReserved1;//2
    WORD bfReserved2;//2
    DWORD bfOffBits;//4
} BITMAPFILEHEADER;
        这个结构的长度是固定的,为 14 个字节( WORD 为无符号 16 位整数, DWORD 为无符号32 位整数),各个域的说明如下:
bfType
        指定文件类型,必须是 0x424D ,即字符串 "BM" ,也就是说所有 .bmp 文件的头两个字节都 是"BM"
bfSize
        指定文件大小,包括这 14 个字节
bfReserved1 bfReserved2
                为保留字,不用考虑
bfOffBits
        为从文件头到实际的位图数据的偏移字节数, 前三个部分的长度之和

第二部分

        第二部分为位图信息头 BITMAPINFOHEADER,也是一个结构,其定义如下:

typedef uint16_t WORD;
typedef uint32_t DWORD;
typedef uint32_t LONG; 
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; 

        这个结构的长度是固定的,为 40 个字节(WORD 为无符号 16 位整数,DWORD 无符号 32 位整数,LONG 32 位整数),各个域的说明如下:

biSize
        指定这个结构的长度,为 40
biWidth
        指定图象的宽度,单位是象素
biHeight
        指定图象的高度,单位是象素
biPlanes
        必须是 1 ,不用考虑
biBitCount

        指定表示颜色时要用到的位数,常用的值为 1(黑白二色图),416 色图),8256 色),24

(真彩色图)(新的 .bmp 格式支持 32 位色,这里就不做讨论了)。
biCompression
        指定位图是否压缩,有效的值为 BI_RGB BI_RLE8 BI_RLE4 BI_BITFIELDS(都是一 些 Windows 定义好的常量)。要说明的是, Windows 位图可以采用 RLE4 ,和 RLE8 的压缩 格式,但用的不多。我们今后所讨论的只有第一种不压缩的情况,即 biCompression 为BI_RGB 的情况。
biSizeImage
        指定实际的位图数据占用的字节数,其实也可以从以下的公式中计算出来:
biSizeImage=biWidth'*biHeight
        要注意的是:上述公式中的 biWidth' 必须是 4 的整倍数(所以不是 biWidth ,而是 biWidth', 表示大于或等于 biWidth 的,离 4 最近的整倍数。举个例子,如果 iWidth=240,则 biWidth'=240 ;如果 biWidth=241 biWidth'=244 )如果 biCompression BI_RGB,则该项可能为零
biXPelsPerMeter
        指定目标设备的水平分辨率,单位是每米的象素个数,关于分辨率的概念,我们将在打印部 分详细介绍。
biYPelsPerMeter
        指定目标设备的垂直分辨率,单位同上。
biClrUsed
        指定本图象实际用到的颜色数,如果该值为零,则用到的颜色数为 2 biBitCount 次方。
biClrImportant
        指定本图象中重要的颜色数,如果该值为零,则认为所有的颜色都是重要的。

第三部分-调色板

        第三部分为调色板(Palette),当然,这里是对那些需要调色板的位图文件而言的。有些位图, 如真彩色图,前面已经讲过,是不需要调色板的,BITMAPINFOHEADER 后直接是位图数据。调色板实际上是一个数组,共有 biClrUsed 个元素(如果该值为零,则有 2 biBitCount 方个元素)。数组中每个元素的类型是一个 RGBQUAD 结构,占 4 个字节,其定义如下:

typedef uint8_t BYTE;
typedef struct tagRGBQUAD{
    BYTE rgbBlue; //该颜色的蓝色分量
    BYTE rgbGreen; //该颜色的绿色分量
    BYTE rgbRed; //该颜色的红色分量
    BYTE rgbReserved; //保留值
} RGBQUAD;

第四部分

        第四部分就是实际的图象数据了。对于用到调色板的位图,图象数据就是该像素颜在调色板
中的索引值,对于真彩色图,图象数据就是实际的 R,G,B 值。下面就 2 色, 16 色, 256 色位
图和真彩色位图分别介绍。对于 2 色位图,用 1 位就可以表示该像素的颜色(一般 0 表示黑, 1 表示白),所以一个字节可以表示 8 个像素。对于 16 色位图,用 4 位可以表示一个像素的颜色,所以一个字节可以表示 2 个像素。对于 256 色位图,一个字节刚好可以表示 1 个像素。对于真彩色图,三个字节才能表示 1 个像素。
        要注意两点:
        1.每一行的字节数必须是 4 的整倍数,如果不是,则需要补齐。这在前面介绍 biSizeImage
时已经提到了。
        2.一般来说, .BMP 文件的数据从下到上,从左到右的。也就是说,从文件中最先读到的
是图象最下面一行的左边第一个像素,然后是左边第二个像素…接下来是倒数第二行左边第
一个像素,左边第二个像素…依次类推,最后得到的是最上面一行的最右一个像素。
好了,终于介绍完 bmp 文件结构了,是不是觉得头有些大。

二 实践

        还是不知道应该怎么设置怎么办,调色板也不知道应该怎么设置。找一个目标图片,读出它的内部数据,然后将他们一个一个的赋值给新图片。

读图片的参数源码

#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
char buf[1024];
typedef uint16_t WORD;
typedef uint32_t DWORD;
#pragma pack(1)
typedef struct tagBITMAPFILEHEADER{
    WORD bfType;//2
    DWORD bfSize;//4
    WORD bfReserved1;//2
    WORD bfReserved2;//2
    DWORD bfOffBits;//4
} BITMAPFILEHEADER;
#pragma pack()
typedef uint32_t LONG; 
#pragma pack(1)
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; 
#pragma pack()
void show_bit_map_file_header(BITMAPFILEHEADER *p)
{
	printf("bfType=%04x\n",p->bfType);
	printf("bfSize=%d\n",p->bfSize);
	printf("bfReserved1=%d\n",p->bfReserved1);
	printf("bfReserved2=%d\n",p->bfReserved2);
	printf("bfOffBits=%d\n",p->bfOffBits);
}
void show_bit_map_info_header(BITMAPINFOHEADER *p)
{
	printf("biSize=%d\n",p->biSize);
	printf("biWidth=%d\n",p->biWidth);
	printf("biHeight=%d\n",p->biHeight);
	printf("biPlanes=%d\n",p->biPlanes);
	printf("biBitCount=%d\n",p->biBitCount);
	printf("biCompression=%d\n",p->biCompression);
	printf("biSizeImage=%d\n",p->biSizeImage);
	printf("biXPelsPerMeter=%d\n",p->biXPelsPerMeter);
	printf("biYPelsPerMeter=%d\n",p->biYPelsPerMeter);
	printf("biClrUsed=%d\n",p->biClrUsed);
	printf("biClrImportant=%d\n",p->biClrImportant);
}

void show_bmp_info(char *name)
{
	BITMAPFILEHEADER bit_map_file_header;
	BITMAPINFOHEADER bit_map_info_header;
	int fd = 0;
	int i = 0;
	fd = open(name,O_RDONLY);
	if(fd < 0){
		perror("open");
		return;
	}
	printf("open %s ok \n",name);
	read(fd,&bit_map_file_header,sizeof(bit_map_file_header));
	read(fd,&bit_map_info_header,sizeof(bit_map_info_header));
	show_bit_map_file_header(&bit_map_file_header);
	show_bit_map_info_header(&bit_map_info_header);
	read(fd,buf,1024);
	for(i = 0;i < 1024;i++){
		if(i > 0 && i%16 == 0){
			printf("\n");
		}
		printf("0x%02x,",(uint8_t)buf[i]);
	}
	printf("\n");
	close(fd);
}
int main(int argc,char *argv[])
{
	show_bmp_info("2.bmp");
	return 0;
}

        运行结果:

        输出信息里面的那一堆的0x十六进制数据是调色板,这个图片的调色板是1024字节,怎么知道是1024字节?我提前计算的。这个图片大小是1025078 - 54(图片头)-1280*800(图片数组)= 1024;1024就是调色板大小了。

        再分析一下为什么是1024个字节呢?调色板实际上是一个数组,共有 biClrUsed 个元素,下面的输出中,biClrUsed的值是256。数组中每个元素的类型是一个 RGBQUAD 结构,占 4 个字节。所以是biClrUsed * sizeof(RGBQUAD) = 256 * 4 = 1024字节。

open 2.bmp ok
bfType=4d42
bfSize=1025078
bfReserved1=0
bfReserved2=0
bfOffBits=1078
biSize=40
biWidth=1280
biHeight=800
biPlanes=1
biBitCount=8
biCompression=0
biSizeImage=1024000
biXPelsPerMeter=5669
biYPelsPerMeter=5669
biClrUsed=256
biClrImportant=256
0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x00,0x02,0x02,0x02,0x00,0x03,0x03,0x03,0x00,
0x04,0x04,0x04,0x00,0x05,0x05,0x05,0x00,0x06,0x06,0x06,0x00,0x07,0x07,0x07,0x00,
0x08,0x08,0x08,0x00,0x09,0x09,0x09,0x00,0x0a,0x0a,0x0a,0x00,0x0b,0x0b,0x0b,0x00,
0x0c,0x0c,0x0c,0x00,0x0d,0x0d,0x0d,0x00,0x0e,0x0e,0x0e,0x00,0x0f,0x0f,0x0f,0x00,
0x10,0x10,0x10,0x00,0x11,0x11,0x11,0x00,0x12,0x12,0x12,0x00,0x13,0x13,0x13,0x00,
0x14,0x14,0x14,0x00,0x15,0x15,0x15,0x00,0x16,0x16,0x16,0x00,0x17,0x17,0x17,0x00,
0x18,0x18,0x18,0x00,0x19,0x19,0x19,0x00,0x1a,0x1a,0x1a,0x00,0x1b,0x1b,0x1b,0x00,
0x1c,0x1c,0x1c,0x00,0x1d,0x1d,0x1d,0x00,0x1e,0x1e,0x1e,0x00,0x1f,0x1f,0x1f,0x00,
0x20,0x20,0x20,0x00,0x21,0x21,0x21,0x00,0x22,0x22,0x22,0x00,0x23,0x23,0x23,0x00,
0x24,0x24,0x24,0x00,0x25,0x25,0x25,0x00,0x26,0x26,0x26,0x00,0x27,0x27,0x27,0x00,
0x28,0x28,0x28,0x00,0x29,0x29,0x29,0x00,0x2a,0x2a,0x2a,0x00,0x2b,0x2b,0x2b,0x00,
0x2c,0x2c,0x2c,0x00,0x2d,0x2d,0x2d,0x00,0x2e,0x2e,0x2e,0x00,0x2f,0x2f,0x2f,0x00,
0x30,0x30,0x30,0x00,0x31,0x31,0x31,0x00,0x32,0x32,0x32,0x00,0x33,0x33,0x33,0x00,
0x34,0x34,0x34,0x00,0x35,0x35,0x35,0x00,0x36,0x36,0x36,0x00,0x37,0x37,0x37,0x00,
0x38,0x38,0x38,0x00,0x39,0x39,0x39,0x00,0x3a,0x3a,0x3a,0x00,0x3b,0x3b,0x3b,0x00,
0x3c,0x3c,0x3c,0x00,0x3d,0x3d,0x3d,0x00,0x3e,0x3e,0x3e,0x00,0x3f,0x3f,0x3f,0x00,
0x40,0x40,0x40,0x00,0x41,0x41,0x41,0x00,0x42,0x42,0x42,0x00,0x43,0x43,0x43,0x00,
0x44,0x44,0x44,0x00,0x45,0x45,0x45,0x00,0x46,0x46,0x46,0x00,0x47,0x47,0x47,0x00,
0x48,0x48,0x48,0x00,0x49,0x49,0x49,0x00,0x4a,0x4a,0x4a,0x00,0x4b,0x4b,0x4b,0x00,
0x4c,0x4c,0x4c,0x00,0x4d,0x4d,0x4d,0x00,0x4e,0x4e,0x4e,0x00,0x4f,0x4f,0x4f,0x00,
0x50,0x50,0x50,0x00,0x51,0x51,0x51,0x00,0x52,0x52,0x52,0x00,0x53,0x53,0x53,0x00,
0x54,0x54,0x54,0x00,0x55,0x55,0x55,0x00,0x56,0x56,0x56,0x00,0x57,0x57,0x57,0x00,
0x58,0x58,0x58,0x00,0x59,0x59,0x59,0x00,0x5a,0x5a,0x5a,0x00,0x5b,0x5b,0x5b,0x00,
0x5c,0x5c,0x5c,0x00,0x5d,0x5d,0x5d,0x00,0x5e,0x5e,0x5e,0x00,0x5f,0x5f,0x5f,0x00,
0x60,0x60,0x60,0x00,0x61,0x61,0x61,0x00,0x62,0x62,0x62,0x00,0x63,0x63,0x63,0x00,
0x64,0x64,0x64,0x00,0x65,0x65,0x65,0x00,0x66,0x66,0x66,0x00,0x67,0x67,0x67,0x00,
0x68,0x68,0x68,0x00,0x69,0x69,0x69,0x00,0x6a,0x6a,0x6a,0x00,0x6b,0x6b,0x6b,0x00,
0x6c,0x6c,0x6c,0x00,0x6d,0x6d,0x6d,0x00,0x6e,0x6e,0x6e,0x00,0x6f,0x6f,0x6f,0x00,
0x70,0x70,0x70,0x00,0x71,0x71,0x71,0x00,0x72,0x72,0x72,0x00,0x73,0x73,0x73,0x00,
0x74,0x74,0x74,0x00,0x75,0x75,0x75,0x00,0x76,0x76,0x76,0x00,0x77,0x77,0x77,0x00,
0x78,0x78,0x78,0x00,0x79,0x79,0x79,0x00,0x7a,0x7a,0x7a,0x00,0x7b,0x7b,0x7b,0x00,
0x7c,0x7c,0x7c,0x00,0x7d,0x7d,0x7d,0x00,0x7e,0x7e,0x7e,0x00,0x7f,0x7f,0x7f,0x00,
0x80,0x80,0x80,0x00,0x81,0x81,0x81,0x00,0x82,0x82,0x82,0x00,0x83,0x83,0x83,0x00,
0x84,0x84,0x84,0x00,0x85,0x85,0x85,0x00,0x86,0x86,0x86,0x00,0x87,0x87,0x87,0x00,
0x88,0x88,0x88,0x00,0x89,0x89,0x89,0x00,0x8a,0x8a,0x8a,0x00,0x8b,0x8b,0x8b,0x00,
0x8c,0x8c,0x8c,0x00,0x8d,0x8d,0x8d,0x00,0x8e,0x8e,0x8e,0x00,0x8f,0x8f,0x8f,0x00,
0x90,0x90,0x90,0x00,0x91,0x91,0x91,0x00,0x92,0x92,0x92,0x00,0x93,0x93,0x93,0x00,
0x94,0x94,0x94,0x00,0x95,0x95,0x95,0x00,0x96,0x96,0x96,0x00,0x97,0x97,0x97,0x00,
0x98,0x98,0x98,0x00,0x99,0x99,0x99,0x00,0x9a,0x9a,0x9a,0x00,0x9b,0x9b,0x9b,0x00,
0x9c,0x9c,0x9c,0x00,0x9d,0x9d,0x9d,0x00,0x9e,0x9e,0x9e,0x00,0x9f,0x9f,0x9f,0x00,
0xa0,0xa0,0xa0,0x00,0xa1,0xa1,0xa1,0x00,0xa2,0xa2,0xa2,0x00,0xa3,0xa3,0xa3,0x00,
0xa4,0xa4,0xa4,0x00,0xa5,0xa5,0xa5,0x00,0xa6,0xa6,0xa6,0x00,0xa7,0xa7,0xa7,0x00,
0xa8,0xa8,0xa8,0x00,0xa9,0xa9,0xa9,0x00,0xaa,0xaa,0xaa,0x00,0xab,0xab,0xab,0x00,
0xac,0xac,0xac,0x00,0xad,0xad,0xad,0x00,0xae,0xae,0xae,0x00,0xaf,0xaf,0xaf,0x00,
0xb0,0xb0,0xb0,0x00,0xb1,0xb1,0xb1,0x00,0xb2,0xb2,0xb2,0x00,0xb3,0xb3,0xb3,0x00,
0xb4,0xb4,0xb4,0x00,0xb5,0xb5,0xb5,0x00,0xb6,0xb6,0xb6,0x00,0xb7,0xb7,0xb7,0x00,
0xb8,0xb8,0xb8,0x00,0xb9,0xb9,0xb9,0x00,0xba,0xba,0xba,0x00,0xbb,0xbb,0xbb,0x00,
0xbc,0xbc,0xbc,0x00,0xbd,0xbd,0xbd,0x00,0xbe,0xbe,0xbe,0x00,0xbf,0xbf,0xbf,0x00,
0xc0,0xc0,0xc0,0x00,0xc1,0xc1,0xc1,0x00,0xc2,0xc2,0xc2,0x00,0xc3,0xc3,0xc3,0x00,
0xc4,0xc4,0xc4,0x00,0xc5,0xc5,0xc5,0x00,0xc6,0xc6,0xc6,0x00,0xc7,0xc7,0xc7,0x00,
0xc8,0xc8,0xc8,0x00,0xc9,0xc9,0xc9,0x00,0xca,0xca,0xca,0x00,0xcb,0xcb,0xcb,0x00,
0xcc,0xcc,0xcc,0x00,0xcd,0xcd,0xcd,0x00,0xce,0xce,0xce,0x00,0xcf,0xcf,0xcf,0x00,
0xd0,0xd0,0xd0,0x00,0xd1,0xd1,0xd1,0x00,0xd2,0xd2,0xd2,0x00,0xd3,0xd3,0xd3,0x00,
0xd4,0xd4,0xd4,0x00,0xd5,0xd5,0xd5,0x00,0xd6,0xd6,0xd6,0x00,0xd7,0xd7,0xd7,0x00,
0xd8,0xd8,0xd8,0x00,0xd9,0xd9,0xd9,0x00,0xda,0xda,0xda,0x00,0xdb,0xdb,0xdb,0x00,
0xdc,0xdc,0xdc,0x00,0xdd,0xdd,0xdd,0x00,0xde,0xde,0xde,0x00,0xdf,0xdf,0xdf,0x00,
0xe0,0xe0,0xe0,0x00,0xe1,0xe1,0xe1,0x00,0xe2,0xe2,0xe2,0x00,0xe3,0xe3,0xe3,0x00,
0xe4,0xe4,0xe4,0x00,0xe5,0xe5,0xe5,0x00,0xe6,0xe6,0xe6,0x00,0xe7,0xe7,0xe7,0x00,
0xe8,0xe8,0xe8,0x00,0xe9,0xe9,0xe9,0x00,0xea,0xea,0xea,0x00,0xeb,0xeb,0xeb,0x00,
0xec,0xec,0xec,0x00,0xed,0xed,0xed,0x00,0xee,0xee,0xee,0x00,0xef,0xef,0xef,0x00,
0xf0,0xf0,0xf0,0x00,0xf1,0xf1,0xf1,0x00,0xf2,0xf2,0xf2,0x00,0xf3,0xf3,0xf3,0x00,
0xf4,0xf4,0xf4,0x00,0xf5,0xf5,0xf5,0x00,0xf6,0xf6,0xf6,0x00,0xf7,0xf7,0xf7,0x00,
0xf8,0xf8,0xf8,0x00,0xf9,0xf9,0xf9,0x00,0xfa,0xfa,0xfa,0x00,0xfb,0xfb,0xfb,0x00,
0xfc,0xfc,0xfc,0x00,0xfd,0xfd,0xfd,0x00,0xfe,0xfe,0xfe,0x00,0xff,0xff,0xff,0x00,

生成一个图片的代码

#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>

#define IMAGE_SIZE	1280*800
char read_buf[IMAGE_SIZE];

typedef uint16_t WORD;
typedef uint32_t DWORD;
#pragma pack(1)
typedef struct tagBITMAPFILEHEADER{
    WORD bfType;//2
    DWORD bfSize;//4
    WORD bfReserved1;//2
    WORD bfReserved2;//2
    DWORD bfOffBits;//4
} BITMAPFILEHEADER;
#pragma pack()
typedef uint32_t LONG; 
#pragma pack(1)
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; 

static char color_board[] = {
0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x00,0x02,0x02,0x02,0x00,0x03,0x03,0x03,0x00,
0x04,0x04,0x04,0x00,0x05,0x05,0x05,0x00,0x06,0x06,0x06,0x00,0x07,0x07,0x07,0x00,
0x08,0x08,0x08,0x00,0x09,0x09,0x09,0x00,0x0a,0x0a,0x0a,0x00,0x0b,0x0b,0x0b,0x00,
0x0c,0x0c,0x0c,0x00,0x0d,0x0d,0x0d,0x00,0x0e,0x0e,0x0e,0x00,0x0f,0x0f,0x0f,0x00,
0x10,0x10,0x10,0x00,0x11,0x11,0x11,0x00,0x12,0x12,0x12,0x00,0x13,0x13,0x13,0x00,
0x14,0x14,0x14,0x00,0x15,0x15,0x15,0x00,0x16,0x16,0x16,0x00,0x17,0x17,0x17,0x00,
0x18,0x18,0x18,0x00,0x19,0x19,0x19,0x00,0x1a,0x1a,0x1a,0x00,0x1b,0x1b,0x1b,0x00,
0x1c,0x1c,0x1c,0x00,0x1d,0x1d,0x1d,0x00,0x1e,0x1e,0x1e,0x00,0x1f,0x1f,0x1f,0x00,
0x20,0x20,0x20,0x00,0x21,0x21,0x21,0x00,0x22,0x22,0x22,0x00,0x23,0x23,0x23,0x00,
0x24,0x24,0x24,0x00,0x25,0x25,0x25,0x00,0x26,0x26,0x26,0x00,0x27,0x27,0x27,0x00,
0x28,0x28,0x28,0x00,0x29,0x29,0x29,0x00,0x2a,0x2a,0x2a,0x00,0x2b,0x2b,0x2b,0x00,
0x2c,0x2c,0x2c,0x00,0x2d,0x2d,0x2d,0x00,0x2e,0x2e,0x2e,0x00,0x2f,0x2f,0x2f,0x00,
0x30,0x30,0x30,0x00,0x31,0x31,0x31,0x00,0x32,0x32,0x32,0x00,0x33,0x33,0x33,0x00,
0x34,0x34,0x34,0x00,0x35,0x35,0x35,0x00,0x36,0x36,0x36,0x00,0x37,0x37,0x37,0x00,
0x38,0x38,0x38,0x00,0x39,0x39,0x39,0x00,0x3a,0x3a,0x3a,0x00,0x3b,0x3b,0x3b,0x00,
0x3c,0x3c,0x3c,0x00,0x3d,0x3d,0x3d,0x00,0x3e,0x3e,0x3e,0x00,0x3f,0x3f,0x3f,0x00,
0x40,0x40,0x40,0x00,0x41,0x41,0x41,0x00,0x42,0x42,0x42,0x00,0x43,0x43,0x43,0x00,
0x44,0x44,0x44,0x00,0x45,0x45,0x45,0x00,0x46,0x46,0x46,0x00,0x47,0x47,0x47,0x00,
0x48,0x48,0x48,0x00,0x49,0x49,0x49,0x00,0x4a,0x4a,0x4a,0x00,0x4b,0x4b,0x4b,0x00,
0x4c,0x4c,0x4c,0x00,0x4d,0x4d,0x4d,0x00,0x4e,0x4e,0x4e,0x00,0x4f,0x4f,0x4f,0x00,
0x50,0x50,0x50,0x00,0x51,0x51,0x51,0x00,0x52,0x52,0x52,0x00,0x53,0x53,0x53,0x00,
0x54,0x54,0x54,0x00,0x55,0x55,0x55,0x00,0x56,0x56,0x56,0x00,0x57,0x57,0x57,0x00,
0x58,0x58,0x58,0x00,0x59,0x59,0x59,0x00,0x5a,0x5a,0x5a,0x00,0x5b,0x5b,0x5b,0x00,
0x5c,0x5c,0x5c,0x00,0x5d,0x5d,0x5d,0x00,0x5e,0x5e,0x5e,0x00,0x5f,0x5f,0x5f,0x00,
0x60,0x60,0x60,0x00,0x61,0x61,0x61,0x00,0x62,0x62,0x62,0x00,0x63,0x63,0x63,0x00,
0x64,0x64,0x64,0x00,0x65,0x65,0x65,0x00,0x66,0x66,0x66,0x00,0x67,0x67,0x67,0x00,
0x68,0x68,0x68,0x00,0x69,0x69,0x69,0x00,0x6a,0x6a,0x6a,0x00,0x6b,0x6b,0x6b,0x00,
0x6c,0x6c,0x6c,0x00,0x6d,0x6d,0x6d,0x00,0x6e,0x6e,0x6e,0x00,0x6f,0x6f,0x6f,0x00,
0x70,0x70,0x70,0x00,0x71,0x71,0x71,0x00,0x72,0x72,0x72,0x00,0x73,0x73,0x73,0x00,
0x74,0x74,0x74,0x00,0x75,0x75,0x75,0x00,0x76,0x76,0x76,0x00,0x77,0x77,0x77,0x00,
0x78,0x78,0x78,0x00,0x79,0x79,0x79,0x00,0x7a,0x7a,0x7a,0x00,0x7b,0x7b,0x7b,0x00,
0x7c,0x7c,0x7c,0x00,0x7d,0x7d,0x7d,0x00,0x7e,0x7e,0x7e,0x00,0x7f,0x7f,0x7f,0x00,
0x80,0x80,0x80,0x00,0x81,0x81,0x81,0x00,0x82,0x82,0x82,0x00,0x83,0x83,0x83,0x00,
0x84,0x84,0x84,0x00,0x85,0x85,0x85,0x00,0x86,0x86,0x86,0x00,0x87,0x87,0x87,0x00,
0x88,0x88,0x88,0x00,0x89,0x89,0x89,0x00,0x8a,0x8a,0x8a,0x00,0x8b,0x8b,0x8b,0x00,
0x8c,0x8c,0x8c,0x00,0x8d,0x8d,0x8d,0x00,0x8e,0x8e,0x8e,0x00,0x8f,0x8f,0x8f,0x00,
0x90,0x90,0x90,0x00,0x91,0x91,0x91,0x00,0x92,0x92,0x92,0x00,0x93,0x93,0x93,0x00,
0x94,0x94,0x94,0x00,0x95,0x95,0x95,0x00,0x96,0x96,0x96,0x00,0x97,0x97,0x97,0x00,
0x98,0x98,0x98,0x00,0x99,0x99,0x99,0x00,0x9a,0x9a,0x9a,0x00,0x9b,0x9b,0x9b,0x00,
0x9c,0x9c,0x9c,0x00,0x9d,0x9d,0x9d,0x00,0x9e,0x9e,0x9e,0x00,0x9f,0x9f,0x9f,0x00,
0xa0,0xa0,0xa0,0x00,0xa1,0xa1,0xa1,0x00,0xa2,0xa2,0xa2,0x00,0xa3,0xa3,0xa3,0x00,
0xa4,0xa4,0xa4,0x00,0xa5,0xa5,0xa5,0x00,0xa6,0xa6,0xa6,0x00,0xa7,0xa7,0xa7,0x00,
0xa8,0xa8,0xa8,0x00,0xa9,0xa9,0xa9,0x00,0xaa,0xaa,0xaa,0x00,0xab,0xab,0xab,0x00,
0xac,0xac,0xac,0x00,0xad,0xad,0xad,0x00,0xae,0xae,0xae,0x00,0xaf,0xaf,0xaf,0x00,
0xb0,0xb0,0xb0,0x00,0xb1,0xb1,0xb1,0x00,0xb2,0xb2,0xb2,0x00,0xb3,0xb3,0xb3,0x00,
0xb4,0xb4,0xb4,0x00,0xb5,0xb5,0xb5,0x00,0xb6,0xb6,0xb6,0x00,0xb7,0xb7,0xb7,0x00,
0xb8,0xb8,0xb8,0x00,0xb9,0xb9,0xb9,0x00,0xba,0xba,0xba,0x00,0xbb,0xbb,0xbb,0x00,
0xbc,0xbc,0xbc,0x00,0xbd,0xbd,0xbd,0x00,0xbe,0xbe,0xbe,0x00,0xbf,0xbf,0xbf,0x00,
0xc0,0xc0,0xc0,0x00,0xc1,0xc1,0xc1,0x00,0xc2,0xc2,0xc2,0x00,0xc3,0xc3,0xc3,0x00,
0xc4,0xc4,0xc4,0x00,0xc5,0xc5,0xc5,0x00,0xc6,0xc6,0xc6,0x00,0xc7,0xc7,0xc7,0x00,
0xc8,0xc8,0xc8,0x00,0xc9,0xc9,0xc9,0x00,0xca,0xca,0xca,0x00,0xcb,0xcb,0xcb,0x00,
0xcc,0xcc,0xcc,0x00,0xcd,0xcd,0xcd,0x00,0xce,0xce,0xce,0x00,0xcf,0xcf,0xcf,0x00,
0xd0,0xd0,0xd0,0x00,0xd1,0xd1,0xd1,0x00,0xd2,0xd2,0xd2,0x00,0xd3,0xd3,0xd3,0x00,
0xd4,0xd4,0xd4,0x00,0xd5,0xd5,0xd5,0x00,0xd6,0xd6,0xd6,0x00,0xd7,0xd7,0xd7,0x00,
0xd8,0xd8,0xd8,0x00,0xd9,0xd9,0xd9,0x00,0xda,0xda,0xda,0x00,0xdb,0xdb,0xdb,0x00,
0xdc,0xdc,0xdc,0x00,0xdd,0xdd,0xdd,0x00,0xde,0xde,0xde,0x00,0xdf,0xdf,0xdf,0x00,
0xe0,0xe0,0xe0,0x00,0xe1,0xe1,0xe1,0x00,0xe2,0xe2,0xe2,0x00,0xe3,0xe3,0xe3,0x00,
0xe4,0xe4,0xe4,0x00,0xe5,0xe5,0xe5,0x00,0xe6,0xe6,0xe6,0x00,0xe7,0xe7,0xe7,0x00,
0xe8,0xe8,0xe8,0x00,0xe9,0xe9,0xe9,0x00,0xea,0xea,0xea,0x00,0xeb,0xeb,0xeb,0x00,
0xec,0xec,0xec,0x00,0xed,0xed,0xed,0x00,0xee,0xee,0xee,0x00,0xef,0xef,0xef,0x00,
0xf0,0xf0,0xf0,0x00,0xf1,0xf1,0xf1,0x00,0xf2,0xf2,0xf2,0x00,0xf3,0xf3,0xf3,0x00,
0xf4,0xf4,0xf4,0x00,0xf5,0xf5,0xf5,0x00,0xf6,0xf6,0xf6,0x00,0xf7,0xf7,0xf7,0x00,
0xf8,0xf8,0xf8,0x00,0xf9,0xf9,0xf9,0x00,0xfa,0xfa,0xfa,0x00,0xfb,0xfb,0xfb,0x00,
0xfc,0xfc,0xfc,0x00,0xfd,0xfd,0xfd,0x00,0xfe,0xfe,0xfe,0x00,0xff,0xff,0xff,0x00,
};
#pragma pack()
//本函数不支持调色板
int write_bmp(char *name,char *buf)
{
	int fd = 0;
	BITMAPFILEHEADER bit_map_file_header;
	BITMAPINFOHEADER bit_map_info_header;
	fd = open(name,O_RDWR | O_CREAT | O_TRUNC,0666);
	if(fd < 0){
		perror("open");
		return -1;
	}
	printf("%ld,%ld\n",sizeof(BITMAPFILEHEADER),sizeof(BITMAPINFOHEADER));
	printf("open %s ok\n",name);
	memset(&bit_map_file_header,0,sizeof(BITMAPFILEHEADER));
	memset(&bit_map_info_header,0,sizeof(BITMAPINFOHEADER));
	bit_map_file_header.bfType = 0x4D42;
	bit_map_file_header.bfSize = 1280*800 + 54 + 1024;
	bit_map_file_header.bfOffBits = 54 + 1024;//就是位图数据之前的文件头长度,包括调色板。
	
	write(fd,&bit_map_file_header,sizeof(BITMAPFILEHEADER));
	
	bit_map_info_header.biSize = 40;
	bit_map_info_header.biWidth = 1280;
	bit_map_info_header.biHeight = 800;
	bit_map_info_header.biPlanes = 1;
	bit_map_info_header.biBitCount = 8;
	bit_map_info_header.biCompression = 0;// //压缩方式,可以是0,1,2,其中0表示不压缩
	bit_map_info_header.biSizeImage = 1280*800;
	bit_map_info_header.biXPelsPerMeter = 0;
	bit_map_info_header.biYPelsPerMeter = 0;
	bit_map_info_header.biClrUsed = 256;
	bit_map_info_header.biClrImportant = 256;
	write(fd,&bit_map_info_header,sizeof(BITMAPINFOHEADER));
	write(fd,color_board,1024);
	write(fd,buf,1280*800);
	
	
	close(fd);
	
	return 0;
}
int main()
{
	memset(read_buf,0x55,sizeof(read_buf));
	write_bmp("8_256.bmp",read_buf);
	return 0;
}

运行结果

下面这个就是生成的图片的属性:

结束

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
实现将彩色BMP转化为二值的方法如下: 1. 打开BMP文件并读取文件头信息和像数据。 2. 将像数据按行读取,并将每个像素的RGB值转换为灰度值。 3. 对于每个灰度值,如果其大于等于某个阈值,则将其设置为255(白色),否则设置为0(黑色),即将灰度像二值化。 4. 将二值化后的像数据按行写入新的BMP文件中,并更新文件头信息。 下面是一个示例代码,实现了将彩色BMP转化为二值的功能: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #pragma pack(2) // 结构体按2字节对齐 typedef struct { char bfType[2]; // 文件类型,必须为BM 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; // 颜色平面数,必须为1 unsigned short biBitCount; // 每个像素的位数 unsigned int biCompression; // 压缩类型,0表示不压缩 unsigned int biSizeImage; // 像数据大小 int biXPelsPerMeter; // 水平分辨率 int biYPelsPerMeter; // 垂直分辨率 unsigned int biClrUsed; // 调色板中实际使用的颜色数 unsigned int biClrImportant; // 重要的颜色数 } BITMAPINFOHEADER; #pragma pack() // 恢复默认对齐方式 int main(int argc, char *argv[]) { if (argc != 3) { printf("Usage: %s input.bmp output.bmp\n", argv[0]); return 1; } // 打开输入文件 FILE *fIn = fopen(argv[1], "rb"); if (fIn == NULL) { printf("Failed to open input file!\n"); return 1; } // 打开输出文件 FILE *fOut = fopen(argv[2], "wb"); if (fOut == NULL) { printf("Failed to open output file!\n"); fclose(fIn); return 1; } // 读取文件头信息 BITMAPFILEHEADER fileHeader; fread(&fileHeader, sizeof(BITMAPFILEHEADER), 1, fIn); // 读取信息头信息 BITMAPINFOHEADER infoHeader; fread(&infoHeader, sizeof(BITMAPINFOHEADER), 1, fIn); // 判断是否为24位彩色位 if (infoHeader.biBitCount != 24) { printf("Only 24-bit color bitmap is supported!\n"); fclose(fIn); fclose(fOut); return 1; } // 计算每行像素数据的大小(按4字节对齐) int rowSize = ((infoHeader.biWidth * 3) + 3) & ~3; // 计算像数据大小 int dataSize = rowSize * infoHeader.biHeight; // 读取调色板数据(忽略) if (fileHeader.bfOffBits != sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)) { fseek(fIn, fileHeader.bfOffBits - sizeof(BITMAPFILEHEADER) - sizeof(BITMAPINFOHEADER), SEEK_CUR); } // 分配内存读取像数据 unsigned char *data = (unsigned char *)malloc(dataSize); if (data == NULL) { printf("Failed to allocate memory!\n"); fclose(fIn); fclose(fOut); return 1; } fread(data, dataSize, 1, fIn); // 二值化像数据 unsigned char *binaryData = (unsigned char *)malloc(dataSize); if (binaryData == NULL) { printf("Failed to allocate memory!\n"); free(data); fclose(fIn); fclose(fOut); return 1; } int threshold = 128; // 阈值 for (int y = 0; y < infoHeader.biHeight; y++) { for (int x = 0; x < infoHeader.biWidth; x++) { int index = y * rowSize + x * 3; int gray = (data[index] * 30 + data[index + 1] * 59 + data[index + 2] * 11) / 100; // 计算灰度值 binaryData[y * rowSize + x] = (gray >= threshold) ? 255 : 0; // 二值化 } } // 更新文件头信息 fileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dataSize; fileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER); // 写入文件头信息 fwrite(&fileHeader, sizeof(BITMAPFILEHEADER), 1, fOut); fwrite(&infoHeader, sizeof(BITMAPINFOHEADER), 1, fOut); // 写入像数据 fwrite(binaryData, dataSize, 1, fOut); // 关闭文件并释放内存 free(data); free(binaryData); fclose(fIn); fclose(fOut); printf("Done!\n"); return 0; } ``` 该代码使用了灰度化和阈值化的方法将彩色BMP转化为二值,其中灰度值的计算使用了RGB加权平均法。可以通过调整阈值来控制二值化的效果。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

千册

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值