libRaw中的unprocessed_raw程序可以将数码相机的raw图像转存为tiff图像。但是如果想知道更多的raw图像信息,并分离出不带tiff头的raw图像数据,则需要改造unprocessed_raw程序。
ispforfun在unprocessed_raw中添加了相应的代码,改写出第一版的代码。分享给大家,如果有好的建议,欢迎大家一起讨论。ispforfun会根据大家的意见将好的建议实现在后续的版本中。
1 /* -*- C++ -*- 2 * File: unprocessed_raw.cpp 3 * Copyright 2009-2013 LibRaw LLC ([email protected]) 4 * Created: Fri Jan 02, 2009 5 * 6 * LibRaw sample 7 * Generates unprocessed raw image: with masked pixels and without black subtraction 8 * 9 10 LibRaw is free software; you can redistribute it and/or modify 11 it under the terms of the one of three licenses as you choose: 12 13 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 14 (See file LICENSE.LGPL provided in LibRaw distribution archive for details). 15 16 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 17 (See file LICENSE.CDDL provided in LibRaw distribution archive for details). 18 19 3. LibRaw Software License 27032010 20 (See file LICENSE.LibRaw.pdf provided in LibRaw distribution archive for details). 21 22 */ 23 24 /* 25 Modified by ispforfun 26 1. add more dump information for camera raw images. 27 2. write out naive raw file. 28 */ 29 30 #include <stdio.h> 31 #include <string.h> 32 #include <math.h> 33 #include <time.h> 34 #ifndef WIN32 35 #include <netinet/in.h> 36 #else 37 #include <sys/utime.h> 38 #include <winsock2.h> 39 #endif 40 41 #include "libraw/libraw.h" 42 43 #ifdef WIN32 44 #define snprintf _snprintf 45 #endif 46 47 #if !(LIBRAW_COMPILE_CHECK_VERSION_NOTLESS(0,14)) 48 #error This code is for LibRaw 0.14+ only 49 #endif 50 51 void gamma_curve (unsigned short curve[]); 52 void write_ppm(unsigned width, unsigned height, unsigned short *bitmap, const char *basename); 53 void write_tiff(int width, int height, unsigned short *bitmap, const char *basename); 54 // added by ispforfun 55 void write_raw(int width, int height, unsigned short *bitmap, const char *fn); 56 57 58 int main(int ac, char *av[]) 59 { 60 int i, ret; 61 int verbose=1,autoscale=0,use_gamma=0,out_tiff=0,out_raw=0; 62 char outfn[1024]; 63 char outrawfn[1024]; 64 65 LibRaw RawProcessor; 66 if(ac<2) 67 { 68 usage: 69 printf( 70 "unprocessed_raw - LibRaw %s sample. %d cameras supported\n" 71 "Usage: %s [-q] [-A] [-g] [-s N] raw-files....\n" 72 "\t-q - be quiet\n" 73 "\t-s N - select Nth image in file (default=0)\n" 74 "\t-g - use gamma correction with gamma 2.2 (not precise,use for visual inspection only)\n" 75 "\t-A - autoscaling (by integer factor)\n" 76 "\t-T - write tiff instead of pgm\n" 77 "\t-r - write naive raw file\n" 78 ,LibRaw::version(), 79 LibRaw::cameraCount(), 80 av[0]); 81 return 0; 82 } 83 84 #define S RawProcessor.imgdata.sizes 85 #define C RawProcessor.imgdata.color 86 #define INFO RawProcessor.imgdata.idata 87 #define OUT RawProcessor.imgdata.params 88 89 for (i=1;i<ac;i++) 90 { 91 if(av[i][0]==‘-‘) 92 { 93 if(av[i][1]==‘q‘ && av[i][2]==0) 94 verbose=0; 95 else if(av[i][1]==‘A‘ && av[i][2]==0) 96 autoscale=1; 97 else if(av[i][1]==‘g‘ && av[i][2]==0) 98 use_gamma = 1; 99 else if(av[i][1]==‘T‘ && av[i][2]==0) 100 out_tiff = 1; 101 else if(av[i][1]==‘r‘ && av[i][2]==0) 102 out_raw = 1; 103 else if(av[i][1]==‘s‘ && av[i][2]==0) 104 { 105 i++; 106 OUT.shot_select=av[i]?atoi(av[i]):0; 107 } 108 else 109 goto usage; 110 continue; 111 } 112 113 if(verbose) printf("Processing file %s\n",av[i]); 114 if( (ret = RawProcessor.open_file(av[i])) != LIBRAW_SUCCESS) 115 { 116 fprintf(stderr,"Cannot open %s: %s\n",av[i],libraw_strerror(ret)); 117 continue; // no recycle b/c open file will recycle itself 118 } 119 if(verbose) 120 { 121 printf("Camera Model is %s, and manufactured by %s.\n", INFO.model, INFO.make); 122 printf("Bayer Format: "); 123 putchar(INFO.cdesc[RawProcessor.fcol(0,0)]); 124 putchar(INFO.cdesc[RawProcessor.fcol(0,1)]); 125 putchar(INFO.cdesc[RawProcessor.fcol(1,0)]); 126 putchar(INFO.cdesc[RawProcessor.fcol(1,1)]); 127 printf("\nColor Information\n"); 128 printf("Black level = %d, %d, %d, %d\n", C.cblack[0], C.cblack[1], C.cblack[2], C.cblack[3]); 129 printf("Black = %d\n", C.black); 130 printf("data maximum = %d\n", C.data_maximum); 131 printf("maximum = %d\n", C.maximum); 132 printf("cam_mul = %f, %f, %f, %f\n", C.cam_mul[0], C.cam_mul[1], C.cam_mul[2], C.cam_mul[3]); 133 printf("Image size: %dx%d\nRaw size: %dx%d\n",S.width,S.height,S.raw_width,S.raw_height); 134 printf("Margins: top=%d, left=%d\n", 135 S.top_margin,S.left_margin); 136 } 137 138 if( (ret = RawProcessor.unpack() ) != LIBRAW_SUCCESS) 139 { 140 fprintf(stderr,"Cannot unpack %s: %s\n",av[i],libraw_strerror(ret)); 141 continue; 142 } 143 144 if(verbose) 145 printf("Unpacked....\n"); 146 147 libraw_decoder_info_t decoder_info; 148 RawProcessor.get_decoder_info(&decoder_info); 149 if(!(decoder_info.decoder_flags & LIBRAW_DECODER_FLATFIELD)) 150 { 151 printf("Only Bayer-pattern RAW files supported, sorry....\n"); 152 continue; 153 } 154 155 156 if(autoscale) 157 { 158 unsigned max=0,scale; 159 for(int j=0; j<S.raw_height*S.raw_width; j++) 160 if(max < RawProcessor.imgdata.rawdata.raw_image[j]) 161 max = RawProcessor.imgdata.rawdata.raw_image[j]; 162 if (max >0 && max< 1<<15) 163 { 164 scale = (1<<16)/max; 165 if(verbose) 166 printf("Scaling with multiplier=%d (max=%d)\n",scale,max); 167 168 for(int j=0; j<S.raw_height*S.raw_width; j++) 169 RawProcessor.imgdata.rawdata.raw_image[j] *= scale; 170 } 171 } 172 if(use_gamma) 173 { 174 unsigned short curve[0x10000]; 175 gamma_curve(curve); 176 for(int j=0; j<S.raw_height*S.raw_width; j++) 177 RawProcessor.imgdata.rawdata.raw_image[j] 178 = curve[RawProcessor.imgdata.rawdata.raw_image[j]]; 179 if(verbose) 180 printf("Gamma-corrected....\n"); 181 } 182 183 184 if(OUT.shot_select) 185 snprintf(outfn,sizeof(outfn),"%s-%d.%s",av[i],OUT.shot_select,out_tiff?"tiff":"pgm"); 186 else 187 snprintf(outfn,sizeof(outfn),"%s.%s",av[i],out_tiff?"tiff":"pgm"); 188 189 if (out_raw){ 190 snprintf(outrawfn,sizeof(outrawfn),"%s.%s",av[i],"raw"); 191 write_raw(S.raw_width,S.raw_height,RawProcessor.imgdata.rawdata.raw_image,outrawfn); 192 } 193 194 if(out_tiff) 195 write_tiff(S.raw_width,S.raw_height,RawProcessor.imgdata.rawdata.raw_image,outfn); 196 else 197 write_ppm(S.raw_width,S.raw_height,RawProcessor.imgdata.rawdata.raw_image,outfn); 198 199 if(verbose) printf("Stored to file %s\n",outfn); 200 } 201 return 0; 202 } 203 204 void write_ppm(unsigned width, unsigned height, unsigned short *bitmap, const char *fname) 205 { 206 if(!bitmap) return; 207 208 FILE *f = fopen(fname,"wb"); 209 if(!f) return; 210 int bits = 16; 211 fprintf (f, "P5\n%d %d\n%d\n", width, height, (1 << bits)-1); 212 unsigned char *data = (unsigned char *)bitmap; 213 unsigned data_size = width*height*2; 214 #define SWAP(a,b) { a ^= b; a ^= (b ^= a); } 215 for(unsigned i=0; i< data_size; i+=2) 216 SWAP(data[i],data[i+1]); 217 #undef SWAP 218 fwrite(data,data_size,1,f); 219 fclose(f); 220 } 221 222 /* == gamma curve and tiff writer - simplified cut‘n‘paste from dcraw.c */ 223 224 #define SQR(x) ((x)*(x)) 225 226 void gamma_curve (unsigned short *curve) 227 { 228 229 double pwr = 1.0/2.2; 230 double ts = 0.0; 231 int imax = 0xffff; 232 int mode = 2; 233 int i; 234 double g[6], bnd[2]={0,0}, r; 235 236 g[0] = pwr; 237 g[1] = ts; 238 g[2] = g[3] = g[4] = 0; 239 bnd[g[1] >= 1] = 1; 240 if (g[1] && (g[1]-1)*(g[0]-1) <= 0) { 241 for (i=0; i < 48; i++) { 242 g[2] = (bnd[0] + bnd[1])/2; 243 if (g[0]) bnd[(pow(g[2]/g[1],-g[0]) - 1)/g[0] - 1/g[2] > -1] = g[2]; 244 else bnd[g[2]/exp(1-1/g[2]) < g[1]] = g[2]; 245 } 246 g[3] = g[2] / g[1]; 247 if (g[0]) g[4] = g[2] * (1/g[0] - 1); 248 } 249 if (g[0]) g[5] = 1 / (g[1]*SQR(g[3])/2 - g[4]*(1 - g[3]) + 250 (1 - pow(g[3],1+g[0]))*(1 + g[4])/(1 + g[0])) - 1; 251 else g[5] = 1 / (g[1]*SQR(g[3])/2 + 1 252 - g[2] - g[3] - g[2]*g[3]*(log(g[3]) - 1)) - 1; 253 for (i=0; i < 0x10000; i++) { 254 curve[i] = 0xffff; 255 if ((r = (double) i / imax) < 1) 256 curve[i] = 0x10000 * ( mode 257 ? (r < g[3] ? r*g[1] : (g[0] ? pow( r,g[0])*(1+g[4])-g[4] : log(r)*g[2]+1)) 258 : (r < g[2] ? r/g[1] : (g[0] ? pow((r+g[4])/(1+g[4]),1/g[0]) : exp((r-1)/g[2])))); 259 } 260 } 261 262 263 void tiff_set (ushort *ntag, 264 ushort tag, ushort type, int count, int val) 265 { 266 struct tiff_tag *tt; 267 int c; 268 269 tt = (struct tiff_tag *)(ntag+1) + (*ntag)++; 270 tt->tag = tag; 271 tt->type = type; 272 tt->count = count; 273 if (type < 3 && count <= 4) 274 for(c=0;c<4;c++) tt->val.c[c] = val >> (c << 3); 275 else if (type == 3 && count <= 2) 276 for(c=0;c<2;c++) tt->val.s[c] = val >> (c << 4); 277 else tt->val.i = val; 278 } 279 #define TOFF(ptr) ((char *)(&(ptr)) - (char *)th) 280 281 282 void tiff_head (int width, int height, struct tiff_hdr *th) 283 { 284 int c; 285 time_t timestamp = time(NULL); 286 struct tm *t; 287 288 memset (th, 0, sizeof *th); 289 th->t_order = htonl(0x4d4d4949) >> 16; 290 th->magic = 42; 291 th->ifd = 10; 292 tiff_set (&th->ntag, 254, 4, 1, 0); 293 tiff_set (&th->ntag, 256, 4, 1, width); 294 tiff_set (&th->ntag, 257, 4, 1, height); 295 tiff_set (&th->ntag, 258, 3, 1, 16); 296 for(c=0;c<4;c++) th->bps[c] = 16; 297 tiff_set (&th->ntag, 259, 3, 1, 1); 298 tiff_set (&th->ntag, 262, 3, 1, 1); 299 tiff_set (&th->ntag, 273, 4, 1, sizeof *th); 300 tiff_set (&th->ntag, 277, 3, 1, 1); 301 tiff_set (&th->ntag, 278, 4, 1, height); 302 tiff_set (&th->ntag, 279, 4, 1, height*width*2); 303 tiff_set (&th->ntag, 282, 5, 1, TOFF(th->rat[0])); 304 tiff_set (&th->ntag, 283, 5, 1, TOFF(th->rat[2])); 305 tiff_set (&th->ntag, 284, 3, 1, 1); 306 tiff_set (&th->ntag, 296, 3, 1, 2); 307 tiff_set (&th->ntag, 306, 2, 20, TOFF(th->date)); 308 th->rat[0] = th->rat[2] = 300; 309 th->rat[1] = th->rat[3] = 1; 310 t = localtime (×tamp); 311 if(t) 312 sprintf (th->date, "%04d:%02d:%02d %02d:%02d:%02d", 313 t->tm_year+1900,t->tm_mon+1,t->tm_mday,t->tm_hour,t->tm_min,t->tm_sec); 314 } 315 316 void write_tiff(int width, int height, unsigned short *bitmap, const char *fn) 317 { 318 struct tiff_hdr th; 319 320 FILE *ofp = fopen(fn,"wb"); 321 if(!ofp) return; 322 tiff_head (width,height,&th); 323 fwrite (&th, sizeof th, 1, ofp); 324 fwrite (bitmap, 2, width*height, ofp); 325 fclose(ofp); 326 } 327 328 329 void write_raw(int width, int height, unsigned short *bitmap, const char *fn) 330 { 331 FILE *ofp = fopen(fn,"wb"); 332 if(!ofp) return; 333 fwrite (bitmap, 2, width*height, ofp); 334 fclose(ofp); 335 }
编译成功,调用的命令为:
unprocessed_raw -r -T DSC00018.ARW
DSC00018.ARW可以替换成相应的数码相机raw文件。
Processing file DSC00018.ARW
Camera Model is DSC-RX100M3, and manufactured by Sony.
Bayer Format: RGGB
Color Information
Black level = 0, 0, 0, 0
Black = 200
data maximum = 0
maximum = 4095
cam_mul = 2576.000000, 1024.000000, 1784.000000, 1024.000000
Image size: 5496x3672
Raw size: 5504x3672
Margins: top=0, left=0
Unpacked....
Stored to file DSC00018.ARW.tiff
可以发现DSC00018.ARW.tiff和DSC00018.ARW.raw文件。
时间: 2024-10-08 09:58:39