File indexing completed on 2025-01-05 03:56:48

0001 /* -*- C++ -*-
0002  * File: 4channels.cpp
0003  * Copyright 2008-2021 LibRaw LLC (info@libraw.org)
0004  * Created: Mon Feb 09, 2009
0005  *
0006  * LibRaw sample
0007  * Generates 4 TIFF file from RAW data, one file per channel
0008  *
0009 
0010 LibRaw is free software; you can redistribute it and/or modify
0011 it under the terms of the one of two licenses as you choose:
0012 
0013 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
0014    (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
0015 
0016 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
0017    (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
0018 
0019 
0020  */
0021 #include <stdio.h>
0022 #include <string.h>
0023 #include <math.h>
0024 #include "libraw/libraw.h"
0025 
0026 #ifndef LIBRAW_WIN32_CALLS
0027 #include <netinet/in.h>
0028 #else
0029 #include <winsock2.h>
0030 #endif
0031 
0032 #ifdef LIBRAW_WIN32_CALLS
0033 #define snprintf _snprintf
0034 #endif
0035 
0036 int main(int ac, char *av[])
0037 {
0038   int i, ret;
0039   int autoscale = 0, black_subtraction = 1, use_gamma = 0;
0040   char outfn[1024];
0041 
0042   LibRaw RawProcessor;
0043   if (ac < 2)
0044   {
0045   usage:
0046     printf("4channels - LibRaw %s sample. %d cameras supported\n"
0047            "Usage: %s [-s N] [-g] [-A] [-B] [-N] raw-files....\n"
0048            "\t-s N - select Nth image in file (default=0)\n"
0049            "\t-g - use gamma correction with gamma 2.2 (not precise,use for "
0050            "visual inspection only)\n"
0051            "\t-A - autoscaling (by integer factor)\n"
0052            "\t-B - no black subtraction\n",
0053            LibRaw::version(), LibRaw::cameraCount(), av[0]);
0054     return 0;
0055   }
0056 
0057 #define P1 RawProcessor.imgdata.idata
0058 #define S RawProcessor.imgdata.sizes
0059 #define C RawProcessor.imgdata.color
0060 #define T RawProcessor.imgdata.thumbnail
0061 #define P2 RawProcessor.imgdata.other
0062 #define OUT RawProcessor.imgdata.params
0063 #define OUTR RawProcessor.imgdata.rawparams
0064 
0065   OUT.output_bps = 16;
0066   OUT.output_tiff = 1;
0067   OUT.user_flip = 0;
0068   OUT.no_auto_bright = 1;
0069   OUT.half_size = 1;
0070 
0071   for (i = 1; i < ac; i++)
0072   {
0073     if (av[i][0] == '-')
0074     {
0075       if (av[i][1] == 's' && av[i][2] == 0)
0076       {
0077         i++;
0078         OUTR.shot_select = av[i] ? atoi(av[i]) : 0;
0079       }
0080       else if (av[i][1] == 'g' && av[i][2] == 0)
0081         use_gamma = 1;
0082       else if (av[i][1] == 'A' && av[i][2] == 0)
0083         autoscale = 1;
0084       else if (av[i][1] == 'B' && av[i][2] == 0)
0085       {
0086         black_subtraction = 0;
0087       }
0088       else
0089         goto usage;
0090       continue;
0091     }
0092     if (!use_gamma)
0093       OUT.gamm[0] = OUT.gamm[1] = 1;
0094 
0095     int c;
0096     printf("Processing file %s\n", av[i]);
0097     if ((ret = RawProcessor.open_file(av[i])) != LIBRAW_SUCCESS)
0098     {
0099       fprintf(stderr, "Cannot open %s: %s\n", av[i], libraw_strerror(ret));
0100       continue; // no recycle b/c open file will recycle itself
0101     }
0102     if (P1.is_foveon)
0103     {
0104       printf("Cannot process Foveon image %s\n", av[i]);
0105       continue;
0106     }
0107     if ((ret = RawProcessor.unpack()) != LIBRAW_SUCCESS)
0108     {
0109       fprintf(stderr, "Cannot unpack %s: %s\n", av[i], libraw_strerror(ret));
0110       continue;
0111     }
0112     RawProcessor.raw2image();
0113     if (black_subtraction)
0114     {
0115       RawProcessor.subtract_black();
0116     }
0117 
0118     if (autoscale)
0119     {
0120       unsigned max = 0, scale = 1;
0121       for (int j = 0; j < S.iheight * S.iwidth; j++)
0122         for (int c = 0; c < 4; c++)
0123           if (max < RawProcessor.imgdata.image[j][c])
0124             max = RawProcessor.imgdata.image[j][c];
0125       if (max > 0 && max < 1 << 15)
0126       {
0127         scale = (1 << 16) / max;
0128         printf("Scaling with multiplier=%d (max=%d)\n", scale, max);
0129         for (int j = 0; j < S.iheight * S.iwidth; j++)
0130           for (c = 0; c < 4; c++)
0131             RawProcessor.imgdata.image[j][c] *= scale;
0132       }
0133       printf("Black level (scaled)=%d\n", C.black * scale);
0134     }
0135     else
0136       printf("Black level (unscaled)=%d\n", C.black);
0137 
0138     // hack to make dcraw tiff writer happy
0139     int isrgb = (P1.colors == 4 ? 0 : 1);
0140     P1.colors = 1;
0141     S.width = S.iwidth;
0142     S.height = S.iheight;
0143 
0144     for (int layer = 0; layer < 4; layer++)
0145     {
0146       if (layer > 0)
0147       {
0148         for (int rc = 0; rc < S.iheight * S.iwidth; rc++)
0149           RawProcessor.imgdata.image[rc][0] =
0150               RawProcessor.imgdata.image[rc][layer];
0151       }
0152       char lname[8];
0153       if (isrgb)
0154       {
0155         snprintf(lname, 7, "%c", ((char *)("RGBG"))[layer]);
0156         if (layer == 3)
0157           strcat(lname, "2");
0158       }
0159       else
0160         snprintf(lname, 7, "%c", ((char *)("GCMY"))[layer]);
0161 
0162       if (OUTR.shot_select)
0163         snprintf(outfn, sizeof(outfn), "%s-%d.%s.tiff", av[i], OUTR.shot_select,
0164                  lname);
0165       else
0166         snprintf(outfn, sizeof(outfn), "%s.%s.tiff", av[i], lname);
0167 
0168       printf("Writing file %s\n", outfn);
0169       if (LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_ppm_tiff_writer(outfn)))
0170         fprintf(stderr, "Cannot write %s: %s\n", outfn, libraw_strerror(ret));
0171     }
0172   }
0173   return 0;
0174 }