分享

RGB 888 to RGB 565

 ColonelLee 2010-12-27
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

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));

typedef struct {
    unsigned char r;
    unsigned char g;
    unsigned char b;
}data24;


typedef struct {
    short r;
    short g;
    short b;
}ERROR;

struct data16 {
    unsigned short r:5;
    unsigned short g:6;
    unsigned short b:5;
};


void plus_truncate_uchar(unsigned char *a,char b)
{
//    printf("xxx=%d\n",*a);

    if(int(*a)+b>0xff)*a=0xff;
    else if(int(*a)+b<0)*a=0;
    else *a+=b;    
//printf("yyy=%d\n",*a);
}

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,j, n;
    ERROR error;

    const unsigned long red_mask    = 0xF800ul;
    const unsigned long green_mask  = 0x07E0ul;
    const unsigned long blue_mask   = 0x001Ful;

    short bmpwidth;
    short bmpheight;
    data24 **bmpBuf;

    if (argc != 3) {
        fprintf(stderr, "Wrong usage!\n"
                "Tyr %s <Source BMP file> <Destenation BMP file>\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;

    bmpwidth=in_header2.width;
    bmpheight=in_header2.height;
    bmpBuf = new data24 *[bmpheight];
    bmpBuf[0] = new data24 [bmpwidth*bmpheight];

    for (short i = 0; i<bmpheight; i++) bmpBuf[i]=bmpBuf[0] + bmpwidth*i;

    printf("bmpwidth=%d  bmpheight=%d \n",bmpwidth,bmpheight);


    for(i=0;i<bmpheight;i++)
        for(j=0;j<bmpwidth;j++){

            //printf("%d  %d \n",i,j);
            read(fd_in, in_buff, sizeof(in_buff));

            bmpBuf[i][j].r=in_buff[0];
            bmpBuf[i][j].g=in_buff[1];
            bmpBuf[i][j].b=in_buff[2];

        }


printf("\ndither ing ...\n");    
//////////////////////////////////////////////////////////////////////

    for(i=0;i<bmpheight;i++)
        for(j=0;j<bmpwidth;j++){
            error.r=bmpBuf[i][j].r & 0x07;
////////////////////////////
            if(error.r>=4){
                if((int)bmpBuf[i][j].r + 0x08>0xff)bmpBuf[i][j].r=0xff;
                else bmpBuf[i][j].r += 0x08;
                error.r-=0x08;
            }
////////////////////////////
            error.g=bmpBuf[i][j].g & 0x03;
            if(error.g>=2){
                if((int)bmpBuf[i][j].g + 0x04>0xff)bmpBuf[i][j].g=0xff;
                else bmpBuf[i][j].g += 0x04;
                error.g-=0x04;
            }
////////////////////////////
            error.b=bmpBuf[i][j].b & 0x07;
            if(error.b>=4){
                if((int)bmpBuf[i][j].b + 0x08>0xff)bmpBuf[i][j].b=0xff;
                else bmpBuf[i][j].b += 0x08;
                error.b-=0x08;
            }

            //if(j<10)printf("%d  %d  %d |%d  %d  %d \n",bmpBuf[i][j].r,bmpBuf[i][j].g,bmpBuf[i][j].b,error.r,error.g,error.b);


////////////////////////////
            if(j+1<bmpwidth)plus_truncate_uchar(&bmpBuf[i][j+1].r,(error.r*7)>>4);
            if(i+1<bmpheight){
                if (j-1 >0)plus_truncate_uchar(&bmpBuf[i+1][j-1].r,(error.r*3)>>4);
                       plus_truncate_uchar(&bmpBuf[i+1][j].r,(error.r*5)>>4);
                if (j+1 <bmpwidth)plus_truncate_uchar(&bmpBuf[i+1][j+1].r,(error.r*1)>>4);
            }

////////////////////////////                
            if(j+1<bmpwidth)plus_truncate_uchar(&bmpBuf[i][j+1].g,(error.g*7)>>4);
            if(i+1<bmpheight){
                if (j-1 >0)plus_truncate_uchar(&bmpBuf[i+1][j-1].g,(error.g*3)>>4);
                       plus_truncate_uchar(&bmpBuf[i+1][j].g,(error.g*5)>>4);
                if (j+1 <bmpwidth)plus_truncate_uchar(&bmpBuf[i+1][j+1].g,(error.g*1)>>4);
            }

////////////////////////////
            if(j+1<bmpwidth)plus_truncate_uchar(&bmpBuf[i][j+1].b,(error.b*7)>>4);
            if(i+1<bmpheight){
                if (j-1 >0)plus_truncate_uchar(&bmpBuf[i+1][j-1].b,(error.b*3)>>4);
                       plus_truncate_uchar(&bmpBuf[i+1][j].b,(error.b*5)>>4);
                if (j+1 <bmpwidth)plus_truncate_uchar(&bmpBuf[i+1][j+1].b,(error.b*1)>>4);
            }


////////////////////////////
    }


printf("\nwrite to bmp ...\n");

/////////////////////////////////////////////////////////////////////

    for(i=0;i<bmpheight;i++)
        for(j=0;j<bmpwidth;j++){
                out_buff.r = bmpBuf[i][j].r >> 3;
                out_buff.g = bmpBuf[i][j].g >> 2;
                out_buff.b = bmpBuf[i][j].b >> 3;

            write(fd_out, &out_buff, sizeof(out_buff));

                if ((i*bmpheight+j) % n == 0) {
                        printf("\r  %d%%", (i*bmpheight+j) / 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:
    delete[] bmpBuf[0];
    delete[] bmpBuf;
    close(fd_out);
    close(fd_in);
    return 0;
}

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多