Coverage Report

Created: 2026-09-14 07:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/LibRaw/src/postprocessing/dcraw_process.cpp
Line
Count
Source
1
/* -*- C++ -*-
2
 * Copyright 2019-2025 LibRaw LLC (info@libraw.org)
3
 *
4
 LibRaw is free software; you can redistribute it and/or modify
5
 it under the terms of the one of two licenses as you choose:
6
7
1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
8
   (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
9
10
2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
11
   (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
12
13
 */
14
15
#include "../../internal/libraw_cxx_defs.h"
16
17
int LibRaw::dcraw_process(void)
18
2.49k
{
19
2.49k
  int quality, i;
20
21
2.49k
  int iterations = -1, dcb_enhance = 1, noiserd = 0;
22
2.49k
  float preser = 0;
23
2.49k
  float expos = 1.0;
24
25
2.49k
  CHECK_ORDER_LOW(LIBRAW_PROGRESS_LOAD_RAW);
26
  //    CHECK_ORDER_HIGH(LIBRAW_PROGRESS_PRE_INTERPOLATE);
27
28
2.49k
  try
29
2.49k
  {
30
31
2.49k
    int no_crop = 1;
32
33
2.49k
    if (~O.cropbox[2] && ~O.cropbox[3])
34
0
      no_crop = 0;
35
36
12.4k
  for(int c = 0; c < 4; c++)
37
9.97k
    if (O.aber[c]< 0.001 || O.aber[c] > 1000.f)
38
0
      O.aber[c] = 1.0;
39
40
2.49k
    libraw_decoder_info_t di;
41
2.49k
    get_decoder_info(&di);
42
43
2.49k
    bool is_bayer = (imgdata.idata.filters || P1.colors == 1);
44
2.49k
    int subtract_inline =
45
2.49k
        !O.bad_pixels && !O.dark_frame && is_bayer && !IO.zero_is_bad;
46
47
2.49k
    int rc = raw2image_ex(subtract_inline); // allocate imgdata.image and copy data!
48
2.49k
  if (rc != LIBRAW_SUCCESS)
49
141
    return rc;
50
51
    // Adjust sizes
52
53
2.35k
    int save_4color = O.four_color_rgb;
54
55
2.35k
    if (IO.zero_is_bad)
56
136
    {
57
136
      remove_zeroes();
58
136
      SET_PROC_FLAG(LIBRAW_PROGRESS_REMOVE_ZEROES);
59
136
    }
60
61
2.35k
    if (O.bad_pixels && no_crop)
62
0
    {
63
0
      bad_pixels(O.bad_pixels);
64
0
      SET_PROC_FLAG(LIBRAW_PROGRESS_BAD_PIXELS);
65
0
    }
66
67
2.35k
    if (O.dark_frame && no_crop)
68
0
    {
69
0
      subtract(O.dark_frame);
70
0
      SET_PROC_FLAG(LIBRAW_PROGRESS_DARK_FRAME);
71
0
    }
72
    /* pre subtract black callback: check for it above to disable subtract
73
     * inline */
74
75
2.35k
    if (callbacks.pre_subtractblack_cb)
76
0
      (callbacks.pre_subtractblack_cb)(this);
77
78
2.35k
    quality = 2 + !IO.fuji_width;
79
80
2.35k
    if (O.user_qual >= 0)
81
2.35k
      quality = O.user_qual;
82
83
2.35k
    if (!subtract_inline || !C.data_maximum)
84
707
    {
85
707
      adjust_bl();
86
707
      subtract_black_internal();
87
707
    }
88
89
2.35k
    if (!(di.decoder_flags & LIBRAW_DECODER_FIXEDMAXC))
90
1.69k
      adjust_maximum();
91
92
2.35k
    if (O.user_sat > 0)
93
0
      C.maximum = O.user_sat;
94
95
2.35k
    if (P1.is_foveon)
96
0
    {
97
0
      if (load_raw == &LibRaw::x3f_load_raw)
98
0
      {
99
        // Filter out zeroes
100
0
        for (int q = 0; q < S.height * S.width; q++)
101
0
        {
102
0
          for (int c = 0; c < 4; c++)
103
0
            if ((short)imgdata.image[q][c] < 0)
104
0
              imgdata.image[q][c] = 0;
105
0
        }
106
0
      }
107
0
      SET_PROC_FLAG(LIBRAW_PROGRESS_FOVEON_INTERPOLATE);
108
0
    }
109
110
2.35k
    if (O.green_matching && !O.half_size)
111
0
    {
112
0
      green_matching();
113
0
    }
114
115
2.35k
    if (callbacks.pre_scalecolors_cb)
116
0
      (callbacks.pre_scalecolors_cb)(this);
117
118
2.35k
    if (!O.no_auto_scale)
119
2.35k
    {
120
2.35k
      scale_colors();
121
2.35k
      SET_PROC_FLAG(LIBRAW_PROGRESS_SCALE_COLORS);
122
2.35k
    }
123
124
2.35k
    if (callbacks.pre_preinterpolate_cb)
125
0
      (callbacks.pre_preinterpolate_cb)(this);
126
127
2.35k
    pre_interpolate();
128
129
2.35k
    SET_PROC_FLAG(LIBRAW_PROGRESS_PRE_INTERPOLATE);
130
131
2.35k
    if (O.dcb_iterations >= 0)
132
2.35k
      iterations = O.dcb_iterations;
133
2.35k
    if (O.dcb_enhance_fl >= 0)
134
2.35k
      dcb_enhance = O.dcb_enhance_fl;
135
2.35k
    if (O.fbdd_noiserd >= 0)
136
2.35k
      noiserd = O.fbdd_noiserd;
137
138
    /* pre-exposure correction callback */
139
140
2.35k
    if (O.exp_correc > 0)
141
0
    {
142
0
      expos = O.exp_shift;
143
0
      preser = O.exp_preser;
144
0
      exp_bef(expos, preser);
145
0
    }
146
147
2.35k
    if (callbacks.pre_interpolate_cb)
148
0
      (callbacks.pre_interpolate_cb)(this);
149
150
    /* post-exposure correction fallback */
151
2.35k
    if (P1.filters && !O.no_interpolation)
152
1.88k
    {
153
1.88k
    int real_colors = P1.colors;
154
1.88k
    int bad_bayer = 0;
155
1.88k
    if (P1.filters > 1000)
156
8.84k
      for (int r = 0; r < 4; r++)
157
63.6k
        for (int c = 0; c < 8; c++)
158
56.6k
        {
159
56.6k
          real_colors = MAX(COLOR(r, c) + 1, real_colors);
160
56.6k
          if (P1.filters > 1000)
161
56.6k
          {
162
            // Normal bayer: adjacent pixels horizontally/vertically have different colors
163
56.6k
            bad_bayer += (FC(r, c) == FC(r + 1, c));
164
56.6k
            bad_bayer += (FC(r, c) == FC(r, c + 1));
165
56.6k
          }
166
56.6k
        }
167
168
1.88k
      if (noiserd > 0 && P1.colors == 3 && real_colors == 3 && P1.filters > 1000)
169
0
        fbdd(noiserd);
170
171
1.88k
      if (P1.filters > 1000 && callbacks.interpolate_bayer_cb)
172
0
        (callbacks.interpolate_bayer_cb)(this);
173
1.88k
      else if (P1.filters == 9 && callbacks.interpolate_xtrans_cb)
174
0
        (callbacks.interpolate_xtrans_cb)(this);
175
1.88k
      else if (quality == 0)
176
0
        lin_interpolate();
177
1.88k
      else if (quality == 1 || P1.colors > 3 || real_colors > 3 || bad_bayer || (P1.filters != LIBRAW_XTRANS && P1.filters <= 1000))
178
284
        vng_interpolate();
179
1.59k
      else if (quality == 2 && P1.filters > 1000)
180
0
        ppg_interpolate();
181
1.59k
      else if (P1.filters == LIBRAW_XTRANS)
182
74
      {
183
        // Fuji X-Trans
184
74
        xtrans_interpolate(quality > 2 ? 3 : 1);
185
74
      }
186
1.52k
      else if (quality == 3)
187
1.52k
        ahd_interpolate(); // really don't need it here due to fallback op
188
0
      else if (quality == 4)
189
0
        dcb(iterations, dcb_enhance);
190
191
0
      else if (quality == 11)
192
0
        dht_interpolate();
193
0
      else if (quality == 12)
194
0
        aahd_interpolate();
195
      // fallback to AHD
196
0
      else
197
0
      {
198
0
        ahd_interpolate();
199
0
        imgdata.process_warnings |= LIBRAW_WARN_FALLBACK_TO_AHD;
200
0
      }
201
202
1.88k
      SET_PROC_FLAG(LIBRAW_PROGRESS_INTERPOLATE);
203
1.88k
    }
204
2.35k
    if (IO.mix_green)
205
64
    {
206
47.3k
      for (P1.colors = 3, i = 0; i < S.height * S.width; i++)
207
47.3k
        imgdata.image[i][1] = (imgdata.image[i][1] + imgdata.image[i][3]) >> 1;
208
64
      SET_PROC_FLAG(LIBRAW_PROGRESS_MIX_GREEN);
209
64
    }
210
211
2.35k
    if (callbacks.post_interpolate_cb)
212
0
      (callbacks.post_interpolate_cb)(this);
213
2.35k
    else if (!P1.is_foveon && P1.colors == 3 && O.med_passes > 0)
214
0
    {
215
0
      median_filter();
216
0
      SET_PROC_FLAG(LIBRAW_PROGRESS_MEDIAN_FILTER);
217
0
    }
218
219
2.35k
    if (O.highlight == 2)
220
0
    {
221
0
      blend_highlights();
222
0
      SET_PROC_FLAG(LIBRAW_PROGRESS_HIGHLIGHTS);
223
0
    }
224
225
2.35k
    if (O.highlight > 2)
226
0
    {
227
0
      recover_highlights();
228
0
      SET_PROC_FLAG(LIBRAW_PROGRESS_HIGHLIGHTS);
229
0
    }
230
231
2.35k
    if (O.use_fuji_rotate)
232
2.27k
    {
233
2.27k
      fuji_rotate();
234
2.27k
      SET_PROC_FLAG(LIBRAW_PROGRESS_FUJI_ROTATE);
235
2.27k
    }
236
237
2.35k
    if (!libraw_internal_data.output_data.histogram)
238
2.27k
    {
239
2.27k
      libraw_internal_data.output_data.histogram =
240
2.27k
          (int(*)[LIBRAW_HISTOGRAM_SIZE])calloc(1,
241
2.27k
              sizeof(*libraw_internal_data.output_data.histogram) * 4);
242
2.27k
    }
243
#ifndef NO_LCMS
244
    if (O.camera_profile)
245
    {
246
      apply_profile(O.camera_profile, O.output_profile);
247
      SET_PROC_FLAG(LIBRAW_PROGRESS_APPLY_PROFILE);
248
    }
249
#endif
250
251
2.35k
    if (callbacks.pre_converttorgb_cb)
252
0
      (callbacks.pre_converttorgb_cb)(this);
253
254
2.35k
    convert_to_rgb();
255
2.35k
    SET_PROC_FLAG(LIBRAW_PROGRESS_CONVERT_RGB);
256
257
2.35k
    if (callbacks.post_converttorgb_cb)
258
0
      (callbacks.post_converttorgb_cb)(this);
259
260
2.35k
    if (O.use_fuji_rotate)
261
2.27k
    {
262
2.27k
      stretch();
263
2.27k
      SET_PROC_FLAG(LIBRAW_PROGRESS_STRETCH);
264
2.27k
    }
265
2.35k
    O.four_color_rgb = save_4color; // also, restore
266
267
2.35k
    return 0;
268
2.49k
  }
269
2.49k
  catch (const std::bad_alloc&)
270
2.49k
  {
271
0
      recycle();
272
0
      return LIBRAW_UNSUFFICIENT_MEMORY;
273
0
  }
274
2.49k
  catch (const LibRaw_exceptions& err)
275
2.49k
  {
276
74
    EXCEPTION_HANDLER(err);
277
74
  }
278
2.49k
}