File indexing completed on 2025-01-05 03:56:48
0001 /* -*- C++ -*- 0002 * File: postprocessing_benchmark.cpp 0003 * Copyright 2008-2021 LibRaw LLC (info@libraw.org) 0004 * Created: Jul 13, 2011 0005 * 0006 * LibRaw simple C++ API: creates 8 different renderings from 1 source file. 0007 The 1st and 4th one should be identical 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 #include <stdio.h> 0020 #include <string.h> 0021 #include <math.h> 0022 0023 #include "libraw/libraw.h" 0024 0025 #ifndef LIBRAW_WIN32_CALLS 0026 #include <unistd.h> 0027 #include <fcntl.h> 0028 #include <sys/stat.h> 0029 #else 0030 #include <winsock2.h> 0031 #endif 0032 0033 #include "libraw/libraw.h" 0034 0035 void timerstart(void); 0036 float timerend(void); 0037 0038 int main(int argc, char *argv[]) 0039 { 0040 int i, ret, rep = 1; 0041 LibRaw RawProcessor; 0042 #ifdef OUT 0043 #undef OUT 0044 #endif 0045 #define OUT RawProcessor.imgdata.params 0046 #define OUTR RawProcessor.imgdata.rawparams 0047 #define S RawProcessor.imgdata.sizes 0048 0049 if (argc < 2) 0050 { 0051 printf( 0052 "postprocessing benchmark: LibRaw %s sample, %d cameras supported\n" 0053 "Measures postprocessing speed with different options\n" 0054 "Usage: %s [-a] [-H N] [-q N] [-h] [-m N] [-n N] [-s N] [-B x y w h] " 0055 "[-R N]\n" 0056 "-a average image for white balance\n" 0057 "-H <num> Highlight mode (0=clip, 1=unclip, 2=blend, " 0058 "3+=rebuild)\n" 0059 "-q <num> Set the interpolation quality\n" 0060 "-h Half-size color image\n" 0061 "-m <num> Apply a num-passes 3x3 median filter to R-G and B-G\n" 0062 "-n <num> Set threshold for wavelet denoising\n" 0063 "-s <num> Select one raw image from input file\n" 0064 "-B <x y w h> Crop output image\n" 0065 "-R <num> Number of repetitions\n" 0066 "-c Do not use rawspeed\n", 0067 LibRaw::version(), LibRaw::cameraCount(), argv[0]); 0068 return 0; 0069 } 0070 char opm, opt, *cp, *sp; 0071 int arg, c; 0072 int shrink = 0; 0073 0074 argv[argc] = (char *)""; 0075 for (arg = 1; (((opm = argv[arg][0]) - 2) | 2) == '+';) 0076 { 0077 char *optstr = argv[arg]; 0078 opt = argv[arg++][1]; 0079 if ((cp = strchr(sp = (char *)"HqmnsBR", opt)) != 0) 0080 for (i = 0; i < "1111141"[cp - sp] - '0'; i++) 0081 if (!isdigit(argv[arg + i][0]) && !optstr[2]) 0082 { 0083 fprintf(stderr, "Non-numeric argument to \"-%c\"\n", opt); 0084 return 1; 0085 } 0086 switch (opt) 0087 { 0088 case 'a': 0089 OUT.use_auto_wb = 1; 0090 break; 0091 case 'H': 0092 OUT.highlight = atoi(argv[arg++]); 0093 break; 0094 case 'q': 0095 OUT.user_qual = atoi(argv[arg++]); 0096 break; 0097 case 'h': 0098 OUT.half_size = 1; 0099 OUT.four_color_rgb = 1; 0100 shrink = 1; 0101 break; 0102 case 'm': 0103 OUT.med_passes = atoi(argv[arg++]); 0104 break; 0105 case 'n': 0106 OUT.threshold = (float)atof(argv[arg++]); 0107 break; 0108 case 's': 0109 OUTR.shot_select = abs(atoi(argv[arg++])); 0110 break; 0111 case 'B': 0112 for (c = 0; c < 4; c++) 0113 OUT.cropbox[c] = atoi(argv[arg++]); 0114 break; 0115 case 'R': 0116 rep = abs(atoi(argv[arg++])); 0117 if (rep < 1) 0118 rep = 1; 0119 break; 0120 case 'c': 0121 RawProcessor.imgdata.rawparams.use_rawspeed = 0; 0122 break; 0123 default: 0124 fprintf(stderr, "Unknown option \"-%c\".\n", opt); 0125 return 1; 0126 } 0127 } 0128 for (; arg < argc; arg++) 0129 { 0130 printf("Processing file %s\n", argv[arg]); 0131 timerstart(); 0132 if ((ret = RawProcessor.open_file(argv[arg])) != LIBRAW_SUCCESS) 0133 { 0134 fprintf(stderr, "Cannot open_file %s: %s\n", argv[arg], 0135 libraw_strerror(ret)); 0136 continue; // no recycle b/c open file will recycle itself 0137 } 0138 0139 if ((ret = RawProcessor.unpack()) != LIBRAW_SUCCESS) 0140 { 0141 fprintf(stderr, "Cannot unpack %s: %s\n", argv[arg], 0142 libraw_strerror(ret)); 0143 continue; 0144 } 0145 float qsec = timerend(); 0146 printf("\n%.1f msec for unpack\n", qsec); 0147 float mpix, rmpix; 0148 timerstart(); 0149 for (c = 0; c < rep; c++) 0150 { 0151 if ((ret = RawProcessor.dcraw_process()) != LIBRAW_SUCCESS) 0152 { 0153 fprintf(stderr, "Cannot postprocess %s: %s\n", argv[arg], 0154 libraw_strerror(ret)); 0155 break; 0156 } 0157 libraw_processed_image_t *p = RawProcessor.dcraw_make_mem_image(); 0158 if (p) 0159 RawProcessor.dcraw_clear_mem(p); 0160 RawProcessor.free_image(); 0161 } 0162 float msec = timerend() / (float)rep; 0163 0164 if ((ret = RawProcessor.adjust_sizes_info_only()) != LIBRAW_SUCCESS) 0165 { 0166 fprintf(stderr, "Cannot adjust sizes for %s: %s\n", argv[arg], 0167 libraw_strerror(ret)); 0168 break; 0169 } 0170 rmpix = (S.iwidth * S.iheight) / 1000000.0f; 0171 0172 if (c == rep) // no failure 0173 { 0174 unsigned int crop[4]; 0175 for (int i = 0; i < 4; i++) 0176 crop[i] = (OUT.cropbox[i]) >> shrink; 0177 if (crop[0] + crop[2] > S.iwidth) 0178 crop[2] = S.iwidth - crop[0]; 0179 if (crop[1] + crop[3] > S.iheight) 0180 crop[3] = S.iheight - crop[1]; 0181 0182 mpix = float(crop[2] * crop[3]) / 1000000.0f; 0183 float mpixsec = mpix * 1000.0f / msec; 0184 0185 printf("Performance: %.2f Mpix/sec\n" 0186 "File: %s, Frame: %d %.1f total Mpix, %.1f msec\n" 0187 "Params: WB=%s Highlight=%d Qual=%d HalfSize=%s Median=%d " 0188 "Wavelet=%.0f\n" 0189 "Crop: %u-%u:%ux%u, active Mpix: %.2f, %.1f frames/sec\n", 0190 mpixsec, argv[arg], OUTR.shot_select, rmpix, msec, 0191 OUT.use_auto_wb ? "auto" : "default", OUT.highlight, OUT.user_qual, 0192 OUT.half_size ? "YES" : "No", OUT.med_passes, OUT.threshold, 0193 crop[0], crop[1], crop[2], crop[3], mpix, 1000.0f / msec); 0194 } 0195 } 0196 0197 return 0; 0198 } 0199 0200 #ifndef LIBRAW_WIN32_CALLS 0201 static struct timeval start, end; 0202 void timerstart(void) { gettimeofday(&start, NULL); } 0203 float timerend(void) 0204 { 0205 gettimeofday(&end, NULL); 0206 float msec = (end.tv_sec - start.tv_sec) * 1000.0f + 0207 (end.tv_usec - start.tv_usec) / 1000.0f; 0208 return msec; 0209 } 0210 #else 0211 LARGE_INTEGER start; 0212 void timerstart(void) { QueryPerformanceCounter(&start); } 0213 float timerend() 0214 { 0215 LARGE_INTEGER unit, end; 0216 QueryPerformanceCounter(&end); 0217 QueryPerformanceFrequency(&unit); 0218 float msec = (float)(end.QuadPart - start.QuadPart); 0219 msec /= (float)unit.QuadPart / 1000.0f; 0220 return msec; 0221 } 0222 0223 #endif