File indexing completed on 2025-01-05 03:56:48
0001 /* -*- C++ -*- 0002 * File: dcraw_emu.cpp 0003 * Copyright 2008-2021 LibRaw LLC (info@libraw.org) 0004 * Created: Sun Mar 23, 2008 0005 * 0006 * LibRaw simple C++ API sample: almost complete dcraw emulator 0007 * 0008 0009 LibRaw is free software; you can redistribute it and/or modify 0010 it under the terms of the one of two licenses as you choose: 0011 0012 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 0013 (See file LICENSE.LGPL provided in LibRaw distribution archive for details). 0014 0015 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 0016 (See file LICENSE.CDDL provided in LibRaw distribution archive for details). 0017 0018 0019 */ 0020 #ifdef _MSC_VER 0021 // suppress sprintf-related warning. sprintf() is permitted in sample code 0022 #define _CRT_SECURE_NO_WARNINGS 0023 #endif 0024 0025 #include <stdio.h> 0026 #include <string.h> 0027 #include <stdlib.h> 0028 #include <math.h> 0029 #include <ctype.h> 0030 0031 #include "libraw/libraw.h" 0032 0033 #ifndef LIBRAW_WIN32_CALLS 0034 #include <sys/mman.h> 0035 #include <sys/time.h> 0036 #include <unistd.h> 0037 #else 0038 #include <io.h> 0039 #endif 0040 #include <fcntl.h> 0041 #include <sys/stat.h> 0042 0043 #ifdef LIBRAW_WIN32_CALLS 0044 #define snprintf _snprintf 0045 #include <windows.h> 0046 #else 0047 #define O_BINARY 0 0048 #endif 0049 0050 #ifdef USE_DNGSDK 0051 #include "dng_host.h" 0052 #include "dng_negative.h" 0053 #include "dng_simple_image.h" 0054 #include "dng_info.h" 0055 #endif 0056 0057 void usage(const char *prog) 0058 { 0059 printf("dcraw_emu: almost complete dcraw emulator\n"); 0060 printf("Usage: %s [OPTION]... [FILE]...\n", prog); 0061 printf("-c float-num Set adjust maximum threshold (default 0.75)\n" 0062 "-v Verbose: print progress messages (repeated -v will add " 0063 "verbosity)\n" 0064 "-w Use camera white balance, if possible\n" 0065 "-a Average the whole image for white balance\n" 0066 "-A <x y w h> Average a grey box for white balance\n" 0067 "-r <r g b g> Set custom white balance\n" 0068 "+M/-M Use/don't use an embedded color matrix\n" 0069 "-C <r b> Correct chromatic aberration\n" 0070 "-P <file> Fix the dead pixels listed in this file\n" 0071 "-K <file> Subtract dark frame (16-bit raw PGM)\n" 0072 "-k <num> Set the darkness level\n" 0073 "-S <num> Set the saturation level\n" 0074 "-R <num> Set raw processing options to num\n" 0075 "-n <num> Set threshold for wavelet denoising\n" 0076 "-H [0-9] Highlight mode (0=clip, 1=unclip, 2=blend, 3+=rebuild)\n" 0077 "-t [0-7] Flip image (0=none, 3=180, 5=90CCW, 6=90CW)\n" 0078 "-o [0-8] Output colorspace (raw,sRGB,Adobe,Wide,ProPhoto,XYZ,ACES,\n" 0079 " DCI-P3,Rec2020)\n" 0080 #ifndef NO_LCMS 0081 "-o file Output ICC profile\n" 0082 "-p file Camera input profile (use \'embed\' for embedded profile)\n" 0083 #endif 0084 "-j Don't stretch or rotate raw pixels\n" 0085 "-W Don't automatically brighten the image\n" 0086 "-b <num> Adjust brightness (default = 1.0)\n" 0087 "-q N Set the interpolation quality:\n" 0088 " 0 - linear, 1 - VNG, 2 - PPG, 3 - AHD, 4 - DCB\n" 0089 " 11 - DHT, 12 - AAHD\n" 0090 "-h Half-size color image (twice as fast as \"-q 0\")\n" 0091 "-f Interpolate RGGB as four colors\n" 0092 "-m <num> Apply a 3x3 median filter to R-G and B-G\n" 0093 "-s [0..N-1] Select one raw image from input file\n" 0094 "-4 Linear 16-bit, same as \"-6 -W -g 1 1\n" 0095 "-6 Write 16-bit output\n" 0096 "-g pow ts Set gamma curve to gamma pow and toe slope ts (default = " 0097 "2.222 4.5)\n" 0098 "-T Write TIFF instead of PPM\n" 0099 "-G Use green_matching() filter\n" 0100 "-B <x y w h> use cropbox\n" 0101 "-F Use FILE I/O instead of streambuf API\n" 0102 "-Z <suf> Output filename generation rules\n" 0103 " .suf => append .suf to input name, keeping existing suffix " 0104 "too\n" 0105 " suf => replace input filename last extension\n" 0106 " - => output to stdout\n" 0107 " filename.suf => output to filename.suf\n" 0108 "-timing Detailed timing report\n" 0109 "-fbdd N 0 - disable FBDD noise reduction (default), 1 - light " 0110 "FBDD, 2 - full\n" 0111 "-dcbi N Number of extra DCD iterations (default - 0)\n" 0112 "-dcbe DCB color enhance\n" 0113 "-aexpo <e p> exposure correction\n" 0114 "-apentax4shot enables merge of 4-shot pentax files\n" 0115 "-apentax4shotorder 3102 sets pentax 4-shot alignment order\n" 0116 #ifdef USE_RAWSPEED_BITS 0117 "-arsbits V Set use_rawspeed to V\n" 0118 #endif 0119 "-mmap Use memory mmaped buffer instead of plain FILE I/O\n" 0120 "-mem Use memory buffer instead of FILE I/O\n" 0121 "-disars Do not use RawSpeed library\n" 0122 "-disinterp Do not run interpolation step\n" 0123 "-dsrawrgb1 Disable YCbCr to RGB conversion for sRAW (Cb/Cr " 0124 "interpolation enabled)\n" 0125 "-dsrawrgb2 Disable YCbCr to RGB conversion for sRAW (Cb/Cr " 0126 "interpolation disabled)\n" 0127 #ifdef USE_DNGSDK 0128 "-dngsdk Use Adobe DNG SDK for DNG decode\n" 0129 "-dngflags N set DNG decoding options to value N\n" 0130 #endif 0131 "-doutputflags N set params.output_flags to N\n" 0132 ); 0133 exit(1); 0134 } 0135 0136 static int verbosity = 0; 0137 int cnt = 0; 0138 int my_progress_callback(void *d, enum LibRaw_progress p, int iteration, 0139 int expected) 0140 { 0141 char *passed = (char *)(d ? d : "default string"); // data passed to callback 0142 // at set_callback stage 0143 0144 if (verbosity > 2) // verbosity set by repeat -v switches 0145 { 0146 printf("CB: %s pass %d of %d (data passed=%s)\n", libraw_strprogress(p), 0147 iteration, expected, passed); 0148 } 0149 else if (iteration == 0) // 1st iteration of each step 0150 printf("Starting %s (expecting %d iterations)\n", libraw_strprogress(p), 0151 expected); 0152 else if (iteration == expected - 1) 0153 printf("%s finished\n", libraw_strprogress(p)); 0154 0155 /// if(++cnt>10) return 1; // emulate user termination on 10-th callback 0156 /// call 0157 0158 return 0; // always return 0 to continue processing 0159 } 0160 0161 // timer 0162 #ifndef LIBRAW_WIN32_CALLS 0163 static struct timeval start, end; 0164 void timerstart(void) { gettimeofday(&start, NULL); } 0165 void timerprint(const char *msg, const char *filename) 0166 { 0167 gettimeofday(&end, NULL); 0168 float msec = (end.tv_sec - start.tv_sec) * 1000.0f + 0169 (end.tv_usec - start.tv_usec) / 1000.0f; 0170 printf("Timing: %s/%s: %6.3f msec\n", filename, msg, msec); 0171 } 0172 #else 0173 LARGE_INTEGER start; 0174 void timerstart(void) { QueryPerformanceCounter(&start); } 0175 void timerprint(const char *msg, const char *filename) 0176 { 0177 LARGE_INTEGER unit, end; 0178 QueryPerformanceCounter(&end); 0179 QueryPerformanceFrequency(&unit); 0180 float msec = (float)(end.QuadPart - start.QuadPart); 0181 msec /= (float)unit.QuadPart / 1000.0f; 0182 printf("Timing: %s/%s: %6.3f msec\n", filename, msg, msec); 0183 } 0184 0185 #endif 0186 0187 struct file_mapping 0188 { 0189 void *map; 0190 INT64 fsize; 0191 #ifdef LIBRAW_WIN32_CALLS 0192 HANDLE fd, fd_map; 0193 file_mapping() : map(0), fsize(0), fd(INVALID_HANDLE_VALUE), fd_map(INVALID_HANDLE_VALUE){} 0194 #else 0195 int fd; 0196 file_mapping() : map(0), fsize(0), fd(-1){} 0197 #endif 0198 }; 0199 0200 void create_mapping(struct file_mapping& data, const std::string& fn) 0201 { 0202 #ifdef LIBRAW_WIN32_CALLS 0203 std::wstring fpath(fn.begin(), fn.end()); 0204 if ((data.fd = CreateFileW(fpath.c_str(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) == INVALID_HANDLE_VALUE) return; 0205 LARGE_INTEGER fs; 0206 if (!GetFileSizeEx(data.fd, &fs)) return; 0207 data.fsize = fs.QuadPart; 0208 if ((data.fd_map = ::CreateFileMapping(data.fd, 0, PAGE_READONLY, fs.HighPart, fs.LowPart, 0)) == INVALID_HANDLE_VALUE) return; 0209 data.map = MapViewOfFile(data.fd_map, FILE_MAP_READ, 0, 0, data.fsize); 0210 #else 0211 struct stat stt; 0212 if ((data.fd = open(fn.c_str(), O_RDONLY)) < 0) return; 0213 if (fstat(data.fd, &stt) != 0) return; 0214 data.fsize = stt.st_size; 0215 data.map = mmap(0, data.fsize, PROT_READ | PROT_WRITE, MAP_PRIVATE, data.fd, 0); 0216 return; 0217 #endif 0218 } 0219 0220 void close_mapping(struct file_mapping& data) 0221 { 0222 #ifdef LIBRAW_WIN32_CALLS 0223 if (data.map) UnmapViewOfFile(data.map); 0224 if (data.fd_map != INVALID_HANDLE_VALUE) CloseHandle(data.fd_map); 0225 if (data.fd != INVALID_HANDLE_VALUE) CloseHandle(data.fd); 0226 data.map = 0; 0227 data.fsize = 0; 0228 data.fd = data.fd_map = INVALID_HANDLE_VALUE; 0229 #else 0230 if (data.map) 0231 munmap(data.map, data.fsize); 0232 if (data.fd >= 0) 0233 close(data.fd); 0234 data.map = 0; 0235 data.fsize = 0; 0236 data.fd = -1; 0237 #endif 0238 } 0239 0240 0241 int main(int argc, char *argv[]) 0242 { 0243 if (argc == 1) 0244 usage(argv[0]); 0245 0246 LibRaw RawProcessor; 0247 int i, arg, c, ret; 0248 char opm, opt, *cp, *sp; 0249 int use_timing = 0, use_mem = 0, use_mmap = 0; 0250 char *outext = NULL; 0251 #ifdef USE_DNGSDK 0252 dng_host *dnghost = NULL; 0253 #endif 0254 struct file_mapping mapping; 0255 void *iobuffer = 0; 0256 #ifdef OUT 0257 #undef OUT 0258 #endif 0259 #define OUT RawProcessor.imgdata.params 0260 #define OUTR RawProcessor.imgdata.rawparams 0261 0262 argv[argc] = (char *)""; 0263 for (arg = 1; (((opm = argv[arg][0]) - 2) | 2) == '+';) 0264 { 0265 char *optstr = argv[arg]; 0266 opt = argv[arg++][1]; 0267 if ((cp = strchr(sp = (char *)"cnbrkStqmHABCgU", opt)) != 0) 0268 for (i = 0; i < "111411111144221"[cp - sp] - '0'; i++) 0269 if (!isdigit(argv[arg + i][0]) && !optstr[2]) 0270 { 0271 fprintf(stderr, "Non-numeric argument to \"-%c\"\n", opt); 0272 return 1; 0273 } 0274 if (!strchr("ftdeam", opt) && argv[arg - 1][2]) { 0275 fprintf(stderr, "Unknown option \"%s\".\n", argv[arg - 1]); 0276 continue; 0277 } 0278 switch (opt) 0279 { 0280 case 'v': 0281 verbosity++; 0282 break; 0283 case 'G': 0284 OUT.green_matching = 1; 0285 break; 0286 case 'c': 0287 OUT.adjust_maximum_thr = (float)atof(argv[arg++]); 0288 break; 0289 case 'U': 0290 OUT.auto_bright_thr = (float)atof(argv[arg++]); 0291 break; 0292 case 'n': 0293 OUT.threshold = (float)atof(argv[arg++]); 0294 break; 0295 case 'b': 0296 OUT.bright = (float)atof(argv[arg++]); 0297 break; 0298 case 'P': 0299 OUT.bad_pixels = argv[arg++]; 0300 break; 0301 case 'K': 0302 OUT.dark_frame = argv[arg++]; 0303 break; 0304 case 'r': 0305 for (c = 0; c < 4; c++) 0306 OUT.user_mul[c] = (float)atof(argv[arg++]); 0307 break; 0308 case 'C': 0309 OUT.aber[0] = 1 / atof(argv[arg++]); 0310 OUT.aber[2] = 1 / atof(argv[arg++]); 0311 break; 0312 case 'g': 0313 OUT.gamm[0] = 1 / atof(argv[arg++]); 0314 OUT.gamm[1] = atof(argv[arg++]); 0315 break; 0316 case 'k': 0317 OUT.user_black = atoi(argv[arg++]); 0318 break; 0319 case 'S': 0320 OUT.user_sat = atoi(argv[arg++]); 0321 break; 0322 case 'R': 0323 OUTR.options = atoi(argv[arg++]); 0324 break; 0325 case 't': 0326 if (!strcmp(optstr, "-timing")) 0327 use_timing = 1; 0328 else if (!argv[arg - 1][2]) 0329 OUT.user_flip = atoi(argv[arg++]); 0330 else 0331 fprintf(stderr, "Unknown option \"%s\".\n", argv[arg - 1]); 0332 break; 0333 case 'q': 0334 OUT.user_qual = atoi(argv[arg++]); 0335 break; 0336 case 'm': 0337 if (!strcmp(optstr, "-mmap")) 0338 use_mmap = 1; 0339 else 0340 if (!strcmp(optstr, "-mem")) 0341 use_mem = 1; 0342 else 0343 { 0344 if (!argv[arg - 1][2]) 0345 OUT.med_passes = atoi(argv[arg++]); 0346 else 0347 fprintf(stderr, "Unknown option \"%s\".\n", argv[arg - 1]); 0348 } 0349 break; 0350 case 'H': 0351 OUT.highlight = atoi(argv[arg++]); 0352 break; 0353 case 's': 0354 OUTR.shot_select = abs(atoi(argv[arg++])); 0355 break; 0356 case 'o': 0357 if (isdigit(argv[arg][0]) && !isdigit(argv[arg][1])) 0358 OUT.output_color = atoi(argv[arg++]); 0359 #ifndef NO_LCMS 0360 else 0361 OUT.output_profile = argv[arg++]; 0362 break; 0363 case 'p': 0364 OUT.camera_profile = argv[arg++]; 0365 #endif 0366 break; 0367 case 'h': 0368 OUT.half_size = 1; 0369 break; 0370 case 'f': 0371 if (!strcmp(optstr, "-fbdd")) 0372 OUT.fbdd_noiserd = atoi(argv[arg++]); 0373 else 0374 { 0375 if (!argv[arg - 1][2]) 0376 OUT.four_color_rgb = 1; 0377 else 0378 fprintf(stderr, "Unknown option \"%s\".\n", argv[arg - 1]); 0379 } 0380 break; 0381 case 'A': 0382 for (c = 0; c < 4; c++) 0383 OUT.greybox[c] = atoi(argv[arg++]); 0384 break; 0385 case 'B': 0386 for (c = 0; c < 4; c++) 0387 OUT.cropbox[c] = atoi(argv[arg++]); 0388 break; 0389 case 'a': 0390 if (!strcmp(optstr, "-aexpo")) 0391 { 0392 OUT.exp_correc = 1; 0393 OUT.exp_shift = (float)atof(argv[arg++]); 0394 OUT.exp_preser = (float)atof(argv[arg++]); 0395 } 0396 #ifdef USE_RAWSPEED_BITS 0397 else if (!strcmp(optstr, "-arsbits")) 0398 { 0399 OUTR.use_rawspeed = atoi(argv[arg++]); 0400 } 0401 #endif 0402 else if (!strcmp(optstr, "-apentax4shot")) 0403 { 0404 OUTR.options |= LIBRAW_RAWOPTIONS_PENTAX_PS_ALLFRAMES; 0405 } 0406 else if (!strcmp(optstr, "-apentax4shotorder")) 0407 { 0408 strncpy(OUTR.p4shot_order, argv[arg++], 5); 0409 } 0410 else if (!argv[arg - 1][2]) 0411 OUT.use_auto_wb = 1; 0412 else 0413 fprintf(stderr, "Unknown option \"%s\".\n", argv[arg - 1]); 0414 break; 0415 case 'w': 0416 OUT.use_camera_wb = 1; 0417 break; 0418 case 'M': 0419 OUT.use_camera_matrix = (opm == '+')?3:0; 0420 break; 0421 case 'j': 0422 OUT.use_fuji_rotate = 0; 0423 break; 0424 case 'W': 0425 OUT.no_auto_bright = 1; 0426 break; 0427 case 'T': 0428 OUT.output_tiff = 1; 0429 break; 0430 case '4': 0431 OUT.gamm[0] = OUT.gamm[1] = OUT.no_auto_bright = 1; /* no break here! */ 0432 case '6': 0433 OUT.output_bps = 16; 0434 break; 0435 case 'Z': 0436 outext = strdup(argv[arg++]); 0437 break; 0438 case 'd': 0439 if (!strcmp(optstr, "-dcbi")) 0440 OUT.dcb_iterations = atoi(argv[arg++]); 0441 else if (!strcmp(optstr, "-doutputflags")) 0442 OUT.output_flags = atoi(argv[arg++]); 0443 else if (!strcmp(optstr, "-disars")) 0444 OUTR.use_rawspeed = 0; 0445 else if (!strcmp(optstr, "-disinterp")) 0446 OUT.no_interpolation = 1; 0447 else if (!strcmp(optstr, "-dcbe")) 0448 OUT.dcb_enhance_fl = 1; 0449 else if (!strcmp(optstr, "-dsrawrgb1")) 0450 { 0451 OUTR.specials |= LIBRAW_RAWSPECIAL_SRAW_NO_RGB; 0452 OUTR.specials &= ~LIBRAW_RAWSPECIAL_SRAW_NO_INTERPOLATE; 0453 } 0454 else if (!strcmp(optstr, "-dsrawrgb2")) 0455 { 0456 OUTR.specials &= ~LIBRAW_RAWSPECIAL_SRAW_NO_RGB; 0457 OUTR.specials |= LIBRAW_RAWSPECIAL_SRAW_NO_INTERPOLATE; 0458 } 0459 #ifdef USE_DNGSDK 0460 else if (!strcmp(optstr, "-dngsdk")) 0461 { 0462 dnghost = new dng_host; 0463 RawProcessor.set_dng_host(dnghost); 0464 } 0465 else if (!strcmp(optstr, "-dngflags")) 0466 { 0467 OUTR.use_dngsdk = atoi(argv[arg++]); 0468 } 0469 #endif 0470 else 0471 fprintf(stderr, "Unknown option \"%s\".\n", argv[arg - 1]); 0472 break; 0473 default: 0474 fprintf(stderr, "Unknown option \"-%c\".\n", opt); 0475 break; 0476 } 0477 } 0478 #ifndef LIBRAW_WIN32_CALLS 0479 putenv((char *)"TZ=UTC"); // dcraw compatibility, affects TIFF datestamp field 0480 #else 0481 _putenv( 0482 (char *)"TZ=UTC"); // dcraw compatibility, affects TIFF datestamp field 0483 #endif 0484 #define P1 RawProcessor.imgdata.idata 0485 #define S RawProcessor.imgdata.sizes 0486 #define C RawProcessor.imgdata.color 0487 #define T RawProcessor.imgdata.thumbnail 0488 #define P2 RawProcessor.imgdata.other 0489 0490 if (outext && !strcmp(outext, "-")) 0491 use_timing = verbosity = 0; 0492 0493 if (verbosity > 1) 0494 RawProcessor.set_progress_handler(my_progress_callback, 0495 (void *)"Sample data passed"); 0496 #ifdef LIBRAW_USE_OPENMP 0497 if (verbosity) 0498 printf("Using %d threads\n", omp_get_max_threads()); 0499 #endif 0500 0501 int done = 0; 0502 int total = argc - arg; 0503 for (; arg < argc; arg++) 0504 { 0505 char outfn[1024]; 0506 0507 if (verbosity) 0508 printf("Processing file %s\n", argv[arg]); 0509 0510 timerstart(); 0511 0512 if (use_mmap) 0513 { 0514 create_mapping(mapping, argv[arg]); 0515 if (!mapping.map) 0516 { 0517 fprintf(stderr, "Cannot map %s\n", argv[arg]); 0518 close_mapping(mapping); 0519 continue; 0520 } 0521 if ((ret = RawProcessor.open_buffer(mapping.map,mapping.fsize) != 0522 LIBRAW_SUCCESS)) 0523 { 0524 fprintf(stderr, "Cannot open_buffer %s: %s\n", argv[arg], libraw_strerror(ret)); 0525 close_mapping(mapping); 0526 continue; // no recycle b/c open file will recycle itself 0527 } 0528 } 0529 else if (use_mem) 0530 { 0531 int file = open(argv[arg], O_RDONLY | O_BINARY); 0532 struct stat st; 0533 if (file < 0) 0534 { 0535 fprintf(stderr, "Cannot open %s: %s\n", argv[arg], strerror(errno)); 0536 continue; 0537 } 0538 if (fstat(file, &st)) 0539 { 0540 fprintf(stderr, "Cannot stat %s: %s\n", argv[arg], strerror(errno)); 0541 close(file); 0542 continue; 0543 } 0544 if (!(iobuffer = malloc(st.st_size))) 0545 { 0546 fprintf(stderr, "Cannot allocate %d kbytes for memory buffer\n", 0547 (int)(st.st_size / 1024)); 0548 close(file); 0549 continue; 0550 } 0551 int rd; 0552 if (st.st_size != (rd = read(file, iobuffer, st.st_size))) 0553 { 0554 fprintf(stderr, 0555 "Cannot read %d bytes instead of %d to memory buffer\n", 0556 (int)rd, (int)st.st_size); 0557 close(file); 0558 free(iobuffer); 0559 continue; 0560 } 0561 close(file); 0562 if ((ret = RawProcessor.open_buffer(iobuffer, st.st_size)) != 0563 LIBRAW_SUCCESS) 0564 { 0565 fprintf(stderr, "Cannot open_buffer %s: %s\n", argv[arg], 0566 libraw_strerror(ret)); 0567 free(iobuffer); 0568 continue; // no recycle b/c open file will recycle itself 0569 } 0570 } 0571 else 0572 { 0573 ret = RawProcessor.open_file(argv[arg]); 0574 0575 if (ret != LIBRAW_SUCCESS) 0576 { 0577 fprintf(stderr, "Cannot open %s: %s\n", argv[arg], 0578 libraw_strerror(ret)); 0579 continue; // no recycle b/c open_file will recycle itself 0580 } 0581 } 0582 0583 if (use_timing) 0584 timerprint("LibRaw::open_file()", argv[arg]); 0585 0586 timerstart(); 0587 if ((ret = RawProcessor.unpack()) != LIBRAW_SUCCESS) 0588 { 0589 fprintf(stderr, "Cannot unpack %s: %s\n", argv[arg], 0590 libraw_strerror(ret)); 0591 continue; 0592 } 0593 0594 if (use_timing) 0595 timerprint("LibRaw::unpack()", argv[arg]); 0596 0597 timerstart(); 0598 if (LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_process())) 0599 { 0600 fprintf(stderr, "Cannot do postprocessing on %s: %s\n", argv[arg], 0601 libraw_strerror(ret)); 0602 if (LIBRAW_FATAL_ERROR(ret)) 0603 continue; 0604 } 0605 if (use_timing) 0606 timerprint("LibRaw::dcraw_process()", argv[arg]); 0607 0608 if (!outext) 0609 snprintf(outfn, sizeof(outfn), "%s.%s", argv[arg], 0610 OUT.output_tiff ? "tiff" : (P1.colors > 1 ? "ppm" : "pgm")); 0611 else if (!strcmp(outext, "-")) 0612 snprintf(outfn, sizeof(outfn), "-"); 0613 else 0614 { 0615 if (*outext == '.') // append 0616 snprintf(outfn, sizeof(outfn), "%s%s", argv[arg], outext); 0617 else if (strchr(outext, '.') && *outext != '.') // dot is not 1st char 0618 strncpy(outfn, outext, sizeof(outfn)); 0619 else 0620 { 0621 strncpy(outfn, argv[arg], sizeof(outfn)); 0622 if (strlen(outfn) > 0) 0623 { 0624 char *lastchar = outfn + strlen(outfn); // points to term 0 0625 while (--lastchar > outfn) 0626 { 0627 if (*lastchar == '/' || *lastchar == '\\') 0628 break; 0629 if (*lastchar == '.') 0630 { 0631 *lastchar = 0; 0632 break; 0633 }; 0634 } 0635 } 0636 strncat(outfn, ".", sizeof(outfn) - strlen(outfn) - 1); 0637 strncat(outfn, outext, sizeof(outfn) - strlen(outfn) - 1); 0638 } 0639 } 0640 0641 if (verbosity) 0642 { 0643 printf("Writing file %s\n", outfn); 0644 } 0645 0646 if (LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_ppm_tiff_writer(outfn))) 0647 fprintf(stderr, "Cannot write %s: %s\n", outfn, libraw_strerror(ret)); 0648 else 0649 done++; 0650 0651 RawProcessor.recycle(); // just for show this call 0652 0653 if (use_mmap && mapping.map) 0654 close_mapping(mapping); 0655 else if (use_mem && iobuffer) 0656 { 0657 free(iobuffer); 0658 iobuffer = 0; 0659 } 0660 } 0661 #ifdef USE_DNGSDK 0662 if (dnghost) 0663 delete dnghost; 0664 #endif 0665 if (total == 0) 0666 return 1; 0667 if (done < total) 0668 return 2; 0669 return 0; 0670 }