Coverage Report

Created: 2026-09-28 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libraw/src/utils/utils_dcraw.cpp
Line
Count
Source
1
/* -*- C++ -*-
2
 * Copyright 2019-2025 LibRaw LLC (info@libraw.org)
3
 *
4
 LibRaw uses code from dcraw.c -- Dave Coffin's raw photo decoder,
5
 dcraw.c is copyright 1997-2018 by Dave Coffin, dcoffin a cybercom o net.
6
 LibRaw do not use RESTRICTED code from dcraw.c
7
8
 LibRaw is free software; you can redistribute it and/or modify
9
 it under the terms of the one of two licenses as you choose:
10
11
1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
12
   (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
13
14
2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
15
   (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
16
17
 */
18
19
#include "../../internal/dcraw_defs.h"
20
21
int LibRaw::fcol(int row, int col)
22
1.31G
{
23
1.31G
  static const char filter[16][16] = {
24
1.31G
      {2, 1, 1, 3, 2, 3, 2, 0, 3, 2, 3, 0, 1, 2, 1, 0},
25
1.31G
      {0, 3, 0, 2, 0, 1, 3, 1, 0, 1, 1, 2, 0, 3, 3, 2},
26
1.31G
      {2, 3, 3, 2, 3, 1, 1, 3, 3, 1, 2, 1, 2, 0, 0, 3},
27
1.31G
      {0, 1, 0, 1, 0, 2, 0, 2, 2, 0, 3, 0, 1, 3, 2, 1},
28
1.31G
      {3, 1, 1, 2, 0, 1, 0, 2, 1, 3, 1, 3, 0, 1, 3, 0},
29
1.31G
      {2, 0, 0, 3, 3, 2, 3, 1, 2, 0, 2, 0, 3, 2, 2, 1},
30
1.31G
      {2, 3, 3, 1, 2, 1, 2, 1, 2, 1, 1, 2, 3, 0, 0, 1},
31
1.31G
      {1, 0, 0, 2, 3, 0, 0, 3, 0, 3, 0, 3, 2, 1, 2, 3},
32
1.31G
      {2, 3, 3, 1, 1, 2, 1, 0, 3, 2, 3, 0, 2, 3, 1, 3},
33
1.31G
      {1, 0, 2, 0, 3, 0, 3, 2, 0, 1, 1, 2, 0, 1, 0, 2},
34
1.31G
      {0, 1, 1, 3, 3, 2, 2, 1, 1, 3, 3, 0, 2, 1, 3, 2},
35
1.31G
      {2, 3, 2, 0, 0, 1, 3, 0, 2, 0, 1, 2, 3, 0, 1, 0},
36
1.31G
      {1, 3, 1, 2, 3, 2, 3, 2, 0, 2, 0, 1, 1, 0, 3, 0},
37
1.31G
      {0, 2, 0, 3, 1, 0, 0, 1, 1, 3, 3, 2, 3, 2, 2, 1},
38
1.31G
      {2, 1, 3, 2, 3, 1, 2, 1, 0, 3, 0, 2, 0, 2, 0, 2},
39
1.31G
      {0, 3, 1, 0, 0, 2, 0, 3, 2, 1, 3, 1, 1, 3, 1, 3}};
40
41
1.31G
  if (filters == 1)
42
7.04M
    return filter[(row + top_margin) & 15][(col + left_margin) & 15];
43
1.30G
  if (filters == 9)
44
272M
    return xtrans[(row + 6) % 6][(col + 6) % 6];
45
1.03G
  return FC(row, col);
46
1.30G
}
47
48
size_t LibRaw::strnlen(const char *s, size_t n)
49
203k
{
50
203k
#if !defined(__FreeBSD__) && !defined(__OpenBSD__)
51
203k
  const char *p = (const char *)memchr(s, 0, n);
52
203k
  return (p ? p - s : n);
53
#else
54
  return ::strnlen(s, n);
55
#endif
56
203k
}
57
58
void *LibRaw::memmem(char *haystack, size_t haystacklen, char *needle,
59
                     size_t needlelen)
60
95.1k
{
61
#if !defined(__GLIBC__) && !defined(__FreeBSD__) && !defined(__OpenBSD__)
62
  char *c;
63
  for (c = haystack; c <= haystack + haystacklen - needlelen; c++)
64
    if (!memcmp(c, needle, needlelen))
65
      return c;
66
  return 0;
67
#else
68
95.1k
  return ::memmem(haystack, haystacklen, needle, needlelen);
69
95.1k
#endif
70
95.1k
}
71
72
char *LibRaw::strcasestr(char *haystack, const char *needle)
73
1.83M
{
74
1.83M
  char *c;
75
15.7M
  for (c = haystack; *c; c++)
76
13.9M
    if (!strncasecmp(c, needle, strlen(needle)))
77
77.8k
      return c;
78
1.75M
  return 0;
79
1.83M
}
80
81
void LibRaw::initdata()
82
0
{
83
0
  tiff_flip = flip = filters = UINT_MAX; /* unknown */
84
0
  raw_height = raw_width = fuji_width = fuji_layout = cr2_slice[0] = 0;
85
0
  maximum = height = width = top_margin = left_margin = 0;
86
0
  cdesc[0] = desc[0] = artist[0] = make[0] = model[0] = model2[0] = 0;
87
0
  iso_speed = shutter = aperture = focal_len = 0;
88
0
  unique_id = 0ULL;
89
0
  tiff_nifds = 0;
90
0
  memset(tiff_ifd, 0, sizeof tiff_ifd);
91
0
  for (int i = 0; i < LIBRAW_IFD_MAXCOUNT; i++)
92
0
  {
93
0
    tiff_ifd[i].dng_color[0].illuminant = tiff_ifd[i].dng_color[1].illuminant =
94
0
        0xffff;
95
0
    for (int c = 0; c < 4; c++)
96
0
      tiff_ifd[i].dng_levels.analogbalance[c] = 1.0f;
97
0
  }
98
0
  for (int i = 0; i < 0x10000; i++)
99
0
    curve[i] = i;
100
0
  memset(gpsdata, 0, sizeof gpsdata);
101
0
  memset(cblack, 0, sizeof cblack);
102
0
  memset(white, 0, sizeof white);
103
0
  memset(mask, 0, sizeof mask);
104
0
  thumb_offset = thumb_length = thumb_width = thumb_height = 0;
105
0
  load_raw = 0;
106
0
  thumb_format = LIBRAW_INTERNAL_THUMBNAIL_JPEG; // default to JPEG
107
0
  data_offset = meta_offset = meta_length = tiff_bps = tiff_compress = 0;
108
0
  kodak_cbpp = zero_after_ff = dng_version = load_flags = 0;
109
0
  timestamp = shot_order = tiff_samples = black = is_foveon = 0;
110
0
  mix_green = profile_length = data_error = zero_is_bad = 0;
111
0
  pixel_aspect = is_raw = raw_color = 1;
112
0
  tile_width = tile_length = 0;
113
0
  metadata_blocks = 0;
114
0
  is_NikonTransfer = 0;
115
0
  is_Olympus = 0;
116
0
  OlympusDNG_SubDirOffsetValid = 0;
117
0
  is_Sony = 0;
118
0
  is_pana_raw = 0;
119
0
  maker_index = LIBRAW_CAMERAMAKER_Unknown;
120
0
  FujiCropMode = 0;
121
0
  is_PentaxRicohMakernotes = 0;
122
0
  normalized_model[0] = 0;
123
0
  normalized_make[0] = 0;
124
0
  CM_found = 0;
125
0
}
126
127
void LibRaw::aRGB_coeff(double aRGB_cam[3][3])
128
410
{
129
410
  static const double rgb_aRGB[3][3] = {
130
410
      {1.39828313770000, -0.3982830047, 9.64980900741708E-8},
131
410
      {6.09219200572997E-8, 0.9999999809, 1.33230799934103E-8},
132
410
      {2.17237099975343E-8, -0.0429383201, 1.04293828050000}};
133
134
410
  double cmatrix_tmp[3][3] = {
135
410
      {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
136
410
  int i, j, k;
137
138
1.64k
  for (i = 0; i < 3; i++)
139
4.92k
    for (j = 0; j < 3; j++)
140
3.69k
    {
141
14.7k
      for (k = 0; k < 3; k++)
142
11.0k
        cmatrix_tmp[i][j] += rgb_aRGB[i][k] * aRGB_cam[k][j];
143
3.69k
      cmatrix[i][j] = (float)cmatrix_tmp[i][j];
144
3.69k
    }
145
410
}
146
147
void LibRaw::romm_coeff(float romm_cam[3][3])
148
1.06k
{
149
1.06k
  static const float rgb_romm[3][3] = /* ROMM == Kodak ProPhoto */
150
1.06k
      {{2.034193f, -0.727420f, -0.306766f},
151
1.06k
       {-0.228811f, 1.231729f, -0.002922f},
152
1.06k
       {-0.008565f, -0.153273f, 1.161839f}};
153
1.06k
  int i, j, k;
154
155
4.25k
  for (i = 0; i < 3; i++)
156
12.7k
    for (j = 0; j < 3; j++)
157
38.2k
      for (cmatrix[i][j] = 0.f, k = 0; k < 3; k++)
158
28.7k
        cmatrix[i][j] += float(rgb_romm[i][k] * romm_cam[k][j]);
159
1.06k
}
160
161
void LibRaw::remove_zeroes()
162
235
{
163
235
  unsigned row, col, tot, n;
164
235
  int r, c;
165
166
235
  RUN_CALLBACK(LIBRAW_PROGRESS_REMOVE_ZEROES, 0, 2);
167
168
55.8k
  for (row = 0; row < height; row++)
169
17.5M
    for (col = 0; col < width; col++)
170
17.5M
      if (BAYER(row, col) == 0)
171
4.71M
      {
172
4.71M
        tot = n = 0;
173
28.2M
        for (r = (int)row - 2; r <= (int)row + 2; r++)
174
141M
          for (c = (int)col - 2; c <= (int)col + 2; c++)
175
117M
            if (r >= 0 && r < height && c >= 0 && c < width &&
176
117M
                FC(r, c) == FC(row, col) && BAYER(r, c))
177
10.5M
              tot += (n++, BAYER(r, c));
178
4.71M
        if (n)
179
4.71M
          BAYER(row, col) = tot / n;
180
4.71M
      }
181
235
  RUN_CALLBACK(LIBRAW_PROGRESS_REMOVE_ZEROES, 1, 2);
182
235
}
183
void LibRaw::crop_masked_pixels()
184
3.99k
{
185
3.99k
  int row, col;
186
3.99k
  unsigned c, m, zero, val;
187
43.1M
#define mblack imgdata.color.black_stat
188
189
3.99k
  if (mask[0][3] > 0)
190
291
    goto mask_set;
191
3.70k
  if (load_raw == &LibRaw::canon_load_raw ||
192
3.66k
      load_raw == &LibRaw::lossless_jpeg_load_raw ||
193
3.23k
      load_raw == &LibRaw::crxLoadRaw)
194
470
  {
195
470
    mask[0][1] = mask[1][1] += 2;
196
470
    mask[0][3] -= 2;
197
470
    goto sides;
198
470
  }
199
3.23k
  if (load_raw == &LibRaw::canon_600_load_raw ||
200
3.23k
      load_raw == &LibRaw::sony_load_raw ||
201
3.23k
      (load_raw == &LibRaw::eight_bit_load_raw && strncmp(model, "DC2", 3)) ||
202
3.22k
      load_raw == &LibRaw::kodak_262_load_raw ||
203
2.82k
      (load_raw == &LibRaw::packed_load_raw && (load_flags & 32)))
204
409
  {
205
879
  sides:
206
879
    mask[0][0] = mask[1][0] = top_margin;
207
879
    mask[0][2] = mask[1][2] = top_margin + height;
208
879
    mask[0][3] += left_margin;
209
879
    mask[1][1] += left_margin + width;
210
879
    mask[1][3] += raw_width;
211
879
  }
212
3.70k
  if (load_raw == &LibRaw::nokia_load_raw)
213
5
  {
214
5
    mask[0][2] = top_margin;
215
5
    mask[0][3] = width;
216
5
  }
217
3.70k
  if (load_raw == &LibRaw::broadcom_load_raw)
218
0
  {
219
0
    mask[0][2] = top_margin;
220
0
    mask[0][3] = width;
221
0
  }
222
3.99k
mask_set:
223
3.99k
  memset(mblack, 0, sizeof mblack);
224
35.9k
  for (zero = m = 0; m < 8; m++)
225
749k
    for (row = MAX(mask[m][0], 0); row < MIN(mask[m][2], raw_height); row++)
226
22.2M
      for (col = MAX(mask[m][1], 0); col < MIN(mask[m][3], raw_width); col++)
227
21.5M
      {
228
        /* No need to subtract margins because full area and active area filters are the same */
229
21.5M
        c = FC(row, col);
230
21.5M
        mblack[c] += val = raw_image[(row)*raw_pitch / 2 + (col)];
231
21.5M
        mblack[4 + c]++;
232
21.5M
        zero += !val;
233
21.5M
      }
234
3.99k
  if (load_raw == &LibRaw::canon_600_load_raw && width < raw_width)
235
0
  {
236
0
    black = (mblack[0] + mblack[1] + mblack[2] + mblack[3]) /
237
0
                MAX(1, (mblack[4] + mblack[5] + mblack[6] + mblack[7])) -
238
0
            4;
239
0
  }
240
3.99k
  else if (zero < mblack[4] && mblack[5] && mblack[6] && mblack[7])
241
39
  {
242
156
    FORC4 cblack[c] = mblack[c] / MAX(1, mblack[4 + c]);
243
39
    black = cblack[4] = cblack[5] = cblack[6] = 0;
244
39
  }
245
3.99k
}
246
#undef mblack
247
248
void LibRaw::pseudoinverse(double (*in)[3], double (*out)[3], int size)
249
13.2k
{
250
13.2k
  double work[3][6], num;
251
13.2k
  int i, j, k;
252
253
53.1k
  for (i = 0; i < 3; i++)
254
39.8k
  {
255
278k
    for (j = 0; j < 6; j++)
256
239k
      work[i][j] = j == i + 3;
257
159k
    for (j = 0; j < 3; j++)
258
481k
      for (k = 0; k < size && k < 4; k++)
259
362k
        work[i][j] += in[k][i] * in[k][j];
260
39.8k
  }
261
53.1k
  for (i = 0; i < 3; i++)
262
39.8k
  {
263
39.8k
    num = work[i][i];
264
278k
    for (j = 0; j < 6; j++)
265
239k
      if (fabs(num) > 0.00001f)
266
86.6k
        work[i][j] /= num;
267
159k
    for (k = 0; k < 3; k++)
268
119k
    {
269
119k
      if (k == i)
270
39.8k
        continue;
271
79.6k
      num = work[k][i];
272
557k
      for (j = 0; j < 6; j++)
273
478k
        work[k][j] -= work[i][j] * num;
274
79.6k
    }
275
39.8k
  }
276
53.5k
  for (i = 0; i < size && i < 4; i++)
277
160k
    for (j = 0; j < 3; j++)
278
482k
      for (out[i][j] = k = 0; k < 3; k++)
279
362k
        out[i][j] += work[j][k + 3] * in[i][k];
280
13.2k
}
281
282
void LibRaw::cam_xyz_coeff(float _rgb_cam[3][4], double cam_xyz[4][3])
283
12.7k
{
284
12.7k
  double cam_rgb[4][3], inverse[4][3], num;
285
12.7k
  int i, j, k;
286
287
51.1k
  for (i = 0; i < colors && i < 4; i++) /* Multiply out XYZ colorspace */
288
153k
    for (j = 0; j < 3; j++)
289
461k
      for (cam_rgb[i][j] = k = 0; k < 3; k++)
290
346k
        cam_rgb[i][j] += cam_xyz[i][k] * LibRaw_constants::xyz_rgb[k][j];
291
292
51.1k
  for (i = 0; i < colors && i < 4; i++)
293
38.4k
  {                               /* Normalize cam_rgb so that */
294
153k
    for (num = j = 0; j < 3; j++) /* cam_rgb * (1,1,1) is (1,1,1,1) */
295
115k
      num += cam_rgb[i][j];
296
38.4k
    if (num > 0.00001)
297
16.5k
    {
298
66.3k
      for (j = 0; j < 3; j++)
299
49.7k
        cam_rgb[i][j] /= num;
300
16.5k
      pre_mul[i] = float(1.0 / num);
301
16.5k
    }
302
21.8k
    else
303
21.8k
    {
304
87.5k
      for (j = 0; j < 3; j++)
305
65.6k
        cam_rgb[i][j] = 0.0;
306
21.8k
      pre_mul[i] = 1.0;
307
21.8k
    }
308
38.4k
  }
309
12.7k
  pseudoinverse(cam_rgb, inverse, colors);
310
50.8k
  for (i = 0; i < 3; i++)
311
153k
    for (j = 0; j < colors && j < 4; j++)
312
115k
      _rgb_cam[i][j] = float(inverse[j][i]);
313
12.7k
}
314
315
void LibRaw::tiff_get(INT64 base, unsigned *tag, unsigned *type,
316
                      unsigned *len, INT64 *save)
317
98.0M
{
318
98.0M
#ifdef LIBRAW_IOSPACE_CHECK
319
98.0M
  INT64 pos = ftell(ifp);
320
98.0M
  INT64 fsize = ifp->size();
321
98.0M
  if (fsize < 12 || (fsize - pos) < 12)
322
20.0k
    throw LIBRAW_EXCEPTION_IO_EOF;
323
98.0M
#endif
324
98.0M
  *tag = get2();
325
98.0M
  *type = get2();
326
98.0M
  *len = get4();
327
98.0M
  *save = ftell(ifp) + 4LL;
328
98.0M
  if (*len * tagtype_dataunit_bytes[(*type <= LIBRAW_EXIFTAG_TYPE_IFD8) ? *type : 0] > 4)
329
84.2M
    fseek(ifp, INT64(get4()) + base, SEEK_SET);
330
98.0M
}