Coverage Report

Created: 2026-10-27 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/LibRaw/src/decoders/dng.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
void LibRaw::vc5_dng_load_raw_placeholder()
22
2
{
23
    // placeholder only, real decoding implemented in GPR SDK
24
2
    if(!dng_version)
25
0
      throw LIBRAW_EXCEPTION_IO_EOF; // never reached
26
2
    throw LIBRAW_EXCEPTION_UNSUPPORTED_FORMAT;
27
2
}
28
void LibRaw::jxl_dng_load_raw_placeholder()
29
1
{
30
  // placeholder only, real decoding implemented in DNG SDK
31
1
  throw LIBRAW_EXCEPTION_UNSUPPORTED_FORMAT;
32
1
}
33
34
void LibRaw::adobe_copy_pixel(unsigned row, unsigned col, ushort **rp)
35
1.70M
{
36
1.70M
  int c;
37
38
1.70M
  if (tiff_samples == 2 && shot_select)
39
0
    (*rp)++;
40
1.70M
  if (raw_image)
41
493k
  {
42
493k
    if (row < raw_height && col < raw_width)
43
493k
      RAW(row, col) = curve[**rp];
44
493k
    *rp += tiff_samples;
45
493k
  }
46
1.21M
  else
47
1.21M
  {
48
1.21M
    if (row < raw_height && col < raw_width)
49
975k
      FORC(int(tiff_samples))
50
2.93M
    image[row * raw_width + col][c] = curve[(*rp)[c]];
51
1.21M
    *rp += tiff_samples;
52
1.21M
  }
53
1.70M
  if (tiff_samples == 2 && shot_select)
54
0
    (*rp)--;
55
1.70M
}
56
void LibRaw::lossless_dng_load_raw()
57
39
{
58
39
  unsigned trow = 0, tcol = 0, jwide, jrow, jcol, row, col, i, j;
59
39
  INT64 save;
60
39
  struct jhead jh;
61
39
  ushort *rp;
62
63
39
  int ss = shot_select;
64
39
  shot_select = libraw_internal_data.unpacker_data.dng_frames[LIM(ss,0,(LIBRAW_IFD_MAXCOUNT*2-1))] & 0xff;
65
66
69
  while (trow < raw_height)
67
67
  {
68
67
    checkCancel();
69
67
    save = ftell(ifp);
70
67
    if (tile_length < INT_MAX)
71
63
      fseek(ifp, get4(), SEEK_SET);
72
67
    if (!ljpeg_start(&jh, 0))
73
32
      break;
74
35
    jwide = jh.wide;
75
35
    if (filters || colors == 1)
76
0
      jwide *= jh.clrs;
77
78
35
    if(filters && (tiff_samples == 2)) // Fuji Super CCD
79
0
        jwide /= 2;
80
35
    try
81
35
    {
82
35
      switch (jh.algo)
83
35
      {
84
0
      case 0xc1:
85
0
    if (tiff_samples > 1)
86
0
      throw LIBRAW_EXCEPTION_IO_CORRUPT;
87
0
        jh.vpred[0] = 16384;
88
0
        getbits(-1);
89
0
        for (jrow = 0; jrow + 7 < (unsigned)jh.high; jrow += 8)
90
0
        {
91
0
          checkCancel();
92
0
          for (jcol = 0; jcol + 7 < (unsigned)jh.wide; jcol += 8)
93
0
          {
94
0
            ljpeg_idct(&jh);
95
0
            rp = jh.idct;
96
0
            row = trow + jcol / tile_width + jrow * 2;
97
0
            col = tcol + jcol % tile_width;
98
0
            for (i = 0; i < 16; i += 2)
99
0
              for (j = 0; j < 8; j++)
100
0
                adobe_copy_pixel(row + i, col + j, &rp);
101
0
          }
102
0
        }
103
0
        break;
104
35
      case 0xc3:
105
517k
        for (row = col = jrow = 0; jrow < (unsigned)jh.high; jrow++)
106
517k
        {
107
517k
          checkCancel();
108
517k
          rp = ljpeg_row(jrow, &jh);
109
517k
          if (tiff_samples == 1 && jh.clrs > 1 && jh.clrs * jwide == raw_width)
110
0
            for (jcol = 0; jcol < jwide * jh.clrs; jcol++)
111
0
            {
112
0
              adobe_copy_pixel(trow + row, tcol + col, &rp);
113
0
              if (++col >= tile_width || col >= raw_width)
114
0
                row += 1 + (col = 0);
115
0
            }
116
517k
          else
117
1.69M
            for (jcol = 0; jcol < jwide; jcol++)
118
1.17M
            {
119
1.17M
              adobe_copy_pixel(trow + row, tcol + col, &rp);
120
1.17M
              if (++col >= tile_width || col >= raw_width)
121
189k
                row += 1 + (col = 0);
122
1.17M
            }
123
517k
        }
124
35
      }
125
35
    }
126
35
    catch (...)
127
35
    {
128
5
      ljpeg_end(&jh);
129
5
      shot_select = ss;
130
5
      throw;
131
5
    }
132
30
    fseek(ifp, save + 4, SEEK_SET);
133
30
    if ((tcol += tile_width) >= raw_width)
134
9
      trow += tile_length + (tcol = 0);
135
30
    ljpeg_end(&jh);
136
30
  }
137
34
  shot_select = ss;
138
34
}
139
140
void LibRaw::packed_dng_load_raw()
141
121
{
142
121
  ushort *pixel, *rp;
143
121
  unsigned row, col;
144
145
121
  if (tile_length < INT_MAX)
146
58
  {
147
58
      packed_tiled_dng_load_raw();
148
58
      return;
149
58
  }
150
151
63
  int ss = shot_select;
152
63
  shot_select = libraw_internal_data.unpacker_data.dng_frames[LIM(ss,0,(LIBRAW_IFD_MAXCOUNT*2-1))] & 0xff;
153
154
63
  pixel = (ushort *)calloc(raw_width, tiff_samples * sizeof *pixel);
155
63
  try
156
63
  {
157
1.63k
    for (row = 0; row < raw_height; row++)
158
1.57k
    {
159
1.57k
      checkCancel();
160
1.57k
      if (tiff_bps == 16)
161
308
        read_shorts(pixel, raw_width * tiff_samples);
162
1.26k
      else
163
1.26k
      {
164
1.26k
        getbits(-1);
165
218k
        for (col = 0; col < raw_width * tiff_samples; col++)
166
216k
          pixel[col] = getbits(tiff_bps);
167
1.26k
      }
168
212k
      for (rp = pixel, col = 0; col < raw_width; col++)
169
210k
        adobe_copy_pixel(row, col, &rp);
170
1.57k
    }
171
63
  }
172
63
  catch (...)
173
63
  {
174
59
    free(pixel);
175
59
    shot_select = ss;
176
59
    throw;
177
59
  }
178
4
  free(pixel);
179
4
  shot_select = ss;
180
4
}
181
#ifdef NO_JPEG
182
void LibRaw::lossy_dng_load_raw() {}
183
#else
184
185
static void jpegErrorExit_d(j_common_ptr /*cinfo*/)
186
0
{
187
0
  throw LIBRAW_EXCEPTION_DECODE_JPEG;
188
0
}
189
190
void LibRaw::lossy_dng_load_raw()
191
1
{
192
1
  if (!image)
193
1
    throw LIBRAW_EXCEPTION_IO_CORRUPT;
194
0
  struct jpeg_decompress_struct cinfo;
195
196
0
  unsigned sorder = order, ntags, opcode, deg, i, j, c;
197
0
  unsigned trow = 0, tcol = 0, row, col;
198
0
  INT64 save = data_offset - 4;
199
0
  ushort cur[4][256];
200
0
  double coeff[9], tot;
201
202
  // Initialize the whole curve table with the default gamma curve first:
203
  // an OpcodeList2 tag (meta_offset) carrying zero opcodes, or none of type
204
  // PolynomialMap(8), must not leave cur[][] uninitialized.
205
0
  gamma_curve(1 / 2.4, 12.92, 1, 255);
206
0
  FORC4 memcpy(cur[c], curve, sizeof cur[0]);
207
208
0
  if (meta_offset)
209
0
  {
210
0
    fseek(ifp, meta_offset, SEEK_SET);
211
0
    order = 0x4d4d;
212
0
    ntags = get4();
213
0
    while (ntags--)
214
0
    {
215
0
      opcode = get4();
216
0
      get4();
217
0
      get4();
218
0
      if (opcode != 8)
219
0
      {
220
0
        fseek(ifp, get4(), SEEK_CUR);
221
0
        continue;
222
0
      }
223
0
      fseek(ifp, 20, SEEK_CUR);
224
0
      if ((c = get4()) > 3)
225
0
        break;
226
0
      fseek(ifp, 12, SEEK_CUR);
227
0
      if ((deg = get4()) > 8)
228
0
        break;
229
0
      for (i = 0; i <= deg && i < 9; i++)
230
0
        coeff[i] = getreal(LIBRAW_EXIFTAG_TYPE_DOUBLE);
231
0
      for (i = 0; i < 256; i++)
232
0
      {
233
0
        for (tot = j = 0; j <= deg; j++)
234
0
          tot += coeff[j] * pow(i / 255.0, (int)j);
235
0
        cur[c][i] = (ushort)(tot * 0xffff);
236
0
      }
237
0
    }
238
0
    order = sorder;
239
0
  }
240
241
0
  struct jpeg_error_mgr pub;
242
0
  cinfo.err = jpeg_std_error(&pub);
243
0
  pub.error_exit = jpegErrorExit_d;
244
245
0
  std::vector<JSAMPLE> buf;
246
247
0
  jpeg_create_decompress(&cinfo);
248
249
0
  while (trow < raw_height)
250
0
  {
251
0
    fseek(ifp, save += 4, SEEK_SET);
252
0
    if (tile_length < INT_MAX)
253
0
      fseek(ifp, get4(), SEEK_SET);
254
0
    if (libraw_internal_data.internal_data.input->jpeg_src(&cinfo) == -1)
255
0
    {
256
0
      jpeg_destroy_decompress(&cinfo);
257
0
      throw LIBRAW_EXCEPTION_DECODE_JPEG;
258
0
    }
259
0
    jpeg_read_header(&cinfo, TRUE);
260
0
    jpeg_start_decompress(&cinfo);
261
0
  if (cinfo.output_components != colors)
262
0
    throw LIBRAW_EXCEPTION_DECODE_JPEG;
263
264
0
  if (buf.size() < cinfo.output_width * cinfo.output_components)
265
0
    buf = std::vector<JSAMPLE>(cinfo.output_width * cinfo.output_components,0);
266
267
0
    try
268
0
    {
269
0
      JSAMPLE *buffer_array[1];
270
0
      buffer_array[0] = buf.data();
271
0
      while (cinfo.output_scanline < cinfo.output_height &&
272
0
             (row = trow + cinfo.output_scanline) < height)
273
0
      {
274
0
        checkCancel();
275
0
        jpeg_read_scanlines(&cinfo, buffer_array, 1);
276
0
        for (col = 0; col < cinfo.output_width && tcol + col < width; col++)
277
0
        {
278
0
          FORC(colors) image[row * width + tcol + col][c] = cur[c][buf[col*colors+c]];
279
0
        }
280
0
      }
281
0
    }
282
0
    catch (...)
283
0
    {
284
0
      jpeg_destroy_decompress(&cinfo);
285
0
      throw;
286
0
    }
287
0
    jpeg_abort_decompress(&cinfo);
288
0
    if ((tcol += tile_width) >= raw_width)
289
0
      trow += tile_length + (tcol = 0);
290
0
  }
291
0
  jpeg_destroy_decompress(&cinfo);
292
0
  maximum = 0xffff;
293
0
}
294
#endif