Coverage Report

Created: 2026-06-02 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/freeimage-svn/FreeImage/trunk/Source/LibRawLite/src/utils/thumb_utils.cpp
Line
Count
Source
1
/* -*- C++ -*-
2
 * Copyright 2019-2021 LibRaw LLC (info@libraw.org)
3
 *
4
5
 LibRaw is free software; you can redistribute it and/or modify
6
 it under the terms of the one of two licenses as you choose:
7
8
1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
9
   (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
10
11
2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
12
   (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
13
14
 */
15
16
#include "../../internal/libraw_cxx_defs.h"
17
18
void LibRaw::kodak_thumb_loader()
19
0
{
20
0
  INT64 est_datasize =
21
0
      T.theight * T.twidth / 3; // is 0.3 bytes per pixel good estimate?
22
0
  if (ID.toffset < 0)
23
0
    throw LIBRAW_EXCEPTION_IO_CORRUPT;
24
25
0
  if (ID.toffset + est_datasize > ID.input->size() + THUMB_READ_BEYOND)
26
0
    throw LIBRAW_EXCEPTION_IO_EOF;
27
28
0
  if(INT64(T.theight) * INT64(T.twidth) > 1024ULL * 1024ULL * LIBRAW_MAX_THUMBNAIL_MB)
29
0
      throw LIBRAW_EXCEPTION_IO_CORRUPT;
30
31
0
  if (INT64(T.theight) * INT64(T.twidth) < 64ULL)
32
0
      throw LIBRAW_EXCEPTION_IO_CORRUPT;
33
34
0
  if(T.twidth < 16 || T.twidth > 8192 || T.theight < 16 || T.theight > 8192)
35
0
    throw LIBRAW_EXCEPTION_IO_CORRUPT;
36
37
  // some kodak cameras
38
0
  ushort s_height = S.height, s_width = S.width, s_iwidth = S.iwidth,
39
0
         s_iheight = S.iheight;
40
0
  ushort s_flags = libraw_internal_data.unpacker_data.load_flags;
41
0
  libraw_internal_data.unpacker_data.load_flags = 12;
42
0
  int s_colors = P1.colors;
43
0
  unsigned s_filters = P1.filters;
44
0
  ushort(*s_image)[4] = imgdata.image;
45
46
0
  S.height = T.theight;
47
0
  S.width = T.twidth;
48
0
  P1.filters = 0;
49
50
0
#define Tformat libraw_internal_data.unpacker_data.thumb_format
51
52
53
0
  if (Tformat == LIBRAW_INTERNAL_THUMBNAIL_KODAK_YCBCR)
54
0
  {
55
0
    S.height += S.height & 1;
56
0
    S.width += S.width & 1;
57
0
  }
58
59
0
  S.iheight = S.height;
60
0
  S.iwidth = S.width;
61
62
0
  imgdata.image =
63
0
      (ushort(*)[4])calloc(S.iheight * S.iwidth, sizeof(*imgdata.image));
64
65
0
  ID.input->seek(ID.toffset, SEEK_SET);
66
  // read kodak thumbnail into T.image[]
67
0
  try
68
0
  {
69
0
      if (Tformat == LIBRAW_INTERNAL_THUMBNAIL_KODAK_YCBCR)
70
0
          kodak_ycbcr_load_raw();
71
0
      else if(Tformat == LIBRAW_INTERNAL_THUMBNAIL_KODAK_RGB)
72
0
        kodak_rgb_load_raw();
73
0
      else if (Tformat == LIBRAW_INTERNAL_THUMBNAIL_KODAK_THUMB)
74
0
        kodak_thumb_load_raw();
75
0
  }
76
0
  catch (...)
77
0
  {
78
0
    free(imgdata.image);
79
0
    imgdata.image = s_image;
80
81
0
    T.twidth = 0;
82
0
    S.width = s_width;
83
84
0
    S.iwidth = s_iwidth;
85
0
    S.iheight = s_iheight;
86
87
0
    T.theight = 0;
88
0
    S.height = s_height;
89
90
0
    T.tcolors = 0;
91
0
    P1.colors = s_colors;
92
93
0
    P1.filters = s_filters;
94
0
    T.tlength = 0;
95
0
    libraw_internal_data.unpacker_data.load_flags = s_flags;
96
0
    return;
97
0
  }
98
99
  // from scale_colors
100
0
  {
101
0
    double dmax;
102
0
    float scale_mul[4];
103
0
    int c, val;
104
0
    for (dmax = DBL_MAX, c = 0; c < 3; c++)
105
0
      if (dmax > C.pre_mul[c])
106
0
        dmax = C.pre_mul[c];
107
108
0
    for (c = 0; c < 3; c++)
109
0
      scale_mul[c] = (C.pre_mul[c] / dmax) * 65535.0 / C.maximum;
110
0
    scale_mul[3] = scale_mul[1];
111
112
0
    size_t size = S.height * S.width;
113
0
    for (unsigned i = 0; i < size * 4; i++)
114
0
    {
115
0
      val = imgdata.image[0][i];
116
0
      if (!val)
117
0
        continue;
118
0
      val *= scale_mul[i & 3];
119
0
      imgdata.image[0][i] = CLIP(val);
120
0
    }
121
0
  }
122
123
  // from convert_to_rgb
124
0
  ushort *img;
125
0
  int row, col;
126
127
0
  int(*t_hist)[LIBRAW_HISTOGRAM_SIZE] =
128
0
      (int(*)[LIBRAW_HISTOGRAM_SIZE])calloc(sizeof(*t_hist), 4);
129
130
0
  float out[3], out_cam[3][4] = {{2.81761312f, -1.98369181f, 0.166078627f, 0},
131
0
                                 {-0.111855984f, 1.73688626f, -0.625030339f, 0},
132
0
                                 {-0.0379119813f, -0.891268849f, 1.92918086f, 0}};
133
134
0
  for (img = imgdata.image[0], row = 0; row < S.height; row++)
135
0
    for (col = 0; col < S.width; col++, img += 4)
136
0
    {
137
0
      out[0] = out[1] = out[2] = 0;
138
0
      int c;
139
0
      for (c = 0; c < 3; c++)
140
0
      {
141
0
        out[0] += out_cam[0][c] * img[c];
142
0
        out[1] += out_cam[1][c] * img[c];
143
0
        out[2] += out_cam[2][c] * img[c];
144
0
      }
145
0
      for (c = 0; c < 3; c++)
146
0
        img[c] = CLIP((int)out[c]);
147
0
      for (c = 0; c < P1.colors; c++)
148
0
        t_hist[c][img[c] >> 3]++;
149
0
    }
150
151
  // from gamma_lut
152
0
  int(*save_hist)[LIBRAW_HISTOGRAM_SIZE] =
153
0
      libraw_internal_data.output_data.histogram;
154
0
  libraw_internal_data.output_data.histogram = t_hist;
155
156
  // make curve output curve!
157
0
  ushort *t_curve = (ushort *)calloc(sizeof(C.curve), 1);
158
0
  memmove(t_curve, C.curve, sizeof(C.curve));
159
0
  memset(C.curve, 0, sizeof(C.curve));
160
0
  {
161
0
    int perc, val, total, t_white = 0x2000, c;
162
163
0
    perc = S.width * S.height * 0.01; /* 99th percentile white level */
164
0
    if (IO.fuji_width)
165
0
      perc /= 2;
166
0
    if (!((O.highlight & ~2) || O.no_auto_bright))
167
0
      for (t_white = c = 0; c < P1.colors; c++)
168
0
      {
169
0
        for (val = 0x2000, total = 0; --val > 32;)
170
0
          if ((total += libraw_internal_data.output_data.histogram[c][val]) >
171
0
              perc)
172
0
            break;
173
0
        if (t_white < val)
174
0
          t_white = val;
175
0
      }
176
0
    gamma_curve(O.gamm[0], O.gamm[1], 2, (t_white << 3) / O.bright);
177
0
  }
178
179
0
  libraw_internal_data.output_data.histogram = save_hist;
180
0
  free(t_hist);
181
182
  // from write_ppm_tiff - copy pixels into bitmap
183
184
0
  int s_flip = imgdata.sizes.flip;
185
0
  if (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_NO_ROTATE_FOR_KODAK_THUMBNAILS)
186
0
    imgdata.sizes.flip = 0;
187
188
0
  S.iheight = S.height;
189
0
  S.iwidth = S.width;
190
0
  if (S.flip & 4)
191
0
    SWAP(S.height, S.width);
192
193
0
  if (T.thumb)
194
0
    free(T.thumb);
195
0
  T.thumb = (char *)calloc(S.width * S.height, P1.colors);
196
0
  T.tlength = S.width * S.height * P1.colors;
197
198
  // from write_tiff_ppm
199
0
  {
200
0
    int soff = flip_index(0, 0);
201
0
    int cstep = flip_index(0, 1) - soff;
202
0
    int rstep = flip_index(1, 0) - flip_index(0, S.width);
203
204
0
    for (int rr = 0; rr < S.height; rr++, soff += rstep)
205
0
    {
206
0
      char *ppm = T.thumb + rr * S.width * P1.colors;
207
0
      for (int cc = 0; cc < S.width; cc++, soff += cstep)
208
0
        for (int c = 0; c < P1.colors; c++)
209
0
          ppm[cc * P1.colors + c] =
210
0
              imgdata.color.curve[imgdata.image[soff][c]] >> 8;
211
0
    }
212
0
  }
213
214
0
  memmove(C.curve, t_curve, sizeof(C.curve));
215
0
  free(t_curve);
216
217
  // restore variables
218
0
  free(imgdata.image);
219
0
  imgdata.image = s_image;
220
221
0
  if (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_NO_ROTATE_FOR_KODAK_THUMBNAILS)
222
0
    imgdata.sizes.flip = s_flip;
223
224
0
  T.twidth = S.width;
225
0
  S.width = s_width;
226
227
0
  S.iwidth = s_iwidth;
228
0
  S.iheight = s_iheight;
229
230
0
  T.theight = S.height;
231
0
  S.height = s_height;
232
233
0
  T.tcolors = P1.colors;
234
0
  P1.colors = s_colors;
235
236
0
  P1.filters = s_filters;
237
0
  libraw_internal_data.unpacker_data.load_flags = s_flags;
238
0
}
239
240
// ������� thumbnail �� �����, ������ thumb_format � ������������ � ��������
241
242
int LibRaw::thumbOK(INT64 maxsz)
243
0
{
244
0
  if (!ID.input)
245
0
    return 0;
246
0
  if (!ID.toffset && !(imgdata.thumbnail.tlength > 0 &&
247
0
                       load_raw == &LibRaw::broadcom_load_raw) // RPi
248
#ifdef USE_6BY9RPI
249
      && !(imgdata.thumbnail.tlength > 0 && libraw_internal_data.unpacker_data.load_flags & 0x4000 &&
250
           (load_raw == &LibRaw::rpi_load_raw8 || load_raw == &LibRaw::nokia_load_raw ||
251
            load_raw == &LibRaw::rpi_load_raw12 || load_raw == &LibRaw::rpi_load_raw14))
252
#endif
253
0
  )
254
0
    return 0;
255
0
  INT64 fsize = ID.input->size();
256
0
  if (fsize > 0xffffffffU)
257
0
    return 0; // No thumb for raw > 4Gb-1
258
0
  int tsize = 0;
259
0
  int tcol = (T.tcolors > 0 && T.tcolors < 4) ? T.tcolors : 3;
260
0
  if (Tformat == LIBRAW_INTERNAL_THUMBNAIL_JPEG)
261
0
    tsize = T.tlength;
262
0
  else if (Tformat == LIBRAW_INTERNAL_THUMBNAIL_PPM)
263
0
    tsize = tcol * T.twidth * T.theight;
264
0
  else if (Tformat == LIBRAW_INTERNAL_THUMBNAIL_PPM16)
265
0
    tsize = tcol * T.twidth * T.theight *
266
0
            ((imgdata.rawparams.options & LIBRAW_RAWOPTIONS_USE_PPM16_THUMBS) ? 2 : 1);
267
#ifdef USE_X3FTOOLS
268
  else if (Tformat == LIBRAW_INTERNAL_THUMBNAIL_X3F)
269
  {
270
    tsize = x3f_thumb_size();
271
  }
272
#endif
273
0
  else // Kodak => no check
274
0
    tsize = 1;
275
0
  if (tsize < 0)
276
0
    return 0;
277
0
  if (maxsz > 0 && tsize > maxsz)
278
0
    return 0;
279
0
  return (tsize + ID.toffset <= fsize) ? 1 : 0;
280
0
}
281
282
int LibRaw::dcraw_thumb_writer(const char *fname)
283
0
{
284
  //    CHECK_ORDER_LOW(LIBRAW_PROGRESS_THUMB_LOAD);
285
286
0
  if (!fname)
287
0
    return ENOENT;
288
289
0
  FILE *tfp = fopen(fname, "wb");
290
291
0
  if (!tfp)
292
0
    return errno;
293
294
0
  if (!T.thumb)
295
0
  {
296
0
    fclose(tfp);
297
0
    return LIBRAW_OUT_OF_ORDER_CALL;
298
0
  }
299
300
0
  try
301
0
  {
302
0
    switch (T.tformat)
303
0
    {
304
0
    case LIBRAW_THUMBNAIL_JPEG:
305
0
      jpeg_thumb_writer(tfp, T.thumb, T.tlength);
306
0
      break;
307
0
    case LIBRAW_THUMBNAIL_BITMAP:
308
0
      fprintf(tfp, "P%d\n%d %d\n255\n", T.tcolors == 1 ? 5 : 6,  T.twidth, T.theight);
309
0
      fwrite(T.thumb, 1, T.tlength, tfp);
310
0
      break;
311
0
    default:
312
0
      fclose(tfp);
313
0
      return LIBRAW_UNSUPPORTED_THUMBNAIL;
314
0
    }
315
0
    fclose(tfp);
316
0
    return 0;
317
0
  }
318
0
  catch (const std::bad_alloc&)
319
0
  {
320
0
      fclose(tfp);
321
0
      EXCEPTION_HANDLER(LIBRAW_EXCEPTION_ALLOC);
322
0
  }
323
0
  catch (const LibRaw_exceptions& err)
324
0
  {
325
0
    fclose(tfp);
326
0
    EXCEPTION_HANDLER(err);
327
0
  }
328
0
}