C实现几种对BMP图片文件的处理

#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文件格式。


###新年将至,预祝大家新的一年,万事顺利!感谢您的浏览!

你可能感兴趣的:(C实现几种对BMP图片文件的处理)