Coverage Report

Created: 2026-08-31 07:17

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
12.8G
{
23
12.8G
  static const char filter[16][16] = {
24
12.8G
      {2, 1, 1, 3, 2, 3, 2, 0, 3, 2, 3, 0, 1, 2, 1, 0},
25
12.8G
      {0, 3, 0, 2, 0, 1, 3, 1, 0, 1, 1, 2, 0, 3, 3, 2},
26
12.8G
      {2, 3, 3, 2, 3, 1, 1, 3, 3, 1, 2, 1, 2, 0, 0, 3},
27
12.8G
      {0, 1, 0, 1, 0, 2, 0, 2, 2, 0, 3, 0, 1, 3, 2, 1},
28
12.8G
      {3, 1, 1, 2, 0, 1, 0, 2, 1, 3, 1, 3, 0, 1, 3, 0},
29
12.8G
      {2, 0, 0, 3, 3, 2, 3, 1, 2, 0, 2, 0, 3, 2, 2, 1},
30
12.8G
      {2, 3, 3, 1, 2, 1, 2, 1, 2, 1, 1, 2, 3, 0, 0, 1},
31
12.8G
      {1, 0, 0, 2, 3, 0, 0, 3, 0, 3, 0, 3, 2, 1, 2, 3},
32
12.8G
      {2, 3, 3, 1, 1, 2, 1, 0, 3, 2, 3, 0, 2, 3, 1, 3},
33
12.8G
      {1, 0, 2, 0, 3, 0, 3, 2, 0, 1, 1, 2, 0, 1, 0, 2},
34
12.8G
      {0, 1, 1, 3, 3, 2, 2, 1, 1, 3, 3, 0, 2, 1, 3, 2},
35
12.8G
      {2, 3, 2, 0, 0, 1, 3, 0, 2, 0, 1, 2, 3, 0, 1, 0},
36
12.8G
      {1, 3, 1, 2, 3, 2, 3, 2, 0, 2, 0, 1, 1, 0, 3, 0},
37
12.8G
      {0, 2, 0, 3, 1, 0, 0, 1, 1, 3, 3, 2, 3, 2, 2, 1},
38
12.8G
      {2, 1, 3, 2, 3, 1, 2, 1, 0, 3, 0, 2, 0, 2, 0, 2},
39
12.8G
      {0, 3, 1, 0, 0, 2, 0, 3, 2, 1, 3, 1, 1, 3, 1, 3}};
40
41
12.8G
  if (filters == 1)
42
39.9M
    return filter[(row + top_margin) & 15][(col + left_margin) & 15];
43
12.7G
  if (filters == 9)
44
4.77G
    return xtrans[(row + 6) % 6][(col + 6) % 6];
45
8.01G
  return FC(row, col);
46
12.7G
}
47
48
size_t LibRaw::strnlen(const char *s, size_t n)
49
854k
{
50
854k
#if !defined(__FreeBSD__) && !defined(__OpenBSD__)
51
854k
  const char *p = (const char *)memchr(s, 0, n);
52
854k
  return (p ? p - s : n);
53
#else
54
  return ::strnlen(s, n);
55
#endif
56
854k
}
57
58
void *LibRaw::memmem(char *haystack, size_t haystacklen, char *needle,
59
                     size_t needlelen)
60
219k
{
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
219k
  return ::memmem(haystack, haystacklen, needle, needlelen);
69
219k
#endif
70
219k
}
71
72
char *LibRaw::strcasestr(char *haystack, const char *needle)
73
5.20M
{
74
5.20M
  char *c;
75
48.7M
  for (c = haystack; *c; c++)
76
43.7M
    if (!strncasecmp(c, needle, strlen(needle)))
77
198k
      return c;
78
5.00M
  return 0;
79
5.20M
}
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
1.94k
{
129
1.94k
  static const double rgb_aRGB[3][3] = {
130
1.94k
      {1.39828313770000, -0.3982830047, 9.64980900741708E-8},
131
1.94k
      {6.09219200572997E-8, 0.9999999809, 1.33230799934103E-8},
132
1.94k
      {2.17237099975343E-8, -0.0429383201, 1.04293828050000}};
133
134
1.94k
  double cmatrix_tmp[3][3] = {
135
1.94k
      {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
136
1.94k
  int i, j, k;
137
138
7.76k
  for (i = 0; i < 3; i++)
139
23.2k
    for (j = 0; j < 3; j++)
140
17.4k
    {
141
69.8k
      for (k = 0; k < 3; k++)
142
52.4k
        cmatrix_tmp[i][j] += rgb_aRGB[i][k] * aRGB_cam[k][j];
143
17.4k
      cmatrix[i][j] = (float)cmatrix_tmp[i][j];
144
17.4k
    }
145
1.94k
}
146
147
void LibRaw::romm_coeff(float romm_cam[3][3])
148
4.38k
{
149
4.38k
  static const float rgb_romm[3][3] = /* ROMM == Kodak ProPhoto */
150
4.38k
      {{2.034193f, -0.727420f, -0.306766f},
151
4.38k
       {-0.228811f, 1.231729f, -0.002922f},
152
4.38k
       {-0.008565f, -0.153273f, 1.161839f}};
153
4.38k
  int i, j, k;
154
155
17.5k
  for (i = 0; i < 3; i++)
156
52.6k
    for (j = 0; j < 3; j++)
157
157k
      for (cmatrix[i][j] = 0.f, k = 0; k < 3; k++)
158
118k
        cmatrix[i][j] += float(rgb_romm[i][k] * romm_cam[k][j]);
159
4.38k
}
160
161
void LibRaw::remove_zeroes()
162
4.27k
{
163
4.27k
  unsigned row, col, tot, n;
164
4.27k
  int r, c;
165
166
4.27k
  RUN_CALLBACK(LIBRAW_PROGRESS_REMOVE_ZEROES, 0, 2);
167
168
223k
  for (row = 0; row < height; row++)
169
26.6M
    for (col = 0; col < width; col++)
170
26.4M
      if (BAYER(row, col) == 0)
171
14.3M
      {
172
14.3M
        tot = n = 0;
173
86.3M
        for (r = (int)row - 2; r <= (int)row + 2; r++)
174
431M
          for (c = (int)col - 2; c <= (int)col + 2; c++)
175
359M
            if (r >= 0 && r < height && c >= 0 && c < width &&
176
359M
                FC(r, c) == FC(row, col) && BAYER(r, c))
177
38.2M
              tot += (n++, BAYER(r, c));
178
14.3M
        if (n)
179
14.3M
          BAYER(row, col) = tot / n;
180
14.3M
      }
181
4.27k
  RUN_CALLBACK(LIBRAW_PROGRESS_REMOVE_ZEROES, 1, 2);
182
4.27k
}
183
void LibRaw::crop_masked_pixels()
184
12.4k
{
185
12.4k
  int row, col;
186
12.4k
  unsigned c, m, zero, val;
187
389M
#define mblack imgdata.color.black_stat
188
189
12.4k
  if (mask[0][3] > 0)
190
282
    goto mask_set;
191
12.1k
  if (load_raw == &LibRaw::canon_load_raw ||
192
11.9k
      load_raw == &LibRaw::lossless_jpeg_load_raw ||
193
11.0k
      load_raw == &LibRaw::crxLoadRaw)
194
1.07k
  {
195
1.07k
    mask[0][1] = mask[1][1] += 2;
196
1.07k
    mask[0][3] -= 2;
197
1.07k
    goto sides;
198
1.07k
  }
199
11.0k
  if (load_raw == &LibRaw::canon_600_load_raw ||
200
10.8k
      load_raw == &LibRaw::sony_load_raw ||
201
10.8k
      (load_raw == &LibRaw::eight_bit_load_raw && strncmp(model, "DC2", 3)) ||
202
10.7k
      load_raw == &LibRaw::kodak_262_load_raw ||
203
9.83k
      (load_raw == &LibRaw::packed_load_raw && (load_flags & 32)))
204
1.22k
  {
205
2.30k
  sides:
206
2.30k
    mask[0][0] = mask[1][0] = top_margin;
207
2.30k
    mask[0][2] = mask[1][2] = top_margin + height;
208
2.30k
    mask[0][3] += left_margin;
209
2.30k
    mask[1][1] += left_margin + width;
210
2.30k
    mask[1][3] += raw_width;
211
2.30k
  }
212
12.1k
  if (load_raw == &LibRaw::nokia_load_raw)
213
7
  {
214
7
    mask[0][2] = top_margin;
215
7
    mask[0][3] = width;
216
7
  }
217
12.1k
  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
12.4k
mask_set:
223
12.4k
  memset(mblack, 0, sizeof mblack);
224
111k
  for (zero = m = 0; m < 8; m++)
225
10.0M
    for (row = MAX(mask[m][0], 0); row < MIN(mask[m][2], raw_height); row++)
226
204M
      for (col = MAX(mask[m][1], 0); col < MIN(mask[m][3], raw_width); col++)
227
194M
      {
228
        /* No need to subtract margins because full area and active area filters are the same */
229
194M
        c = FC(row, col);
230
194M
        mblack[c] += val = raw_image[(row)*raw_pitch / 2 + (col)];
231
194M
        mblack[4 + c]++;
232
194M
        zero += !val;
233
194M
      }
234
12.4k
  if (load_raw == &LibRaw::canon_600_load_raw && width < raw_width)
235
178
  {
236
178
    black = (mblack[0] + mblack[1] + mblack[2] + mblack[3]) /
237
178
                MAX(1, (mblack[4] + mblack[5] + mblack[6] + mblack[7])) -
238
178
            4;
239
178
  }
240
12.2k
  else if (zero < mblack[4] && mblack[5] && mblack[6] && mblack[7])
241
208
  {
242
832
    FORC4 cblack[c] = mblack[c] / MAX(1, mblack[4 + c]);
243
208
    black = cblack[4] = cblack[5] = cblack[6] = 0;
244
208
  }
245
12.4k
}
246
#undef mblack
247
248
void LibRaw::pseudoinverse(double (*in)[3], double (*out)[3], int size)
249
17.2k
{
250
17.2k
  double work[3][6], num;
251
17.2k
  int i, j, k;
252
253
68.8k
  for (i = 0; i < 3; i++)
254
51.6k
  {
255
361k
    for (j = 0; j < 6; j++)
256
309k
      work[i][j] = j == i + 3;
257
206k
    for (j = 0; j < 3; j++)
258
616k
      for (k = 0; k < size && k < 4; k++)
259
461k
        work[i][j] += in[k][i] * in[k][j];
260
51.6k
  }
261
68.8k
  for (i = 0; i < 3; i++)
262
51.6k
  {
263
51.6k
    num = work[i][i];
264
361k
    for (j = 0; j < 6; j++)
265
309k
      if (fabs(num) > 0.00001f)
266
273k
        work[i][j] /= num;
267
206k
    for (k = 0; k < 3; k++)
268
154k
    {
269
154k
      if (k == i)
270
51.6k
        continue;
271
103k
      num = work[k][i];
272
723k
      for (j = 0; j < 6; j++)
273
619k
        work[k][j] -= work[i][j] * num;
274
103k
    }
275
51.6k
  }
276
68.5k
  for (i = 0; i < size && i < 4; i++)
277
205k
    for (j = 0; j < 3; j++)
278
615k
      for (out[i][j] = k = 0; k < 3; k++)
279
461k
        out[i][j] += work[j][k + 3] * in[i][k];
280
17.2k
}
281
282
void LibRaw::cam_xyz_coeff(float _rgb_cam[3][4], double cam_xyz[4][3])
283
8.67k
{
284
8.67k
  double cam_rgb[4][3], inverse[4][3], num;
285
8.67k
  int i, j, k;
286
287
34.3k
  for (i = 0; i < colors && i < 4; i++) /* Multiply out XYZ colorspace */
288
102k
    for (j = 0; j < 3; j++)
289
308k
      for (cam_rgb[i][j] = k = 0; k < 3; k++)
290
231k
        cam_rgb[i][j] += cam_xyz[i][k] * LibRaw_constants::xyz_rgb[k][j];
291
292
34.3k
  for (i = 0; i < colors && i < 4; i++)
293
25.6k
  {                               /* Normalize cam_rgb so that */
294
102k
    for (num = j = 0; j < 3; j++) /* cam_rgb * (1,1,1) is (1,1,1,1) */
295
77.0k
      num += cam_rgb[i][j];
296
25.6k
    if (num > 0.00001)
297
21.6k
    {
298
86.5k
      for (j = 0; j < 3; j++)
299
64.8k
        cam_rgb[i][j] /= num;
300
21.6k
      pre_mul[i] = float(1.0 / num);
301
21.6k
    }
302
4.07k
    else
303
4.07k
    {
304
16.2k
      for (j = 0; j < 3; j++)
305
12.2k
        cam_rgb[i][j] = 0.0;
306
4.07k
      pre_mul[i] = 1.0;
307
4.07k
    }
308
25.6k
  }
309
8.67k
  pseudoinverse(cam_rgb, inverse, colors);
310
34.6k
  for (i = 0; i < 3; i++)
311
103k
    for (j = 0; j < colors && j < 4; j++)
312
77.0k
      _rgb_cam[i][j] = float(inverse[j][i]);
313
8.67k
}
314
315
void LibRaw::tiff_get(INT64 base, unsigned *tag, unsigned *type,
316
                      unsigned *len, INT64 *save)
317
639M
{
318
639M
#ifdef LIBRAW_IOSPACE_CHECK
319
639M
  INT64 pos = ftell(ifp);
320
639M
  INT64 fsize = ifp->size();
321
639M
  if (fsize < 12 || (fsize - pos) < 12)
322
33.1k
    throw LIBRAW_EXCEPTION_IO_EOF;
323
639M
#endif
324
639M
  *tag = get2();
325
639M
  *type = get2();
326
639M
  *len = get4();
327
639M
  *save = ftell(ifp) + 4LL;
328
639M
  if (*len * tagtype_dataunit_bytes[(*type <= LIBRAW_EXIFTAG_TYPE_IFD8) ? *type : 0] > 4)
329
559M
    fseek(ifp, INT64(get4()) + base, SEEK_SET);
330
639M
}