Coverage Report

Created: 2026-09-28 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libraw/src/metadata/ciff.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
#ifdef _MSC_VER
21
#if _MSC_VER < 1800 /* below MSVC 2013 */
22
float roundf(float f)
23
{
24
 return floorf(f + 0.5);
25
}
26
27
#endif
28
#endif
29
30
/*
31
   CIFF block 0x1030 contains an 8x8 white sample.
32
   Load this into white[][] for use in scale_colors().
33
 */
34
void LibRaw::ciff_block_1030()
35
1.63k
{
36
1.63k
  static const ushort key[] = {0x410, 0x45f3};
37
1.63k
  int i, bpp, row, col, vbits = 0;
38
1.63k
  unsigned long bitbuf = 0;
39
40
1.63k
  if ((get2(), get4()) != 0x80008 || !get4())
41
1.17k
    return;
42
466
  bpp = get2();
43
466
  if (bpp != 10 && bpp != 12)
44
336
    return;
45
1.17k
  for (i = row = 0; row < 8; row++)
46
9.36k
    for (col = 0; col < 8; col++)
47
8.32k
    {
48
8.32k
      if (vbits < bpp)
49
6.24k
      {
50
6.24k
        bitbuf = bitbuf << 16 | (get2() ^ key[i++ & 1]);
51
6.24k
        vbits += 16;
52
6.24k
      }
53
8.32k
      white[row][col] = bitbuf >> (vbits -= bpp) & ~(-1 << bpp);
54
8.32k
    }
55
130
}
56
57
/*
58
   Parse a CIFF file, better known as Canon CRW format.
59
 */
60
void LibRaw::parse_ciff(INT64 offset, int length, int depth)
61
145k
{
62
145k
  int nrecs, c, type, len, wbi = -1;
63
145k
  INT64 save, tboff;
64
145k
  ushort key[] = {0x410, 0x45f3};
65
145k
  ushort CanonColorInfo1_key;
66
145k
  ushort Appendix_A = 0;
67
145k
  INT64 WB_table_offset = 0;
68
145k
  int UseWBfromTable_as_AsShot = 1;
69
145k
  int Got_AsShotWB = 0;
70
145k
  INT64 fsize = ifp->size();
71
145k
  if (metadata_blocks++ > LIBRAW_MAX_METADATA_BLOCKS)
72
102
    throw LIBRAW_EXCEPTION_IO_CORRUPT;
73
74
145k
  fseek(ifp, offset + length - 4, SEEK_SET);
75
145k
  tboff = INT64(get4()) + offset;
76
145k
  fseek(ifp, tboff, SEEK_SET);
77
145k
  nrecs = get2();
78
145k
  if (nrecs < 1)
79
14.1k
    return;
80
130k
  if ((nrecs | depth) > 127)
81
69.3k
    return;
82
83
61.5k
  if (nrecs * 10 + offset > fsize)
84
3.00k
    return;
85
86
2.36M
  while (nrecs--)
87
2.32M
  {
88
2.32M
    type = get2();
89
2.32M
    len = get4();
90
2.32M
    INT64 see = offset + get4();
91
2.32M
    save = ftell(ifp);
92
93
    /* the following tags are not sub-tables
94
     * they contain the value in the "len" field
95
     * for such tags skip the check against filesize
96
     */
97
2.32M
    if ((type != 0x2007) && (type != 0x580b) && (type != 0x501c) &&
98
2.31M
        (type != 0x5029) && (type != 0x5813) && (type != 0x5814) &&
99
2.31M
        (type != 0x5817) && (type != 0x5834) && (type != 0x580e))
100
2.31M
    {
101
102
2.31M
      if (see >= fsize)
103
1.75M
      { // At least one byte
104
1.75M
        fseek(ifp, save, SEEK_SET);
105
1.75M
        continue;
106
1.75M
      }
107
560k
      fseek(ifp, see, SEEK_SET);
108
560k
      if ((((type >> 8) + 8) | 8) == 0x38)
109
123k
      {
110
123k
        parse_ciff(ftell(ifp), len, depth + 1); /* Parse a sub-table */
111
123k
      }
112
560k
    }
113
114
571k
    if (type == 0x3004)
115
20.6k
    {
116
20.6k
      parse_ciff(ftell(ifp), len, depth + 1);
117
20.6k
    }
118
550k
    else if (type == 0x0810)
119
944
    {
120
944
      fread(artist, 64, 1, ifp);
121
944
      artist[63] = 0;
122
944
    }
123
549k
    else if (type == 0x080a)
124
2.25k
    {
125
2.25k
      fread(make, 64, 1, ifp);
126
2.25k
      make[63] = 0;
127
2.25k
    int mlen = (int)strbuflen(make);
128
2.25k
      fseek(ifp, mlen - 63, SEEK_CUR);
129
2.25k
      fread(model, 64, 1, ifp);
130
2.25k
      model[63] = 0;
131
132
547k
    } else if (type == 0x080b) {
133
11.9k
      stmread(imCommon.firmware, (unsigned)len, ifp);
134
11.9k
      if (!strncasecmp(imCommon.firmware, "Firmware Version", 16))
135
40
        memmove(imCommon.firmware, imCommon.firmware + 16, strlen(imCommon.firmware) - 15);
136
11.9k
      trimSpaces(imCommon.firmware);
137
138
535k
    } else if (type == 0x1810)
139
3.10k
    {
140
3.10k
      width = get4();
141
3.10k
      height = get4();
142
3.10k
      pixel_aspect = int_to_float(get4());
143
3.10k
      flip = get4();
144
3.10k
    }
145
532k
    else if (type == 0x1835)
146
283
    { /* Get the decoder table */
147
283
      tiff_compress = get4();
148
283
    }
149
531k
    else if (type == 0x2007)
150
309
    {
151
309
      thumb_offset = see;
152
309
      thumb_length = len;
153
309
    }
154
531k
    else if (type == 0x1818)
155
5.85k
    {
156
5.85k
      shutter = libraw_powf64l(2.0f, -int_to_float((get4(), get4())));
157
5.85k
      ilm.CurAp = aperture = libraw_powf64l(2.0f, int_to_float(get4()) / 2);
158
5.85k
    }
159
525k
    else if (type == 0x102a) // CanonShotInfo
160
11.1k
    {
161
      //      iso_speed = pow (2.0, (get4(),get2())/32.0 - 4) * 50;
162
11.1k
      get2(); // skip one
163
11.1k
      iso_speed =
164
11.1k
          libraw_powf64l(2.0f, (get2() + get2()) / 32.0f - 5.0f) * 100.0f;
165
11.1k
      ilm.CurAp = aperture = _CanonConvertAperture((get2(), get2()));
166
11.1k
      shutter = libraw_powf64l(2.0f, -float((short)get2()) / 32.f);
167
11.1k
      imCanon.wbi = wbi = (get2(), get2());
168
11.1k
      if (wbi >= (int)Canon_wbi2std.size())
169
4.32k
        wbi = 0;
170
11.1k
      fseek(ifp, 32, SEEK_CUR);
171
11.1k
      if (shutter > 1e6)
172
2.35k
        shutter = float(get2()) / 10.f;
173
11.1k
    }
174
514k
    else if (type == 0x102c) // CanonColorInfo2 / Appendix A: Pro90IS, G1, G2, S30, S40
175
8.11k
    {
176
8.11k
      int CanonColorInfo2_type = get2(); // G1 1028, G2 272, Pro90 IS 769, S30 274, S40 273, EOS D30 276
177
8.11k
      if (CanonColorInfo2_type > 512) { /* Pro90 IS, G1 */
178
1.83k
        fseek(ifp, 118, SEEK_CUR);
179
7.33k
        FORC4 cam_mul[BG2RG1_2_RGBG(c)] = get2();
180
1.83k
      }
181
6.27k
      else if (CanonColorInfo2_type != 276) { /* G2, S30, S40 */
182
5.25k
        Appendix_A = 1;
183
5.25k
        WB_table_offset = -14;
184
5.25k
        fseek(ifp, 98, SEEK_CUR);
185
21.0k
        FORC4 cam_mul[GRBG_2_RGBG(c)] = get2();
186
5.25k
        if (cam_mul[0] > 0.001f) Got_AsShotWB = 1;
187
5.25k
      }
188
8.11k
    }
189
506k
    else if (type == 0x10a9) // ColorBalance: Canon D60, 10D, 300D, and clones
190
5.87k
    {
191
5.87k
      int bls = 0;
192
/*
193
      int table[] = {
194
          LIBRAW_WBI_Auto,     // 0
195
          LIBRAW_WBI_Daylight, // 1
196
          LIBRAW_WBI_Cloudy,   // 2
197
          LIBRAW_WBI_Tungsten, // 3
198
          LIBRAW_WBI_FL_W,     // 4
199
          LIBRAW_WBI_Flash,    // 5
200
          LIBRAW_WBI_Custom,   // 6, absent in Canon D60
201
          LIBRAW_WBI_Auto,     // 7, use this if camera is set to b/w JPEG
202
          LIBRAW_WBI_Shade,    // 8
203
          LIBRAW_WBI_Kelvin    // 9, absent in Canon D60
204
      };
205
*/
206
5.87k
      int nWB =
207
5.87k
          ((get2() - 2) / 8) -
208
5.87k
          1; // 2 bytes this, N recs 4*2bytes each, last rec is black level
209
5.87k
      if (nWB)
210
21.3k
        FORC4 icWBC[LIBRAW_WBI_Auto][RGGB_2_RGBG(c)] = get2();
211
5.87k
      if (nWB >= 7)
212
4.77k
        Canon_WBpresets(0, 0);
213
1.10k
      else
214
4.40k
        FORC4 cam_mul[c] = float(icWBC[LIBRAW_WBI_Auto][c]);
215
5.87k
      if (nWB == 7) // mostly Canon EOS D60 + some fw#s for 300D;
216
                    // check for 0x1668000 is unreliable
217
3.05k
      {
218
3.05k
        if ((wbi >= 0) && (wbi < 9) && (wbi != 6))
219
1.12k
        {
220
4.48k
          FORC4 cam_mul[c] = float(icWBC[Canon_wbi2std[wbi]][c]);
221
1.12k
        }
222
1.93k
        else
223
1.93k
        {
224
7.74k
          FORC4 cam_mul[c] = float(icWBC[LIBRAW_WBI_Auto][c]);
225
1.93k
        }
226
3.05k
      }
227
2.81k
      else if (nWB == 9) // Canon 10D, 300D
228
1.23k
      {
229
4.95k
        FORC4 icWBC[LIBRAW_WBI_Custom][RGGB_2_RGBG(c)] = get2();
230
4.95k
        FORC4 icWBC[LIBRAW_WBI_Kelvin][RGGB_2_RGBG(c)] = get2();
231
1.23k
        if ((wbi >= 0) && (wbi < 10))
232
418
        {
233
1.67k
          FORC4 cam_mul[c] = float(icWBC[Canon_wbi2std[wbi]][c]);
234
418
        }
235
821
        else
236
821
        {
237
3.28k
          FORC4 cam_mul[c] = float(icWBC[LIBRAW_WBI_Auto][c]);
238
821
        }
239
1.23k
      }
240
5.87k
      FORC4
241
23.4k
      bls += (imCanon.ChannelBlackLevel[RGGB_2_RGBG(c)] = get2());
242
5.87k
      imCanon.AverageBlackLevel = bls / 4;
243
5.87k
    }
244
500k
    else if (type == 0x102d)
245
5.19k
    {
246
5.19k
      Canon_CameraSettings(len >> 1);
247
5.19k
    }
248
249
495k
    else if (type == 0x10b4) {
250
5.42k
      switch (get2()) {
251
452
      case 1:
252
452
        imCommon.ColorSpace = LIBRAW_COLORSPACE_sRGB;
253
452
        break;
254
678
      case 2:
255
678
        imCommon.ColorSpace = LIBRAW_COLORSPACE_AdobeRGB;
256
678
        break;
257
4.29k
      default:
258
4.29k
        imCommon.ColorSpace = LIBRAW_COLORSPACE_Unknown;
259
4.29k
        break;
260
5.42k
      }
261
262
490k
    } else if (type == 0x580b)
263
1.66k
    {
264
1.66k
      if (strcmp(model, "Canon EOS D30"))
265
1.66k
        sprintf(imgdata.shootinginfo.BodySerial, "%d", len);
266
0
      else
267
0
        sprintf(imgdata.shootinginfo.BodySerial, "%0x-%05d", len >> 16,
268
0
                len & 0xffff);
269
1.66k
    }
270
488k
    else if (type == 0x0032) // CanonColorInfo1
271
19.6k
    {
272
19.6k
      if (len == 768) { // EOS D30
273
274
1.74k
        ushort q;
275
1.74k
        fseek(ifp, 4, SEEK_CUR);
276
12.2k
        for (unsigned linenum = 0; linenum < Canon_D30_linenums_2_StdWBi.size(); linenum++) {
277
10.4k
          if (Canon_D30_linenums_2_StdWBi[linenum] != LIBRAW_WBI_Unknown) {
278
41.9k
            FORC4 {
279
41.9k
              q = get2();
280
41.9k
              icWBC[Canon_D30_linenums_2_StdWBi[linenum]][RGGB_2_RGBG(c)] =
281
41.9k
                (int)(roundf(1024000.0f / (float)MAX(1, q)));
282
41.9k
            }
283
//         if (Canon_wbi2std[imCanon.wbi] == *(Canon_D30_linenums_2_StdWBi + linenum)) {
284
//           FORC4 cam_mul[c] = icWBC[*(Canon_D30_linenums_2_StdWBi + linenum)][c];
285
//           Got_AsShotWB = 1;
286
//           }
287
10.4k
          }
288
10.4k
        }
289
1.74k
        fseek (ifp, 68-int(Canon_D30_linenums_2_StdWBi.size())*8, SEEK_CUR);
290
291
6.99k
        FORC4 {
292
6.99k
          q = get2();
293
6.99k
          cam_mul[RGGB_2_RGBG(c)] = 1024.f / float(MAX(1, q));
294
6.99k
        }
295
1.74k
        if (!wbi)
296
508
          cam_mul[0] = -1; // use my auto white balance
297
298
1.74k
      }
299
17.8k
      else if ((cam_mul[0] <= 0.001f) || // Pro1, G3, G5, G6, S45, S50, S60, S70
300
3.32k
               Appendix_A)               // G2, S30, S40
301
16.0k
      {
302
16.0k
        libraw_static_table_t linenums_2_StdWBi;
303
16.0k
        unsigned AsShotWB_linenum = Canon_wbi2std.size();
304
305
16.0k
        CanonColorInfo1_key = get2();
306
16.0k
        if ((CanonColorInfo1_key == key[0]) && (len == 2048)) { // Pro1
307
1.53k
          linenums_2_StdWBi = Canon_KeyIs0x0410_Len2048_linenums_2_StdWBi;
308
1.53k
          WB_table_offset = 8;
309
310
14.5k
        } else if ((CanonColorInfo1_key == key[0]) && (len == 3072)) { // S60, S70, G6
311
1.21k
          linenums_2_StdWBi = Canon_KeyIs0x0410_Len3072_linenums_2_StdWBi;
312
1.21k
          WB_table_offset = 16;
313
314
13.3k
        } else if (!CanonColorInfo1_key && (len == 2048)) { // G2, S30, S40; S45, S50, G3, G5
315
5.68k
          key[0] = key[1] = 0;
316
5.68k
          linenums_2_StdWBi = Canon_KeyIsZero_Len2048_linenums_2_StdWBi;
317
5.68k
          if (atof(imCommon.firmware) < 1.02f)
318
4.48k
            UseWBfromTable_as_AsShot = 0;
319
320
7.63k
        } else goto next_tag;
321
322
8.43k
        if ((Canon_wbi2std[wbi] == LIBRAW_WBI_Auto)    ||
323
2.25k
            (Canon_wbi2std[wbi] == LIBRAW_WBI_Unknown) ||
324
1.86k
            Got_AsShotWB)
325
7.08k
          UseWBfromTable_as_AsShot = 0;
326
327
8.43k
        if (UseWBfromTable_as_AsShot) {
328
539
          int temp_wbi;
329
539
          if (Canon_wbi2std[wbi] == LIBRAW_WBI_Custom) temp_wbi = LIBRAW_WBI_Daylight;
330
395
          else temp_wbi = wbi;
331
5.13k
          for (AsShotWB_linenum = 0; AsShotWB_linenum < linenums_2_StdWBi.size(); AsShotWB_linenum++) {
332
4.74k
            if (Canon_wbi2std[temp_wbi] == linenums_2_StdWBi[AsShotWB_linenum]) {
333
146
              break;
334
146
            }
335
4.74k
          }
336
539
        }
337
338
8.43k
        fseek (ifp, 78LL+WB_table_offset, SEEK_CUR);
339
84.1k
        for (unsigned linenum = 0; linenum < linenums_2_StdWBi.size(); linenum++) {
340
75.7k
          if (linenums_2_StdWBi[linenum] != LIBRAW_WBI_Unknown) {
341
245k
            FORC4 icWBC[linenums_2_StdWBi[linenum]][GRBG_2_RGBG(c)] = get2() ^ key[c & 1];
342
61.4k
            if (UseWBfromTable_as_AsShot && (AsShotWB_linenum == linenum)) {
343
584
              FORC4 cam_mul[c] = float(icWBC[linenums_2_StdWBi[linenum]][c]);
344
146
              Got_AsShotWB = 1;
345
146
            }
346
61.4k
          } else {
347
14.2k
            fseek(ifp, 8, SEEK_CUR);
348
14.2k
          }
349
75.7k
        }
350
8.43k
        if (!Got_AsShotWB)
351
7.77k
          cam_mul[0] = -1;
352
8.43k
      }
353
19.6k
    }
354
468k
    else if (type == 0x1030 && wbi >= 0 && (0x18040 >> wbi & 1))
355
1.63k
    {
356
1.63k
      ciff_block_1030(); // all that don't have 0x10a9
357
1.63k
    }
358
467k
    else if (type == 0x1031)
359
377
    {
360
377
      raw_width  = imCanon.SensorWidth = (get2(), get2());
361
377
      raw_height = imCanon.SensorHeight = get2();
362
377
      fseek(ifp, 4, SEEK_CUR);
363
377
      imCanon.DefaultCropAbsolute = get_CanonArea();
364
377
      imCanon.LeftOpticalBlack    = get_CanonArea();
365
377
    }
366
466k
    else if (type == 0x501c)
367
2.82k
    {
368
2.82k
      iso_speed = float(len & 0xffff);
369
2.82k
    }
370
463k
    else if (type == 0x5029)
371
1.20k
    {
372
1.20k
      ilm.CurFocal = float( len >> 16);
373
1.20k
      ilm.FocalType = len & 0xffff;
374
1.20k
      if (ilm.FocalType == LIBRAW_FT_ZOOM_LENS)
375
166
      {
376
166
        ilm.FocalUnits = 32;
377
166
        if (ilm.FocalUnits > 1)
378
166
          ilm.CurFocal /= (float)ilm.FocalUnits;
379
166
      }
380
1.20k
      focal_len = ilm.CurFocal;
381
1.20k
    }
382
462k
    else if (type == 0x5813)
383
404
    {
384
404
      flash_used = int_to_float(len);
385
404
    }
386
462k
    else if (type == 0x5814)
387
1.34k
    {
388
1.34k
      canon_ev = int_to_float(len);
389
1.34k
    }
390
460k
    else if (type == 0x5817)
391
408
    {
392
408
      shot_order = len;
393
408
    }
394
460k
    else if (type == 0x5834)
395
344
    {
396
344
      unique_id = ((unsigned long long)len << 32) >> 32;
397
344
      setCanonBodyFeatures(unique_id);
398
344
    }
399
460k
    else if (type == 0x580e)
400
2.22k
    {
401
2.22k
      timestamp = len;
402
2.22k
    }
403
457k
    else if (type == 0x180e)
404
347
    {
405
347
      timestamp = get4();
406
347
    }
407
408
563k
next_tag:;
409
#ifdef LOCALTIME
410
    if ((type | 0x4000) == 0x580e)
411
      timestamp = mktime(gmtime(&timestamp));
412
#endif
413
560k
    fseek(ifp, save, SEEK_SET);
414
560k
  }
415
58.5k
}