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