#C实现几种对BMP图片文件的处理
##什么是BMP文件?
BMP(全称Bitmap-File)是Windows操作系统中的一种标准的图像文件格式,能够被多种Windows应用程序所支持。随着Windows操作系统的流行与丰富的Windows应用程序的开发,BMP位图格式理所当然地被广泛应用。这种格式的特点是包含的图像信息较丰富,几乎不进行压缩,但由此导致了它与生俱生来的缺点–占用磁盘空间过大。所以,目前BMP在单机上比较流行。
BMP的格式组成:
1、位图头文件数据结构,它包含BMP图像文件的类型、显示内容等信息;
2、位图信息数据结构,它包含有BMP图像的宽、高、压缩方法,以及定义颜色等信息;
3、调色板,这个部分是可选的,有些位图需要调色板,有些位图,比如真彩色图(24位的BMP)就不需要调色板;
4、位图数据,这部分的内容根据BMP位图使用的位数不同而不同,在24位图中直接使用RGB,而其他的小于24位的使用调色板中颜色索引值;
BMP的位图类型:
其位图一共有两种类型,设备相关位图和设备无关位图;
1、设备无关位图 (Device-Independent Bitmap)
DIB位图包含下列的颜色和尺寸信息:原始设备(即创建图片的设备)的颜色格式;原始设备的分辨率;原始设备的调色板;一个位数位,由红、绿、蓝(RGB)三个值代表一个像素;一个数组压缩标志,用于表明数据的压缩方案;
2、设备相关位图 (Device-Dependent Bitmaps)
DDB位图是被一个单个结构BITMAP所描述,这个结构的成员标明了该位图的宽度、高度、设备的颜色格式等信息;
[^注]:此板块内容来源于百度
##对BMP图片文件进行了什么样的处理?
小编编写了一个基于C program的简单程序,并拥有反色、平铺、为图片加水印的三种功能。下面我就为大家解释一下这三种功能,反色处理顾名思义,就是将图片的整体颜色进行反转处理。比如说原来的图片是白色的,背景是黑的,反色之后的图片就是黑的,背景就会变成白色的了;平铺这一功能,就是将一张图片在一整个版面上铺满;为图片加水印就不用多进行什么解释了,很常用。即:将一个尺寸较小得到透明度为50%的图片附在另一张主图片上。
下面就为大家展示一下源代码!
##源代码
#define _CRT_SECURE_NO_WARNINGS
#include
#include
//右键点击项目的属性,在配置属性、c/c++、代码生成、结构成员对齐
//选择 "1字节"
struct bmpFileHeader {
short bfType; //0x00起始偏移
int bfSize; //0x02 //文件大小
int bfReserve; //0x06
int bfoffBits; //0x0a
int bitSize; //0x0e 为40
int biWidth; //0x12 ****//位图宽
int biHeight; //0x16 *****//位图高
short biPlanes; //0x1a 为1
short biBitCount; //0x1c ****//采用颜色位数,可以是1,2,4,8,16,24,新的可以是32
int biCompression; //0x1e //压缩方式,可以是0,1,2,其中0表示不压缩
int biSizeImage; //0x22 //实际位图数据占用的字节数
int biXPlosPerMeter;//0x26
int biYPlosPerMeter;//0x2a
int biClrUsed; //0x2e
int biClrImportant; //0x32
} header;
//计算此图像每行应占多少字节
int comp_linesize(struct bmpFileHeader * pheader)
{
int w = pheader->biWidth;//图像宽,一行多少像素
int size = w * 3;
if (size % 4 != 0)
size += 4 - size % 4;
return size;
}
void printMsg(struct bmpFileHeader* pheader)
{
printf("此图像宽:%d,高:%d,一行占:%d字节\n", pheader->biWidth, pheader->biHeight, comp_linesize(pheader));
}
void fanse()
{
char file1[200], file2[200];
printf("请输入原始图像文件:\n");
scanf("%s", file1);
FILE* fp1, * fp2;//文件指针
fp1 = fopen(file1, "rb");
if (fp1 == NULL)
{
printf("原始图像不存在\n");
return;
}
fread(&header, sizeof(struct bmpFileHeader), 1, fp1);//图像的头
int linesize = comp_linesize(&header);
int txsize = linesize * header.biHeight;
char* bmpduzi = (char*)malloc(txsize);
fread(bmpduzi, txsize, 1, fp1);//读图像肚子
printMsg(&header);
fclose(fp1);
for (int i = 0; i < txsize; i++)
bmpduzi[i] = 255 - bmpduzi[i];
printf("反色后图像文件存在哪啊,叫啥名啊?:\n");
scanf("%s", file2);
fp2 = fopen(file2, "wb");
if (fp2 == NULL)
{
printf("反色图像不存在\n");
return;
}
fwrite(&header, sizeof(struct bmpFileHeader), 1, fp2);
fwrite(bmpduzi, txsize, 1, fp2);
fclose(fp2);
}
void pingpu()
{
char file1[200], file2[200];
printf("请输入原始图像文件:");
scanf("%s", file1);
FILE* fp1, * fp2;
fp1 = fopen(file1, "rb");
if (fp1 == NULL)
{
printf("原始图像不存在\n");
return;
}
fread(&header, sizeof(struct bmpFileHeader), 1, fp1);
int linesize = comp_linesize(&header);
int txsize = linesize * header.biHeight;
char * bmpduzi = (char*)malloc(txsize);
fread(bmpduzi, txsize, 1, fp1);
printMsg(&header);
fclose(fp1);
printf("想平铺n行,每行m个。请输入n和m:");
int m, n, linesize2;
struct bmpFileHeader header2;
scanf("%d %d", &n, &m);
header2 = header;
header2.biWidth = header.biWidth * m;
header2.biHeight = header.biHeight * n;
linesize2 = comp_linesize(&header2);
int duzi2size = linesize2 * header.biHeight;
char* bmpduzi2 = (char*)malloc(linesize2 * header.biHeight);//用于存储原始图像横向平铺的数据
for (int j = 0; j < header.biHeight; j++)//bmpduzi是header.biHeight行
for (int i = 0; i < m; i++)//平铺m次
for (int k = 0; k < header.biWidth * 3; k++)//原始每行header.biwidth*3个字节
bmpduzi2[linesize2 * j + i * header.biWidth * 3 + k] = bmpduzi[linesize * j + k];
printf("平铺图像文件存在哪啊,叫啥名啊?:\n");
scanf("%s", file2);
fp2 = fopen(file2, "wb");
if (fp2 == NULL)
{
printf("目标图像不存在\n");
return;
}
fwrite(&header2, sizeof(struct bmpFileHeader), 1, fp2);
for (int i = 0; i < n; i++)
fwrite(bmpduzi2,duzi2size,1,fp2);
fclose(fp2);
}
void shuiyin()
{
char file1[200], file2[200],file3[200];
printf("请输入原始图像文件:\n");
scanf("%s", file1);
printf("请输入水印图像文件:\n");
scanf("%s", file2);
FILE* fp1, * fp2,* fp3;
fp1 = fopen(file1, "rb");
if (fp1 == NULL)
{
printf("原始图像不存在\n");
return;
}
fread(&header, sizeof(struct bmpFileHeader), 1, fp1);
int linesize = comp_linesize(&header);
int txsize = linesize * header.biHeight;
unsigned char* bmpduzi = (unsigned char*)malloc(txsize);
fread(bmpduzi, txsize, 1, fp1);
printMsg(&header);
fclose(fp1);
struct bmpFileHeader header2;
fp2 = fopen(file2, "rb");
if (fp2 == NULL)
{
printf("原始图像不存在\n");
return;
}
fread(&header2, sizeof(struct bmpFileHeader), 1, fp2);
int linesize2 = comp_linesize(&header2);
int txsize2= linesize * header2.biHeight;
int duzi2size = linesize2 * header.biHeight;
unsigned char* bmpduzi2 = (unsigned char*)malloc(txsize2);
fread(bmpduzi2, txsize2, 1, fp2);
printMsg(&header2);
fclose(fp2);
for (int i = 0; i < header2.biHeight; i++)
for (int j = 0; j < header2.biWidth * 3; j++)
bmpduzi[linesize * i + j] = bmpduzi2[linesize2 * i + j]*0.5+bmpduzi[linesize*i+j]*0.5;
printf("水印图像文件存在哪啊,叫啥名啊?:\n");
scanf("%s", file3);
fp3 = fopen(file3, "wb");
if (fp3 == NULL)
{
printf("水印图像不存在\n");
return;
}
fwrite(&header, sizeof(struct bmpFileHeader), 1, fp3);
fwrite(bmpduzi, txsize, 1, fp3);
fclose(fp3);
}
int main()
{
printf("欢迎来到Isaac的图像处理程序,请输入对应的数字选择相应的功能:\n");
printf("1:请输入1代表图像反色处理。\n");
printf("2:请输入2代表图像平铺。\n");
printf("3:请输入3代表图像加水印。\n");
printf("0:输入0代表退出本系统。\n");
int function;
while (1)
{
scanf_s("%d", &function);
switch (function)
{
case 1:
fanse();
break;
case 2:
pingpu();
break;
case 3:
shuiyin();
break;
case 0:
return 0;
}
}
}
[^1]:上述程序只能处理BMP图片文件,所以在使用该程序之前要将图片转成BMP文件格式。
###新年将至,预祝大家新的一年,万事顺利!感谢您的浏览!