前两天因为要测试的系统的屏幕是16位色的,需要5-6-5格式的位图来进行测试,随手翻了一下电脑上的图片,都是24位的。找了半天竟然没有找到合适的24位转16位的软件。GIMP是找了半天,还是不会用来把24位的转换为16位的。convert命令倒是有个colors参数,但是转出来,8位的还像,但是,一张800×480的图片转了一中午,竟然,查看结果还是24位的。很是郁闷。
想想图片格式转换还不算太难,BMP的格式其实挺简单,对着网上的说明,自己写了一个临时的C程序来完成这个任务。其实关键就是两个文件头的数据结构,一个是文件基本信息,包括了文件类型,大小和位图阵列在文件中的偏移量。而紧接着这个头的是一个具体的位图信息头,其实网上有比较详细的资料比如:和,所以不再赘述。
但是里边还是有细节是我实验得出的,比如,文件头就是类型是’BM’的位图,文件头就是54字节,颜色表或者16位位图的颜色掩码也算在数据里。颜色掩码的分别是三个32位无符号整数,从前到后分别代表红、绿、蓝的分量所占的位。而且24位使用BI_RGB(0)模式存储,除了54字节的文件头外,都是图像数据或者填充。我这次处理的图片不需要处理对齐问题,就没有仔细考虑这个问题,程序中也没有。很重要的一点,这里的多字节数据存储方式都是小端。我是试验出来的~貌似没有地方讲这个问题~而且16位位图的一个像素占两个字节,是一个16位的整数,也是按照小端模式来存储的……谨记之~
顺便传上这个应急程序,连read、write的状态都没有检查……
代码如下:
#include
#include
#include
#include
#include
#include
struct header1 {
unsigned short type;
size_t size;
unsigned short r1;
unsigned short r2;
size_t off;
} __attribute__((packed));
struct header2 {
size_t size;
long width;
long height;
unsigned short planes;
unsigned short bit_count;
unsigned long compression;
size_t img_size;
long x_pels_per_meter;
long y_pels_per_meter;
unsigned long color_used;
unsigned long color_important;
} __attribute__((packed));
struct data16 {
unsigned short r:5;
unsigned short g:6;
unsigned short b:5;
};
int main(int argc, char *argv[])
{
int fd_in, fd_out;
struct header1 in_header1;
struct header2 in_header2;
unsigned char in_buff[3] = {0};
struct data16 out_buff;
size_t i, n;
const unsigned long red_mask = 0xF800ul;
const unsigned long green_mask = 0x07E0ul;
const unsigned long blue_mask = 0x001Ful;
if (argc != 3) {
fprintf(stderr, "Wrong usage!\n"
"Tyr %s \n", argv[0]);
return -1;
}
fd_in = open(argv[1], O_RDONLY);
fd_out = open(argv[2], O_WRONLY | O_TRUNC | O_CREAT,
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
if (fd_in == -1 || fd_out == -1) {
perror("Open file failed");
}
read(fd_in, &in_header1, sizeof(in_header1));
if (in_header1.type != 0x4d42) {
fprintf(stderr, "%s isn't BMP file\n", argv[1]);
goto end;
}
n = (in_header1.size - 54) / 3;
in_header1.size = n * 2 + 54 + 12;
in_header1.off += 12;
read(fd_in, &in_header2, sizeof(in_header2));
if (in_header2.bit_count != 24) {
fprintf(stderr, "The BMP file %s isn't 24 bit.\n", argv[1]);
goto end;
}
in_header2.bit_count = 16;
in_header2.compression = 3ul;
in_header2.img_size = in_header2.img_size / 3 * 2;
write(fd_out, &in_header1, sizeof(in_header1));
write(fd_out, &in_header2, sizeof(in_header2));
write(fd_out, &red_mask, sizeof(red_mask));
write(fd_out, &green_mask, sizeof(green_mask));
write(fd_out, &blue_mask, sizeof(blue_mask));
n /= 100;
i = 0;
printf("Converting...\n");
while (read(fd_in, in_buff, sizeof(in_buff))) {
out_buff.r = in_buff[0] >> 3;
out_buff.g = in_buff[1] >> 2;
out_buff.b = in_buff[2] >> 3;
write(fd_out, &out_buff, sizeof(out_buff));
if (i++ % n == 0) {
printf("\r %d%%", i / n);
fflush(stdout);
}
}
printf("\r 100%%\n");
printf("24 bit BMP %s to 16 bit (5-6-5) BMP %s ok!\n", argv[1], argv[2]);
end:
close(fd_out);
close(fd_in);
return 0;
}
阅读(5471) | 评论(1) | 转发(0) |