Coverage Report

Created: 2026-10-28 07:09

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