1 /* -*- C++ -*-
2 * File: postprocessing_benchmark.cpp
3 * Copyright 2008-2021 LibRaw LLC (info@libraw.org)
4 * Created: Jul 13, 2011
5 *
6 * LibRaw simple C++ API: creates 8 different renderings from 1 source file.
7 The 1st and 4th one should be identical
8
9 LibRaw is free software; you can redistribute it and/or modify
10 it under the terms of the one of two licenses as you choose:
11
12 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
13 (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
14
15 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
16 (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
17
18 */
19 #include <stdio.h>
20 #include <string.h>
21 #include <math.h>
22
23 #include "libraw/libraw.h"
24
25 #ifndef LIBRAW_WIN32_CALLS
26 #include <unistd.h>
27 #include <fcntl.h>
28 #include <sys/stat.h>
29 #else
30 #include <winsock2.h>
31 #endif
32
33 #include "libraw/libraw.h"
34
35 void timerstart(void);
36 float timerend(void);
37
main(int argc,char * argv[])38 int main(int argc, char *argv[])
39 {
40 int i, ret, rep = 1;
41 LibRaw RawProcessor;
42 #ifdef OUT
43 #undef OUT
44 #endif
45 #define OUT RawProcessor.imgdata.params
46 #define OUTR RawProcessor.imgdata.rawparams
47 #define S RawProcessor.imgdata.sizes
48
49 if (argc < 2)
50 {
51 printf(
52 "postprocessing benchmark: LibRaw %s sample, %d cameras supported\n"
53 "Measures postprocessing speed with different options\n"
54 "Usage: %s [-a] [-H N] [-q N] [-h] [-m N] [-n N] [-s N] [-B x y w h] "
55 "[-R N]\n"
56 "-a average image for white balance\n"
57 "-H <num> Highlight mode (0=clip, 1=unclip, 2=blend, "
58 "3+=rebuild)\n"
59 "-q <num> Set the interpolation quality\n"
60 "-h Half-size color image\n"
61 "-m <num> Apply a num-passes 3x3 median filter to R-G and B-G\n"
62 "-n <num> Set threshold for wavelet denoising\n"
63 "-s <num> Select one raw image from input file\n"
64 "-B <x y w h> Crop output image\n"
65 "-R <num> Number of repetitions\n"
66 "-c Do not use rawspeed\n",
67 LibRaw::version(), LibRaw::cameraCount(), argv[0]);
68 return 0;
69 }
70 char opm, opt, *cp, *sp;
71 int arg, c;
72 int shrink = 0;
73
74 argv[argc] = (char *)"";
75 for (arg = 1; (((opm = argv[arg][0]) - 2) | 2) == '+';)
76 {
77 char *optstr = argv[arg];
78 opt = argv[arg++][1];
79 if ((cp = strchr(sp = (char *)"HqmnsBR", opt)) != 0)
80 for (i = 0; i < "1111141"[cp - sp] - '0'; i++)
81 if (!isdigit(argv[arg + i][0]) && !optstr[2])
82 {
83 fprintf(stderr, "Non-numeric argument to \"-%c\"\n", opt);
84 return 1;
85 }
86 switch (opt)
87 {
88 case 'a':
89 OUT.use_auto_wb = 1;
90 break;
91 case 'H':
92 OUT.highlight = atoi(argv[arg++]);
93 break;
94 case 'q':
95 OUT.user_qual = atoi(argv[arg++]);
96 break;
97 case 'h':
98 OUT.half_size = 1;
99 OUT.four_color_rgb = 1;
100 shrink = 1;
101 break;
102 case 'm':
103 OUT.med_passes = atoi(argv[arg++]);
104 break;
105 case 'n':
106 OUT.threshold = (float)atof(argv[arg++]);
107 break;
108 case 's':
109 OUTR.shot_select = abs(atoi(argv[arg++]));
110 break;
111 case 'B':
112 for (c = 0; c < 4; c++)
113 OUT.cropbox[c] = atoi(argv[arg++]);
114 break;
115 case 'R':
116 rep = abs(atoi(argv[arg++]));
117 if (rep < 1)
118 rep = 1;
119 break;
120 case 'c':
121 RawProcessor.imgdata.rawparams.use_rawspeed = 0;
122 break;
123 default:
124 fprintf(stderr, "Unknown option \"-%c\".\n", opt);
125 return 1;
126 }
127 }
128 for (; arg < argc; arg++)
129 {
130 printf("Processing file %s\n", argv[arg]);
131 timerstart();
132 if ((ret = RawProcessor.open_file(argv[arg])) != LIBRAW_SUCCESS)
133 {
134 fprintf(stderr, "Cannot open_file %s: %s\n", argv[arg],
135 libraw_strerror(ret));
136 continue; // no recycle b/c open file will recycle itself
137 }
138
139 if ((ret = RawProcessor.unpack()) != LIBRAW_SUCCESS)
140 {
141 fprintf(stderr, "Cannot unpack %s: %s\n", argv[arg],
142 libraw_strerror(ret));
143 continue;
144 }
145 float qsec = timerend();
146 printf("\n%.1f msec for unpack\n", qsec);
147 float mpix, rmpix;
148 timerstart();
149 for (c = 0; c < rep; c++)
150 {
151 if ((ret = RawProcessor.dcraw_process()) != LIBRAW_SUCCESS)
152 {
153 fprintf(stderr, "Cannot postprocess %s: %s\n", argv[arg],
154 libraw_strerror(ret));
155 break;
156 }
157 libraw_processed_image_t *p = RawProcessor.dcraw_make_mem_image();
158 if (p)
159 RawProcessor.dcraw_clear_mem(p);
160 RawProcessor.free_image();
161 }
162 float msec = timerend() / (float)rep;
163
164 if ((ret = RawProcessor.adjust_sizes_info_only()) != LIBRAW_SUCCESS)
165 {
166 fprintf(stderr, "Cannot adjust sizes for %s: %s\n", argv[arg],
167 libraw_strerror(ret));
168 break;
169 }
170 rmpix = (S.iwidth * S.iheight) / 1000000.0f;
171
172 if (c == rep) // no failure
173 {
174 unsigned int crop[4];
175 for (int i = 0; i < 4; i++)
176 crop[i] = (OUT.cropbox[i]) >> shrink;
177 if (crop[0] + crop[2] > S.iwidth)
178 crop[2] = S.iwidth - crop[0];
179 if (crop[1] + crop[3] > S.iheight)
180 crop[3] = S.iheight - crop[1];
181
182 mpix = float(crop[2] * crop[3]) / 1000000.0f;
183 float mpixsec = mpix * 1000.0f / msec;
184
185 printf("Performance: %.2f Mpix/sec\n"
186 "File: %s, Frame: %d %.1f total Mpix, %.1f msec\n"
187 "Params: WB=%s Highlight=%d Qual=%d HalfSize=%s Median=%d "
188 "Wavelet=%.0f\n"
189 "Crop: %u-%u:%ux%u, active Mpix: %.2f, %.1f frames/sec\n",
190 mpixsec, argv[arg], OUTR.shot_select, rmpix, msec,
191 OUT.use_auto_wb ? "auto" : "default", OUT.highlight, OUT.user_qual,
192 OUT.half_size ? "YES" : "No", OUT.med_passes, OUT.threshold,
193 crop[0], crop[1], crop[2], crop[3], mpix, 1000.0f / msec);
194 }
195 }
196
197 return 0;
198 }
199
200 #ifndef LIBRAW_WIN32_CALLS
201 static struct timeval start, end;
timerstart(void)202 void timerstart(void) { gettimeofday(&start, NULL); }
timerend(void)203 float timerend(void)
204 {
205 gettimeofday(&end, NULL);
206 float msec = (end.tv_sec - start.tv_sec) * 1000.0f +
207 (end.tv_usec - start.tv_usec) / 1000.0f;
208 return msec;
209 }
210 #else
211 LARGE_INTEGER start;
timerstart(void)212 void timerstart(void) { QueryPerformanceCounter(&start); }
timerend()213 float timerend()
214 {
215 LARGE_INTEGER unit, end;
216 QueryPerformanceCounter(&end);
217 QueryPerformanceFrequency(&unit);
218 float msec = (float)(end.QuadPart - start.QuadPart);
219 msec /= (float)unit.QuadPart / 1000.0f;
220 return msec;
221 }
222
223 #endif
224