source: trunk/tools/rawconvert.c @ 3421

Revision 2574, 9.6 KB checked in by philmoz, 14 months ago (diff)

Add MD & Live View buffer testing using the AF LED.
http://chdk.setepontos.com/index.php?topic=9366.msg96633#msg96633

  • Property svn:eol-style set to native
Line 
1/*
2A small tools to convert CHDK 10 and 12 bit raws to 8 or 16 bit grayscale for inspection
3Can also covert to CHDK formats
4
5Usage:
6rawconvert -<op> -w=<width> -h=<height> [-noshift] [-pgm] <infile> <outfile>
7where <op> is XtoY with X and Y being the source and destination BPP
8by default
9 converting to lower BPP discards the lower bits of the input value.
10 converting to higher BPP shifts the input so the a max value input pixel will be a max value output pixel
11if -noshift is specified
12 converting to a lower BPP discards the upper bits
13 converting to a higher BPP leaves the values unchanged
14
15 NOTES:
16 Host is assumed to be little endian!
17 This is a debugging tool not an imaging tool.
18 
19LINKS:
20CHDK wikia article:     http://chdk.wikia.com/wiki/CHDK_Tools#rawconvert.c
21
22REVISIONS:
231. Initial release. Author: reyalP (28-Oct-2009)
24    CHDK trunk SVN changeset #823 --> http://tools.assembla.com/chdk/changeset/823
25    Forum link: http://chdk.setepontos.com/index.php/topic,2509.msg42402.html#msg42402
26
272. Portable Gray Map support added by cppasm (21-May-2010)
28    Forum link: http://chdk.setepontos.com/index.php/topic,5207.msg50599.html#msg50599
29    Changes:
30         Added support PGM (portable graymap) file format
31     8 and 16 bits per pixel supported, but 16 bit is supported by limited subset of viewers so it's better to use 8 bit PGM
32     PGM output is enabled with -pgm option, and you must specify .PGM extension to output file.
33     example:  rawconvert.exe -10to8 -pgm -w=2672 -h=1968 CRW_0005.RAW IMG_0005.PGM
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
42typedef unsigned (*get_pixel_func_t)(uint8_t *p, unsigned row_bytes, unsigned x, unsigned y);
43typedef void (*set_pixel_func_t)(uint8_t *p, unsigned row_bytes, unsigned x, unsigned y, unsigned value);
44typedef unsigned (*convert_pixel_func_t)(unsigned value);
45
46typedef 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
54void 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
77unsigned 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
89unsigned 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
105void 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
144unsigned get_8_pixel(uint8_t *buf, unsigned row_bytes, unsigned x, unsigned y)
145{
146        return buf[row_bytes*y+x];
147}
148
149void 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
154unsigned 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
159void 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
164void 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},
178op_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
195const 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
205void 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
217int 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 < 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==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}
Note: See TracBrowser for help on using the repository browser.