#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; } |
|
来自: ColonelLee > 《Technology》