????????本文讲的书单元色调色处理及BMP文件调色板与数据的关系。
BMP文件开头有固定格式其文件大小是由:文件信息头(14字节),位图信息头(40字节),调色板,位图数据四部分组成。前两者是固定格式,后两者数据是由前两者的信息确定的,这些网上一搜一大堆不在说明。本文用的是C语言自带的<windi.h>下的BITMAPFILEHEADER、BITMAPINFOHEADER、RGBQUAD,位图数据使用char型数组来存储。
? ? ? ? 例一、先读取一个bmp文件,读取文件信息如下?
位图文件头: 文件类型:19778 文件大小:166 保留字:0 保留字:0 实际位图数据的偏移字节数:62 位图信息头: 结构体的长度:40 位图宽:23 位图高:26 biPlanes平面数:1 biBitCount采用颜色位数:1 压缩方式:0 biSizeImage实际位图数据占用的字节数:104 X方向分辨率:0 Y方向分辨率:0 使用的颜色数:0 重要颜色数:0 (0 ?,0 ?,0 ?,0 ?)(255,255,255,0 ?)
有图片信息知道该图片的biBitCount=1即一位表示一个像素,一个字节表示8个像素,调色板的个数为2个,第一个代表全黑,第二个代表全白,当像素为0时用第一个调色板,像素为1时用第二个调色板,然后根据数据值给其上色。
再看其数据蓝色部分,BMP文件数据是从左到右,从上到下读取。
当你读取第一个字节第一位是0,那么就会调用调色板0给其上色即黑色,第二位是0也调用调色板0给其上色,以此类推,当碰到1时就会调用调色板1上色。
所以当我们想换把整体的黑色换色是就可以选择修改第一个调色板的RGB值,白色同理。
但有时我们需要修改其中一部得分颜色是,我们可以选择修改像素数据(这个要好好理解)。
首先我们来看数据,宽度23,高度26,biBitCount=1,当我们要存储宽度23个像素是我们需要23位来存储他们,即2个字节+7位,但是windows规定一行存储的字节数必须是4的倍数,故我们需要的不再是3个字节,而是需要用4个字节去存储这一行23个像素值,多余的全补0,26行一共就需要
104个字节与上面的biSizeImage相同。接下来我们可以用104个char数组去存储像素。每一个数组存储的是一个字节即8位像素,这s时我们可以选择修改这八个像素值来得到我们想要的颜色展示。
源码展示
#include <stdio.h> #include <stdlib.h> #include <Windows.h> /* 文件头信息 */ static BITMAPFILEHEADER BmpHeader; /* 位图头信息 */ static BITMAPINFOHEADER BmpInfo; /* RGB信息 */ static RGBQUAD BmpRGBQuad[2]; /* 输出文件头信息 */ static void BmpShowHead(BITMAPFILEHEADER* sthead); /* 输出文件文图信息 */ static void BmpShowInfo(BITMAPINFOHEADER* stinfo); static void BmpShowRGB(RGBQUAD* st_bmp_rgbquad);
/* 文件读取到数据块中 */ static void BmpBuffer(); static void BmpDiscolour(); /* 位图数据占用的字节数 */ static unsigned long BisizeimageActualValue;
static FILE* fpBmpRead; static FILE* BmpWrite; static unsigned char BmpBuffers[128];//自己改 void main() { ? ? unsigned short index; ? ? index = 0; ? ? BisizeimageActualValue = 0; ? ? BmpBuffer(); ? ? BmpShowHead(&BmpHeader); ? ? BmpShowInfo(&BmpInfo); ? ? BmpShowRGB(&BmpRGBQuad[0]); ? ? BmpShowRGB(&BmpRGBQuad[1]); ? ?? ? ? printf("\n"); ? ? for (index; index < BisizeimageActualValue; index++) { ? ? ? ? if (index % 4 == 0) { ? ? ? ? ? ? printf("\n"); ? ? ? ? } ? ? ? ? printf("%0*X ",sizeof(char)*2, BmpBuffers[index]); ? ? ? ?/* unsigned short_t_index++; */ ? ? } } /* 位图文件头展示 */ static void BmpShowHead(BITMAPFILEHEADER* sthead) { ? ? printf("位图文件头:\n"); ? ? printf("文件类型:%d\n", sthead->bfType); ? ? printf("文件大小:%d\n", sthead->bfSize); ? ? printf("保留字:%d\n", sthead->bfReserved1); ? ? printf("保留字:%d\n", sthead->bfReserved2); ? ? printf("实际位图数据的偏移字节数:%d\n", sthead->bfOffBits);
}
/* 位图信息头展示 */ static void BmpShowInfo(BITMAPINFOHEADER* stinfo) { ? ? printf("位图信息头:\n"); ? ? printf("结构体的长度:%d\n", stinfo->biSize); ? ? printf("位图宽:%d\n", stinfo->biWidth); ? ? printf("位图高:%d\n", stinfo->biHeight); ? ? printf("biPlanes平面数:%d\n", stinfo->biPlanes); ? ? printf("biBitCount采用颜色位数:%d\n", stinfo->biBitCount); ? ? printf("压缩方式:%d\n", stinfo->biCompression); ? ? printf("biSizeImage实际位图数据占用的字节数:%d\n", stinfo->biSizeImage); ? ? printf("X方向分辨率:%d\n", stinfo->biXPelsPerMeter); ? ? printf("Y方向分辨率:%d\n", stinfo->biYPelsPerMeter); ? ? printf("使用的颜色数:%d\n", stinfo->biClrUsed); ? ? printf("重要颜色数:%d\n", stinfo->biClrImportant); }
/* 颜色展示 */ static void BmpShowRGB(RGBQUAD* BmpRGBQuad) { ? ? printf("(%-3d,%-3d,%-3d,%-3d)", ? ? ? ? BmpRGBQuad->rgbRed, BmpRGBQuad->rgbGreen, BmpRGBQuad->rgbBlue, BmpRGBQuad->rgbReserved); } /* 读数据+写数据 */ static void BmpBuffer() { ? ? unsigned short index; ? ? index = 0; ? ? fpBmpRead = fopen("01.bmp","rb+"); ? ? BmpWrite = fopen("03.bmp","wb+"); ? ? fseek(fpBmpRead,0,SEEK_SET); ? ? fread(&BmpHeader, sizeof(BITMAPFILEHEADER), 1, fpBmpRead); ? ? fread(&BmpInfo, sizeof(BITMAPINFOHEADER), 1, fpBmpRead); ? ? fread(&BmpRGBQuad[0], sizeof(RGBQUAD), 1, fpBmpRead); ? ? fread(&BmpRGBQuad[1], sizeof(RGBQUAD), 1, fpBmpRead); ? ? BisizeimageActualValue = BmpInfo.biSizeImage; ? ??
? ? /* 读取位图数据 */ ? ? for (index; index < BisizeimageActualValue; index++) { ? ? ? ? fread(&BmpBuffers[index], sizeof(char), 1, fpBmpRead); ? ? } ? ? vd_s_bmp_discolour(); ? ? fseek(BmpWrite, 0, SEEK_SET); ? ? fwrite(&BmpHeader, sizeof(BITMAPFILEHEADER), 1, BmpWrite); ? ? fwrite(&BmpInfo, sizeof(BITMAPINFOHEADER), 1, BmpWrite); ? ? fwrite(&BmpRGBQuad[0], sizeof(RGBQUAD), 1, BmpWrite); ? ? fwrite(&BmpRGBQuad[1], sizeof(RGBQUAD), 1, BmpWrite);
? ? /* 写入位图数据 */ ? ? for (index = 0; index < BisizeimageActualValue; index++) { ? ? ? ? fwrite(&BmpBuffers[index], sizeof(char), 1, BmpWrite); ? ? } ? ?? ? ? fclose(fpBmpRead); ? ? fclose(BmpWrite); } static void BmpDiscolour() { ? ? /*U2 u2_t_index; ? ? for (u2_t_index=0; u2_t_index < BisizeimageActualValue; u2_t_index++) { ? ? ? ? BmpBuffers[u2_t_index] = 0XAA; ? ? }*/ }
|