1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include <stdio.h> 18 #include <stdlib.h> 19 #include <unistd.h> 20 #include <string.h> 21 22 #define to565(r,g,b) \ 23 ((((r) >> 3) << 11) | (((g) >> 2) << 5) | ((b) >> 3)) 24 25 #define from565_r(x) ((((x) >> 11) & 0x1f) * 255 / 31) 26 #define from565_g(x) ((((x) >> 5) & 0x3f) * 255 / 63) 27 #define from565_b(x) (((x) & 0x1f) * 255 / 31) 28 29 void to_565_raw(void) 30 { 31 unsigned char in[3]; 32 unsigned short out; 33 34 while(read(0, in, 3) == 3) { 35 out = to565(in[0],in[1],in[2]); 36 write(1, &out, 2); 37 } 38 return; 39 } 40 41 void to_565_raw_dither(int width) 42 { 43 unsigned char in[3]; 44 unsigned short out; 45 int i = 0; 46 int e; 47 48 int* error = malloc((width+2) * 3 * sizeof(int)); 49 int* next_error = malloc((width+2) * 3 * sizeof(int)); 50 memset(error, 0, (width+2) * 3 * sizeof(int)); 51 memset(next_error, 0, (width+2) * 3 * sizeof(int)); 52 error += 3; // array goes from [-3..((width+1)*3+2)] 53 next_error += 3; 54 55 while(read(0, in, 3) == 3) { 56 int r = in[0] + error[i*3+0]; 57 int rb = (r < 0) ? 0 : ((r > 255) ? 255 : r); 58 59 int g = in[1] + error[i*3+1]; 60 int gb = (g < 0) ? 0 : ((g > 255) ? 255 : g); 61 62 int b = in[2] + error[i*3+2]; 63 int bb = (b < 0) ? 0 : ((b > 255) ? 255 : b); 64 65 out = to565(rb, gb, bb); 66 write(1, &out, 2); 67 68 #define apply_error(ch) { \ 69 next_error[(i-1)*3+ch] += e * 3 / 16; \ 70 next_error[(i)*3+ch] += e * 5 / 16; \ 71 next_error[(i+1)*3+ch] += e * 1 / 16; \ 72 error[(i+1)*3+ch] += e - ((e*1/16) + (e*3/16) + (e*5/16)); \ 73 } 74 75 e = r - from565_r(out); 76 apply_error(0); 77 78 e = g - from565_g(out); 79 apply_error(1); 80 81 e = b - from565_b(out); 82 apply_error(2); 83 84 #undef apply_error 85 86 ++i; 87 if (i == width) { 88 // error <- next_error; next_error <- 0 89 int* temp = error; error = next_error; next_error = temp; 90 memset(next_error, 0, (width+1) * 3 * sizeof(int)); 91 i = 0; 92 } 93 } 94 95 free(error-3); 96 free(next_error-3); 97 98 return; 99 } 100 101 void to_565_rle(void) 102 { 103 unsigned char in[3]; 104 unsigned short last, color, count; 105 unsigned total = 0; 106 count = 0; 107 108 while(read(0, in, 3) == 3) { 109 color = to565(in[0],in[1],in[2]); 110 if (count) { 111 if ((color == last) && (count != 65535)) { 112 count++; 113 continue; 114 } else { 115 write(1, &count, 2); 116 write(1, &last, 2); 117 total += count; 118 } 119 } 120 last = color; 121 count = 1; 122 } 123 if (count) { 124 write(1, &count, 2); 125 write(1, &last, 2); 126 total += count; 127 } 128 fprintf(stderr,"%d pixels\n",total); 129 } 130 131 int main(int argc, char **argv) 132 { 133 if ((argc == 2) && (!strcmp(argv[1],"-rle"))) { 134 to_565_rle(); 135 } else { 136 if (argc > 2 && (!strcmp(argv[1], "-w"))) { 137 to_565_raw_dither(atoi(argv[2])); 138 } else { 139 to_565_raw(); 140 } 141 } 142 return 0; 143 } 144