This source file includes following definitions.
- set_12_pixel
- get_12_pixel
- get_10_pixel
- set_10_pixel
- get_8_pixel
- set_8_pixel
- get_16_pixel
- set_16_pixel
- swap_bytes
- find_op
- usage
- main
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35 #include <stdio.h>
36 #include <stdint.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <sys/stat.h>
40 #include <assert.h>
41
42 typedef unsigned (*get_pixel_func_t)(uint8_t *p, unsigned row_bytes, unsigned x, unsigned y);
43 typedef void (*set_pixel_func_t)(uint8_t *p, unsigned row_bytes, unsigned x, unsigned y, unsigned value);
44 typedef unsigned (*convert_pixel_func_t)(unsigned value);
45
46 typedef struct {
47 const char *name;
48 unsigned ibpp;
49 unsigned obpp;
50 get_pixel_func_t get_pixel;
51 set_pixel_func_t set_pixel;
52 } op_def_t;
53
54 void set_12_pixel(uint8_t *p,unsigned row_bytes, unsigned x, unsigned y, unsigned value)
55 {
56 uint8_t* addr=p+y*row_bytes+(x>>2)*6;
57 switch (x%4) {
58 case 0:
59 addr[0] = (addr[0]&0x0F) | (unsigned char)(value << 4);
60 addr[1] = (unsigned char)(value >> 4);
61 break;
62 case 1:
63 addr[0] = (addr[0]&0xF0) | (unsigned char)(value >> 8);
64 addr[3] = (unsigned char)value;
65 break;
66 case 2:
67 addr[2] = (unsigned char)(value >> 4);
68 addr[5] = (addr[5]&0x0F) | (unsigned char)(value << 4);
69 break;
70 case 3:
71 addr[4] = (unsigned char)value;
72 addr[5] = (addr[5]&0xF0) | (unsigned char)(value >> 8);
73 break;
74 }
75 }
76
77 unsigned get_12_pixel(uint8_t *p, unsigned row_bytes, unsigned x, unsigned y)
78 {
79 uint8_t* addr = p + y * row_bytes + (x>>2) * 6;
80 switch (x&3) {
81 case 0: return ((unsigned short)(addr[1]) << 4) | (addr[0] >> 4);
82 case 1: return ((unsigned short)(addr[0] & 0x0F) << 8) | (addr[3]);
83 case 2: return ((unsigned short)(addr[2]) << 4) | (addr[5] >> 4);
84 case 3: return ((unsigned short)(addr[5] & 0x0F) << 8) | (addr[4]);
85 }
86 return 0;
87 }
88
89 unsigned get_10_pixel(uint8_t *p, unsigned row_bytes, unsigned x, unsigned y)
90 {
91 uint8_t* addr = p + y * row_bytes + (x>>3) * 10;
92 switch (x&7) {
93 case 0: return ((0x3fc&(((unsigned short)addr[1])<<2)) | (addr[0] >> 6));
94 case 1: return ((0x3f0&(((unsigned short)addr[0])<<4)) | (addr[3] >> 4));
95 case 2: return ((0x3c0&(((unsigned short)addr[3])<<6)) | (addr[2] >> 2));
96 case 3: return ((0x300&(((unsigned short)addr[2])<<8)) | (addr[5]));
97 case 4: return ((0x3fc&(((unsigned short)addr[4])<<2)) | (addr[7] >> 6));
98 case 5: return ((0x3f0&(((unsigned short)addr[7])<<4)) | (addr[6] >> 4));
99 case 6: return ((0x3c0&(((unsigned short)addr[6])<<6)) | (addr[9] >> 2));
100 case 7: return ((0x300&(((unsigned short)addr[9])<<8)) | (addr[8]));
101 }
102 return 0;
103 }
104
105 void set_10_pixel(uint8_t *p, unsigned row_bytes, unsigned x, unsigned y, unsigned value)
106 {
107 uint8_t* addr = p + y*row_bytes + (x>>3)*10;
108 switch (x&7) {
109 case 0:
110 addr[0] = (addr[0]&0x3F)|(value<<6);
111 addr[1] = value>>2;
112 break;
113 case 1:
114 addr[0] = (addr[0]&0xC0)|(value>>4);
115 addr[3] = (addr[3]&0x0F)|(value<<4);
116 break;
117 case 2:
118 addr[2] = (addr[2]&0x03)|(value<<2);
119 addr[3] = (addr[3]&0xF0)|(value>>6);
120 break;
121 case 3:
122 addr[2] = (addr[2]&0xFC)|(value>>8);
123 addr[5] = value;
124 break;
125 case 4:
126 addr[4] = value>>2;
127 addr[7] = (addr[7]&0x3F)|(value<<6);
128 break;
129 case 5:
130 addr[6] = (addr[6]&0x0F)|(value<<4);
131 addr[7] = (addr[7]&0xC0)|(value>>4);
132 break;
133 case 6:
134 addr[6] = (addr[6]&0xF0)|(value>>6);
135 addr[9] = (addr[9]&0x03)|(value<<2);
136 break;
137 case 7:
138 addr[8] = value;
139 addr[9] = (addr[9]&0xFC)|(value>>8);
140 break;
141 }
142 }
143
144 unsigned get_8_pixel(uint8_t *buf, unsigned row_bytes, unsigned x, unsigned y)
145 {
146 return buf[row_bytes*y+x];
147 }
148
149 void set_8_pixel(uint8_t *buf, unsigned row_bytes, unsigned x, unsigned y, unsigned value)
150 {
151 buf[row_bytes*y+x] = (uint8_t)value;
152 }
153
154 unsigned get_16_pixel(uint8_t *buf, unsigned row_bytes, unsigned x, unsigned y)
155 {
156 return ((uint16_t *)buf)[(row_bytes/2)*y + x];
157 }
158
159 void set_16_pixel(uint8_t *buf, unsigned row_bytes, unsigned x, unsigned y, unsigned value)
160 {
161 ((uint16_t *)buf)[(row_bytes/2)*y + x] = (uint16_t)value;
162 }
163
164 void swap_bytes(unsigned char *src, unsigned char *dst, size_t size)
165 {
166 unsigned char c1, c2;
167 while(size>1)
168 {
169 c1=*src++;
170 c2=*src++;
171 *dst++=c2;
172 *dst++=c1;
173 size-=2;
174 }
175 }
176
177 #define OP_DEF(X,Y) {#X "to" #Y, X, Y, get_##X##_pixel, set_##Y##_pixel},
178 op_def_t op_defs[]={
179 OP_DEF(8,10)
180 OP_DEF(8,12)
181 OP_DEF(8,16)
182 OP_DEF(10,8)
183 OP_DEF(10,12)
184 OP_DEF(10,16)
185 OP_DEF(12,8)
186 OP_DEF(12,10)
187 OP_DEF(12,16)
188 OP_DEF(16,8)
189 OP_DEF(16,10)
190 OP_DEF(16,12)
191 };
192
193 #define NUM_OP_DEFS (sizeof(op_defs)/sizeof(op_def_t))
194
195 const op_def_t *find_op(const char *name)
196 {
197 unsigned i;
198 for( i=0; i < NUM_OP_DEFS; i++) {
199 if(strcmp(name,op_defs[i].name) == 0)
200 return op_defs+i;
201 }
202 return NULL;
203 }
204
205 void usage()
206 {
207 unsigned i;
208 fprintf(stderr,"Usage: -<op> -w=<width> -h=<height> [-pgm] [-noshift] <infile> <outfile>\n");
209 fprintf(stderr," op one of:");
210 for( i=0; i < NUM_OP_DEFS; i++) {
211 fprintf(stderr," %s",op_defs[i].name);
212 }
213 fprintf(stderr,"\n");
214 exit(1);
215 }
216
217 int main(int argc, char**argv)
218 {
219 uint8_t *in_data;
220 uint8_t *out_data;
221 FILE *fp;
222 char *iname=NULL;
223 char *oname=NULL;
224
225 const op_def_t *op=NULL;
226
227 unsigned height=0;
228 unsigned width=0;
229 unsigned npixels;
230 unsigned osize;
231
232 unsigned pixel_shift=1;
233 unsigned pgm_format=0;
234 int bpp_diff;
235
236 struct stat st;
237
238 size_t rcount;
239
240 unsigned i;
241
242 for(i = 1; i < (unsigned)argc; i++) {
243 if ( strncmp(argv[i],"-h=",3) == 0 ) {
244 height=atoi(argv[i]+3);
245 }
246 else if ( strncmp(argv[i],"-w=",3) == 0 ) {
247 width=atoi(argv[i]+3);
248 }
249 else if ( strcmp(argv[i],"-noshift") == 0 ) {
250 pixel_shift=0;
251 }
252 else if( strcmp(argv[i],"-pgm") == 0 ) {
253 pgm_format=1;
254 }
255 else if ( argv[i][0]=='-' ) {
256 if( !(op = find_op(argv[i]+1))) {
257 fprintf(stderr,"%s: unknown option %s\n",argv[0],argv[i]);
258 usage();
259 }
260 }
261 else {
262 if(!iname) {
263 iname=argv[i];
264 }
265 else if (!oname) {
266 oname=argv[i];
267 }
268 else {
269 fprintf(stderr,"%s: unknown option %s\n",argv[0],argv[i]);
270 usage();
271 }
272 }
273 }
274 if(!iname) {
275 fprintf(stderr,"%s: missing input file\n",argv[0]);
276 usage();
277 }
278 if(!oname) {
279 fprintf(stderr,"%s: missing output file\n",argv[0]);
280 usage();
281 }
282 if(!op) {
283 fprintf(stderr,"%s: no op given\n",argv[0]);
284 usage();
285 }
286 if(!height || !width) {
287 fprintf(stderr,"%s: invalid dimensions\n",argv[0]);
288 usage();
289 }
290
291 if(stat(iname,&st) != 0) {
292 fprintf(stderr,"%s: bad input file %s\n",argv[0],iname);
293 exit(1);
294 }
295
296 if((width*op->ibpp)%8 != 0) {
297 fprintf(stderr,"WARNING: width %u not an integral number of bytes at %u bpp\n",width,op->ibpp);
298 }
299 if((width*op->obpp)%8 != 0) {
300 fprintf(stderr,"WARNING: width %u not an integral number of bytes at %u bpp\n",width,op->obpp);
301 }
302 if(pgm_format && op->obpp!=8 && op->obpp!=16) {
303 fprintf(stderr,"WARNING: Portable Gray Map (PGM) format supports only 8 or 16 bpp.\n");
304 pgm_format=0;
305 }
306
307 in_data=malloc(st.st_size);
308 assert(in_data);
309
310 fp=fopen(iname,"rb");
311 assert(fp);
312
313 rcount=fread(in_data,1,st.st_size,fp);
314 assert(rcount==(size_t)st.st_size);
315
316 fclose(fp);
317
318 npixels=height*width;
319 if((npixels*op->ibpp) >> 3 != st.st_size) {
320 fprintf(stderr,"%s: %s mismatched size (%u*%u*%u)/8 -> %u != %u\n",
321 argv[0], iname, width, height, op->ibpp, (npixels*op->ibpp) >> 3, (unsigned)st.st_size);
322 exit(1);
323 }
324 osize = (npixels*op->obpp) >> 3;
325 out_data=malloc(osize);
326 assert(out_data);
327
328 fprintf(stderr,"input: %s %ux%u %u bpp %u bytes\n",iname, width, height, op->ibpp, (unsigned)(st.st_size));
329 fprintf(stderr,"output: %s %u bpp %u bytes\n", oname, op->obpp, osize);
330
331 bpp_diff = op->obpp - op->ibpp;
332 if(pixel_shift) {
333 if(bpp_diff < 0)
334 fprintf(stderr," discard lower %d bits\n",-bpp_diff);
335 else
336 fprintf(stderr," multiply pixel values %d\n",1 << bpp_diff);
337 }
338 else if(bpp_diff < 0) {
339 fprintf(stderr," discard upper %d bits\n",-bpp_diff);
340 }
341
342 {
343 unsigned pixel_value;
344 unsigned in_row_bytes=(width*op->ibpp)>>3;
345 unsigned out_row_bytes=(width*op->obpp)>>3;
346 for(i=0; i<npixels; i++) {
347 pixel_value = op->get_pixel(in_data, in_row_bytes, i%width, i/width);
348 if (pixel_shift) {
349 if (bpp_diff < 0) {
350 pixel_value >>= -bpp_diff;
351 }
352 else if (bpp_diff > 0) {
353 pixel_value <<= bpp_diff;
354 }
355 }
356 op->set_pixel(out_data, out_row_bytes, i%width, i/width, pixel_value);
357 }
358 }
359
360 fp=fopen(oname,"wb");
361 assert(fp);
362 if(pgm_format)
363 {
364 fprintf(fp, "P5\n%d\n%d\n%d\n", width, height, (1 << op->obpp)-1);
365 if(op->obpp==16) swap_bytes(out_data, out_data, osize);
366 }
367 fwrite(out_data, 1, osize, fp);
368 fclose(fp);
369
370 free(in_data);
371 free(out_data);
372 fprintf(stderr,"done\n");
373 return 0;
374 }