1 /* -*- C++ -*-
2  * File: 4channels.cpp
3  * Copyright 2008-2021 LibRaw LLC (info@libraw.org)
4  * Created: Mon Feb 09, 2009
5  *
6  * LibRaw sample
7  * Generates 4 TIFF file from RAW data, one file per channel
8  *
9 
10 LibRaw is free software; you can redistribute it and/or modify
11 it under the terms of the one of two licenses as you choose:
12 
13 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
14    (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
15 
16 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
17    (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
18 
19 
20  */
21 #include <stdio.h>
22 #include <string.h>
23 #include <math.h>
24 #include "libraw/libraw.h"
25 
26 #ifndef LIBRAW_WIN32_CALLS
27 #include <netinet/in.h>
28 #else
29 #include <winsock2.h>
30 #endif
31 
32 #ifdef LIBRAW_WIN32_CALLS
33 #define snprintf _snprintf
34 #endif
35 
main(int ac,char * av[])36 int main(int ac, char *av[])
37 {
38   int i, ret;
39   int autoscale = 0, black_subtraction = 1, use_gamma = 0;
40   char outfn[1024];
41 
42   LibRaw RawProcessor;
43   if (ac < 2)
44   {
45   usage:
46     printf("4channels - LibRaw %s sample. %d cameras supported\n"
47            "Usage: %s [-s N] [-g] [-A] [-B] [-N] raw-files....\n"
48            "\t-s N - select Nth image in file (default=0)\n"
49            "\t-g - use gamma correction with gamma 2.2 (not precise,use for "
50            "visual inspection only)\n"
51            "\t-A - autoscaling (by integer factor)\n"
52            "\t-B - no black subtraction\n",
53            LibRaw::version(), LibRaw::cameraCount(), av[0]);
54     return 0;
55   }
56 
57 #define P1 RawProcessor.imgdata.idata
58 #define S RawProcessor.imgdata.sizes
59 #define C RawProcessor.imgdata.color
60 #define T RawProcessor.imgdata.thumbnail
61 #define P2 RawProcessor.imgdata.other
62 #define OUT RawProcessor.imgdata.params
63 #define OUTR RawProcessor.imgdata.rawparams
64 
65   OUT.output_bps = 16;
66   OUT.output_tiff = 1;
67   OUT.user_flip = 0;
68   OUT.no_auto_bright = 1;
69   OUT.half_size = 1;
70 
71   for (i = 1; i < ac; i++)
72   {
73     if (av[i][0] == '-')
74     {
75       if (av[i][1] == 's' && av[i][2] == 0)
76       {
77         i++;
78         OUTR.shot_select = av[i] ? atoi(av[i]) : 0;
79       }
80       else if (av[i][1] == 'g' && av[i][2] == 0)
81         use_gamma = 1;
82       else if (av[i][1] == 'A' && av[i][2] == 0)
83         autoscale = 1;
84       else if (av[i][1] == 'B' && av[i][2] == 0)
85       {
86         black_subtraction = 0;
87       }
88       else
89         goto usage;
90       continue;
91     }
92     if (!use_gamma)
93       OUT.gamm[0] = OUT.gamm[1] = 1;
94 
95     int c;
96     printf("Processing file %s\n", av[i]);
97     if ((ret = RawProcessor.open_file(av[i])) != LIBRAW_SUCCESS)
98     {
99       fprintf(stderr, "Cannot open %s: %s\n", av[i], libraw_strerror(ret));
100       continue; // no recycle b/c open file will recycle itself
101     }
102     if (P1.is_foveon)
103     {
104       printf("Cannot process Foveon image %s\n", av[i]);
105       continue;
106     }
107     if ((ret = RawProcessor.unpack()) != LIBRAW_SUCCESS)
108     {
109       fprintf(stderr, "Cannot unpack %s: %s\n", av[i], libraw_strerror(ret));
110       continue;
111     }
112     RawProcessor.raw2image();
113     if (black_subtraction)
114     {
115       RawProcessor.subtract_black();
116     }
117 
118     if (autoscale)
119     {
120       unsigned max = 0, scale = 1;
121       for (int j = 0; j < S.iheight * S.iwidth; j++)
122         for (int c = 0; c < 4; c++)
123           if (max < RawProcessor.imgdata.image[j][c])
124             max = RawProcessor.imgdata.image[j][c];
125       if (max > 0 && max < 1 << 15)
126       {
127         scale = (1 << 16) / max;
128         printf("Scaling with multiplier=%d (max=%d)\n", scale, max);
129         for (int j = 0; j < S.iheight * S.iwidth; j++)
130           for (c = 0; c < 4; c++)
131             RawProcessor.imgdata.image[j][c] *= scale;
132       }
133       printf("Black level (scaled)=%d\n", C.black * scale);
134     }
135     else
136       printf("Black level (unscaled)=%d\n", C.black);
137 
138     // hack to make dcraw tiff writer happy
139     int isrgb = (P1.colors == 4 ? 0 : 1);
140     P1.colors = 1;
141     S.width = S.iwidth;
142     S.height = S.iheight;
143 
144     for (int layer = 0; layer < 4; layer++)
145     {
146       if (layer > 0)
147       {
148         for (int rc = 0; rc < S.iheight * S.iwidth; rc++)
149           RawProcessor.imgdata.image[rc][0] =
150               RawProcessor.imgdata.image[rc][layer];
151       }
152       char lname[8];
153       if (isrgb)
154       {
155         snprintf(lname, 7, "%c", ((char *)("RGBG"))[layer]);
156         if (layer == 3)
157           strcat(lname, "2");
158       }
159       else
160         snprintf(lname, 7, "%c", ((char *)("GCMY"))[layer]);
161 
162       if (OUTR.shot_select)
163         snprintf(outfn, sizeof(outfn), "%s-%d.%s.tiff", av[i], OUTR.shot_select,
164                  lname);
165       else
166         snprintf(outfn, sizeof(outfn), "%s.%s.tiff", av[i], lname);
167 
168       printf("Writing file %s\n", outfn);
169       if (LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_ppm_tiff_writer(outfn)))
170         fprintf(stderr, "Cannot write %s: %s\n", outfn, libraw_strerror(ret));
171     }
172   }
173   return 0;
174 }
175