3 * Copyright 2008-2009 Alex Tutubalin <lexa@lexa.ru>
4 * Created: Sun Mar 23, 2008
6 * LibRaw simple C++ API (almost complete dcraw emulator)
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
35 #include "libraw/libraw.h"
37 #define snprintf _snprintf
41 void usage(const char *prog
)
43 printf("dcraw_emu: almost complete dcraw emulator\n");
44 printf("Usage: %s [OPTION]... [FILE]...\n", prog
);
46 "-v Verbose: print progress messages (repeated -v will add verbosity)\n"
47 "-w Use camera white balance, if possible\n"
48 "-a Average the whole image for white balance\n"
49 "-A <x y w h> Average a grey box for white balance\n"
50 "-r <r g b g> Set custom white balance\n"
51 "+M/-M Use/don't use an embedded color matrix\n"
52 "-C <r b> Correct chromatic aberration\n"
53 "-P <file> Fix the dead pixels listed in this file\n"
54 "-K <file> Subtract dark frame (16-bit raw PGM)\n"
55 "-k <num> Set the darkness level\n"
56 "-S <num> Set the saturation level\n"
57 "-n <num> Set threshold for wavelet denoising\n"
58 "-H [0-9] Highlight mode (0=clip, 1=unclip, 2=blend, 3+=rebuild)\n"
59 "-t [0-7] Flip image (0=none, 3=180, 5=90CCW, 6=90CW)\n"
60 "-o [0-5] Output colorspace (raw,sRGB,Adobe,Wide,ProPhoto,XYZ)\n"
62 "-o file Output ICC profile\n"
63 "-p file Camera input profile (use \'embed\' for embedded profile)\n"
65 "-j Don't stretch or rotate raw pixels\n"
66 "-W Don't automatically brighten the image\n"
67 "-b <num> Adjust brightness (default = 1.0)\n"
68 "-q [0-3] Set the interpolation quality\n"
69 "-h Half-size color image (twice as fast as \"-q 0\")\n"
70 "-f Interpolate RGGB as four colors\n"
71 "-m <num> Apply a 3x3 median filter to R-G and B-G\n"
72 "-s [0..N-1] Select one raw image from input file\n"
73 "-4 Write 16-bit linear instead of 8-bit with gamma\n"
74 "-g pow ts Set gamma curve to gamma pow and toe slope ts (default = 2.222 4.5)\n"
75 "-T Write TIFF instead of PPM\n"
77 "-B Use mmap()-ed buffer instead of plain FILE I/O\n"
83 static int verbosity
=0;
86 int my_progress_callback(void *d
,enum LibRaw_progress p
,int iteration
, int expected
)
88 char *passed
= (char*)(d
?d
:"default string"); // data passed to callback at set_callback stage
90 if(verbosity
>2) // verbosity set by repeat -v switches
92 printf("CB: %s pass %d of %d (data passed=%s)\n",libraw_strprogress(p
),iteration
,expected
,passed
);
94 else if (iteration
== 0) // 1st iteration of each step
95 printf("Starting %s (expecting %d iterations)\n", libraw_strprogress(p
),expected
);
96 else if (iteration
== expected
-1)
97 printf("%s finished\n",libraw_strprogress(p
));
99 /// if(++cnt>10) return 1; // emulate user termination on 10-th callback call
101 return 0; // always return 0 to continue processing
105 int main(int argc
, char *argv
[])
107 if(argc
==1) usage(argv
[0]);
111 char opm
,opt
,*cp
,*sp
;
112 int use_mmap
=0, msize
;
115 #define OUT RawProcessor.imgdata.params
118 for (arg
=1; (((opm
= argv
[arg
][0]) - 2) | 2) == '+'; )
120 opt
= argv
[arg
++][1];
121 if ((cp
= strchr (sp
="nbrkStqmHACg", opt
)))
122 for (i
=0; i
< "11411111142"[cp
-sp
]-'0'; i
++)
123 if (!isdigit(argv
[arg
+i
][0]))
125 fprintf (stderr
,"Non-numeric argument to \"-%c\"\n", opt
);
130 case 'v': verbosity
++; break;
132 case 'n': OUT
.threshold
= atof(argv
[arg
++]); break;
133 case 'b': OUT
.bright
= atof(argv
[arg
++]); break;
134 case 'P': OUT
.bad_pixels
= argv
[arg
++]; break;
135 case 'K': OUT
.dark_frame
= argv
[arg
++]; break;
138 OUT
.user_mul
[c
] = atof(argv
[arg
++]);
141 OUT
.aber
[0] = 1 / atof(argv
[arg
++]);
142 OUT
.aber
[2] = 1 / atof(argv
[arg
++]);
145 OUT
.gamm
[0] = 1 / atof(argv
[arg
++]);
146 OUT
.gamm
[1] = atof(argv
[arg
++]);
148 case 'k': OUT
.user_black
= atoi(argv
[arg
++]); break;
149 case 'S': OUT
.user_sat
= atoi(argv
[arg
++]); break;
150 case 't': OUT
.user_flip
= atoi(argv
[arg
++]); break;
151 case 'q': OUT
.user_qual
= atoi(argv
[arg
++]); break;
152 case 'm': OUT
.med_passes
= atoi(argv
[arg
++]); break;
153 case 'H': OUT
.highlight
= atoi(argv
[arg
++]); break;
154 case 's': OUT
.shot_select
= abs(atoi(argv
[arg
++])); break;
156 if(isdigit(argv
[arg
+1][0]) && !isdigit(argv
[arg
+1][1]))
157 OUT
.output_color
= atoi(argv
[arg
++]);
160 OUT
.output_profile
= argv
[arg
++];
162 case 'p': OUT
.camera_profile
= argv
[arg
++];
165 case 'h': OUT
.half_size
= 1;
166 // no break: "-h" implies "-f"
168 OUT
.four_color_rgb
= 1;
170 case 'A': for(c
=0; c
<4;c
++) OUT
.greybox
[c
] = atoi(argv
[arg
++]);
171 case 'a': OUT
.use_auto_wb
= 1; break;
172 case 'w': OUT
.use_camera_wb
= 1; break;
173 case 'M': OUT
.use_camera_matrix
= (opm
== '+'); break;
174 case 'j': OUT
.use_fuji_rotate
= 0; break;
175 case 'W': OUT
.no_auto_bright
= 1; break;
176 case 'T': OUT
.output_tiff
= 1; break;
177 case '4': OUT
.output_bps
= 16; break;
178 case '1': OUT
.gamma_16bit
= 1; break;
180 case 'B': use_mmap
= 1; break;
183 fprintf (stderr
,"Unknown option \"-%c\".\n", opt
);
187 putenv ((char*)"TZ=UTC"); // dcraw compatibility, affects TIFF datestamp field
188 OUT
.filtering_mode
= LIBRAW_FILTERING_AUTOMATIC
;
189 #define P1 RawProcessor.imgdata.idata
190 #define S RawProcessor.imgdata.sizes
191 #define C RawProcessor.imgdata.color
192 #define T RawProcessor.imgdata.thumbnail
193 #define P2 RawProcessor.imgdata.other
196 RawProcessor
.set_progress_handler(my_progress_callback
,(void*)"Sample data passed");
199 printf ("Using %d threads\n", omp_get_max_threads());
202 for ( ; arg
< argc
; arg
++)
206 if(verbosity
) printf("Processing file %s\n",argv
[arg
]);
210 int file
= open(argv
[arg
],O_RDONLY
);
214 fprintf(stderr
,"Cannot open %s: %s\n",argv
[arg
],strerror(errno
));
219 fprintf(stderr
,"Cannot stat %s: %s\n",argv
[arg
],strerror(errno
));
223 int pgsz
= getpagesize();
224 msize
= ((st
.st_size
+pgsz
-1)/pgsz
)*pgsz
;
225 iobuffer
= mmap(NULL
,msize
,PROT_READ
,MAP_PRIVATE
,file
,0);
228 fprintf(stderr
,"Cannot mmap %s: %s\n",argv
[arg
],strerror(errno
));
233 if( (ret
= RawProcessor
.open_buffer(iobuffer
,st
.st_size
) != LIBRAW_SUCCESS
))
235 fprintf(stderr
,"Cannot open_buffer %s: %s\n",argv
[arg
],libraw_strerror(ret
));
236 continue; // no recycle b/c open file will recycle itself
243 if( (ret
= RawProcessor
.open_file(argv
[arg
])) != LIBRAW_SUCCESS
)
245 fprintf(stderr
,"Cannot open %s: %s\n",argv
[arg
],libraw_strerror(ret
));
246 continue; // no recycle b/c open_file will recycle itself
249 if( (ret
= RawProcessor
.unpack() ) != LIBRAW_SUCCESS
)
251 fprintf(stderr
,"Cannot unpack %s: %s\n",argv
[arg
],libraw_strerror(ret
));
254 if (LIBRAW_SUCCESS
!= (ret
= RawProcessor
.dcraw_process()))
256 fprintf(stderr
,"Cannot do postpocessing on %s: %s\n",argv
[arg
],libraw_strerror(ret
));
257 if(LIBRAW_FATAL_ERROR(ret
))
260 snprintf(outfn
,sizeof(outfn
),
262 argv
[arg
], OUT
.output_tiff
? "tiff" : (P1
.colors
>1?"ppm":"pgm"));
264 if(verbosity
) printf("Writing file %s\n",outfn
);
266 if( LIBRAW_SUCCESS
!= (ret
= RawProcessor
.dcraw_ppm_tiff_writer(outfn
)))
267 fprintf(stderr
,"Cannot write %s: %s\n",outfn
,libraw_strerror(ret
));
270 if(use_mmap
&& iobuffer
)
272 munmap(iobuffer
,msize
);
277 RawProcessor
.recycle(); // just for show this call