root/tools/rawconvert.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. set_12_pixel
  2. get_12_pixel
  3. get_10_pixel
  4. set_10_pixel
  5. get_8_pixel
  6. set_8_pixel
  7. get_16_pixel
  8. set_16_pixel
  9. swap_bytes
  10. find_op
  11. usage
  12. main

   1 /*
   2 A small tools to convert CHDK 10 and 12 bit raws to 8 or 16 bit grayscale for inspection
   3 Can also covert to CHDK formats
   4 
   5 Usage:
   6 rawconvert -<op> -w=<width> -h=<height> [-noshift] [-pgm] <infile> <outfile>
   7 where <op> is XtoY with X and Y being the source and destination BPP
   8 by 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
  11 if -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  
  19 LINKS:
  20 CHDK wikia article:     http://chdk.wikia.com/wiki/CHDK_Tools#rawconvert.c
  21 
  22 REVISIONS:
  23 1. 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 
  27 2. 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 
  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 }

/* [<][>][^][v][top][bottom][index][help] */