一.实验要求
编写8bit像素深度bmp图片与24bit像素深度bmp图片互相转换的程序,将给定的8bitbmp图片和24bitbmp图片分别转换为24bitbmp图片和8bitbmp图片,其中24bit转换成8bit时,转换规则及8bitbmp图片的调色板自行设定。
二.实验原理
1.8bit转换为24bit
只需将原8bit图像实际位图数据通过查找调色板获得对应的RGB数值直接写入到24bit图像的实际位图数据中。
2.24bit转换成8bit
先自行设定8bit图像的调色板及24bit转8bit的转换规则,将24bit图像的实际位图数据根据转换规则转换为8bit图像的实际位图数据。
三.实验过程
1.变量名称对应图
2.8bit转换为24bit:
1)24bit实际位图数据的结构
2)完整代码
#include
#include
int main(int argc,char** argv)
{
char *filename_8,*filename_24;
filename_8=argv[1];
filename_24=argv[2];
BITMAPFILEHEADER eight_bit_f,twenty_4_bit_f;
BITMAPINFOHEADER eight_bit_info,twenty_4_bit_info;
RGBQUAD eight_color_buffer[256];
unsigned char *eight_buffer=NULL,*twenty_4_buffer=NULL;//存放实际位图数据
unsigned char *twenty_4_buffer_wr;
unsigned char *eight_buffer_del,*twenty_4_buffer_del;
FILE *fp_8,*fp_24;
fp_8=fopen(filename_8,"rb");
fp_24=fopen(filename_24,"wb");
fread(&eight_bit_f,sizeof(BITMAPFILEHEADER),1,fp_8);
fread(&eight_bit_info,sizeof(BITMAPINFOHEADER),1,fp_8);
fread(&eight_color_buffer,sizeof(RGBQUAD),256,fp_8);
//*需要判断图像大小是否为四字节整数倍(若不是biSizeImage凑整,并且在二进制文件末尾补零,即在图片第一行前补黑电平行,知道行数为4的整数倍)*/
int size=eight_bit_info.biSizeImage;
eight_buffer=new unsigned char[size];
twenty_4_buffer=new unsigned char[3*size];
if(eight_buffer==NULL||twenty_4_buffer==NULL)
{
printf("can not new unsigned char/n");
}
int size_arc=size;//实际图片大小
//判断宽高是否有一个为四的倍数
if((eight_bit_info.biHeight%4!=0) && (eight_bit_info.biWidth%4!=0))
{
size_arc=eight_bit_info.biHeight*eight_bit_info.biWidth;
}
fread(eight_buffer,sizeof(unsigned char),size,fp_8);
twenty_4_buffer_wr=twenty_4_buffer;
twenty_4_buffer_del=twenty_4_buffer;
eight_buffer_del=eight_buffer;
if(eight_bit_f.bfType!=0x4D42)//判断是否为bmp文件(?直接读出的bfType字节序也是反的吗)
{
printf("please input .bmp file/n");
}
for(int i=0;i
3)注意事项
用windows.h头文件,可直接使用两个header
3.24bit转换为8bit:
1)8bit图像调色板及转换规则的设计
*调色板设计思路:共RGB三个分量,设每个分量有x种取值,故RGB共种取值,令<256且最接近256,可得x=6。R、G、B分别有六种取值,且R、G、B的取值范围都在0~255,故取每个分量六种取值之间的增量为42(42*6=252,最接近256),即以R为例,若24bit图中R取值为0~41则8bit图中R取21,若24bit图中R取值为42~81则8bit图中R取(42+21),以此类推。
*调色盘0~255的划分:
2)关键代码及分析
for(int i=0;i
twenty_4_bit_buffer指向当前像素的B值,twenty_4_bit_buffer+1指向当前像素的G值,twenty_4_bit_buffer+2指向当前像素的R值,将24bit实际位图数据转换为8bit实际位图数据时先判断R值再判断G值最后判断B值,将调色板看作数组,以R为例,若R值在(0,41)之间,则其对应数据一定在调色板256个数组的前36个数组中,即在上图对应的R1区域中,以此类推。
3)完整代码
#include
#include
int main(int argc,char** argv)
{
char *filename_8,*filename_24;
filename_8=argv[1];
filename_24=argv[2];
BITMAPFILEHEADER eight_bit_f,twenty_4_bit_f;
BITMAPINFOHEADER eight_bit_info,twenty_4_bit_info;
RGBQUAD eight_color_buffer[256];
unsigned char *eight_buffer=NULL,*twenty_4_buffer=NULL;//存放实际位图数据
unsigned char *eight_buffer_del,*twenty_4_buffer_del;
unsigned char *eight_buffer_wr;
FILE *fp_8,*fp_24;
fp_8=fopen(filename_8,"wb");
fp_24=fopen(filename_24,"rb");
fread(&twenty_4_bit_f,sizeof(BITMAPFILEHEADER),1,fp_24);
fread(&twenty_4_bit_info,sizeof(BITMAPINFOHEADER),1,fp_24);
//设计8bit调色板
int color=0;
for(int r=0;r<6;r++)
{
for(int g=0;g<6;g++)
{
for(int b=0;b<6;b++)
{
eight_color_buffer[color].rgbBlue=b*42+21;
eight_color_buffer[color].rgbGreen=g*42+21;
eight_color_buffer[color].rgbRed=r*42+21;
eight_color_buffer[color].rgbReserved=0;
color++;
}
}
}
//218到255之间被浪费
while(color<256)
{
eight_color_buffer[color].rgbBlue=eight_color_buffer[color].rgbGreen=eight_color_buffer[color].rgbRed=eight_color_buffer[color].rgbReserved=0;
color++;
}
int size=twenty_4_bit_info.biSizeImage/3;
eight_buffer=new unsigned char[size];
twenty_4_buffer=new unsigned char[3*size];
eight_buffer_wr=eight_buffer;
twenty_4_buffer_del=twenty_4_buffer;
eight_buffer_del=eight_buffer;
if(eight_buffer==NULL||twenty_4_buffer==NULL)
{
printf("can not new unsigned char/n");
}
fread(twenty_4_buffer,sizeof(unsigned char),size*3,fp_24);
int size_arc=size;
if((twenty_4_bit_info.biHeight%4!=0) && (twenty_4_bit_info.biWidth%4!=0))
{
size_arc=twenty_4_bit_info.biHeight*twenty_4_bit_info.biWidth;
}
for(int i=0;i
四.实验结果
转换生成的24bit图像与上课发的24bit图像对比(左边是发的,右边是8bit转24bit生成的)
转换生成的8bit图像与上课发的8bit图像对比(左边是发的,右边是24bit转8bit生成的)
结果分析:转换生成的图片与课上发的图片在色彩上有细微差别,可能是调色板的设计不同造成的。