Chinaunix首页 | 论坛 | 博客
  • 博客访问: 137448
  • 博文数量: 27
  • 博客积分: 1546
  • 博客等级: 上尉
  • 技术积分: 255
  • 用 户 组: 普通用户
  • 注册时间: 2007-09-25 22:46
文章分类
文章存档

2013年(2)

2012年(2)

2011年(7)

2010年(11)

2009年(4)

2008年(1)

我的朋友

分类: LINUX

2009-04-14 13:18:35

前两天因为要测试的系统的屏幕是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;
}

阅读(5414) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2009-04-19 23:11:34

opencv