Coverage Report

Created: 2026-05-12 06:30

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
15.1k
{
36
15.1k
  static const ushort key[] = {0x410, 0x45f3};
37
15.1k
  int i, bpp, row, col, vbits = 0;
38
15.1k
  unsigned long bitbuf = 0;
39
40
15.1k
  if ((get2(), get4()) != 0x80008 || !get4())
41
8.00k
    return;
42
7.12k
  bpp = get2();
43
7.12k
  if (bpp != 10 && bpp != 12)
44
1.83k
    return;
45
47.5k
  for (i = row = 0; row < 8; row++)
46
380k
    for (col = 0; col < 8; col++)
47
338k
    {
48
338k
      if (vbits < bpp)
49
230k
      {
50
230k
        bitbuf = bitbuf << 16 | (get2() ^ key[i++ & 1]);
51
230k
        vbits += 16;
52
230k
      }
53
338k
      white[row][col] = bitbuf >> (vbits -= bpp) & ~(-1 << bpp);
54
338k
    }
55
5.28k
}
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
307k
{
62
307k
  int nrecs, c, type, len, wbi = -1;
63
307k
  INT64 save, tboff;
64
307k
  ushort key[] = {0x410, 0x45f3};
65
307k
  ushort CanonColorInfo1_key;
66
307k
  ushort Appendix_A = 0;
67
307k
  INT64 WB_table_offset = 0;
68
307k
  int UseWBfromTable_as_AsShot = 1;
69
307k
  int Got_AsShotWB = 0;
70
307k
  INT64 fsize = ifp->size();
71
307k
  if (metadata_blocks++ > LIBRAW_MAX_METADATA_BLOCKS)
72
194
    throw LIBRAW_EXCEPTION_IO_CORRUPT;
73
74
307k
  fseek(ifp, offset + length - 4, SEEK_SET);
75
307k
  tboff = INT64(get4()) + offset;
76
307k
  fseek(ifp, tboff, SEEK_SET);
77
307k
  nrecs = get2();
78
307k
  if (nrecs < 1)
79
12.5k
    return;
80
294k
  if ((nrecs | depth) > 127)
81
151k
    return;
82
83
143k
  if (nrecs * 10 + offset > fsize)
84
5.61k
    return;
85
86
6.28M
  while (nrecs--)
87
6.16M
  {
88
6.16M
    type = get2();
89
6.16M
    len = get4();
90
6.16M
    INT64 see = offset + get4();
91
6.16M
    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
6.16M
    if ((type != 0x2007) && (type != 0x580b) && (type != 0x501c) &&
98
6.15M
        (type != 0x5029) && (type != 0x5813) && (type != 0x5814) &&
99
6.14M
        (type != 0x5817) && (type != 0x5834) && (type != 0x580e))
100
6.13M
    {
101
102
6.13M
      if (see >= fsize)
103
4.78M
      { // At least one byte
104
4.78M
        fseek(ifp, save, SEEK_SET);
105
4.78M
        continue;
106
4.78M
      }
107
1.35M
      fseek(ifp, see, SEEK_SET);
108
1.35M
      if ((((type >> 8) + 8) | 8) == 0x38)
109
269k
      {
110
269k
        parse_ciff(ftell(ifp), len, depth + 1); /* Parse a sub-table */
111
269k
      }
112
1.35M
    }
113
114
1.38M
    if (type == 0x3004)
115
35.7k
    {
116
35.7k
      parse_ciff(ftell(ifp), len, depth + 1);
117
35.7k
    }
118
1.35M
    else if (type == 0x0810)
119
3.51k
    {
120
3.51k
      fread(artist, 64, 1, ifp);
121
3.51k
      artist[63] = 0;
122
3.51k
    }
123
1.34M
    else if (type == 0x080a)
124
2.47k
    {
125
2.47k
      fread(make, 64, 1, ifp);
126
2.47k
      make[63] = 0;
127
2.47k
      fseek(ifp, strbuflen(make) - 63, SEEK_CUR);
128
2.47k
      fread(model, 64, 1, ifp);
129
2.47k
      model[63] = 0;
130
131
1.34M
    } else if (type == 0x080b) {
132
11.9k
      stmread(imCommon.firmware, (unsigned)len, ifp);
133
11.9k
      if (!strncasecmp(imCommon.firmware, "Firmware Version", 16))
134
1.76k
        memmove(imCommon.firmware, imCommon.firmware + 16, strlen(imCommon.firmware) - 15);
135
11.9k
      trimSpaces(imCommon.firmware);
136
137
1.33M
    } else if (type == 0x1810)
138
4.47k
    {
139
4.47k
      width = get4();
140
4.47k
      height = get4();
141
4.47k
      pixel_aspect = int_to_float(get4());
142
4.47k
      flip = get4();
143
4.47k
    }
144
1.32M
    else if (type == 0x1835)
145
1.80k
    { /* Get the decoder table */
146
1.80k
      tiff_compress = get4();
147
1.80k
    }
148
1.32M
    else if (type == 0x2007)
149
1.89k
    {
150
1.89k
      thumb_offset = see;
151
1.89k
      thumb_length = len;
152
1.89k
    }
153
1.32M
    else if (type == 0x1818)
154
10.4k
    {
155
10.4k
      shutter = libraw_powf64l(2.0f, -int_to_float((get4(), get4())));
156
10.4k
      ilm.CurAp = aperture = libraw_powf64l(2.0f, int_to_float(get4()) / 2);
157
10.4k
    }
158
1.31M
    else if (type == 0x102a) // CanonShotInfo
159
62.9k
    {
160
      //      iso_speed = pow (2.0, (get4(),get2())/32.0 - 4) * 50;
161
62.9k
      get2(); // skip one
162
62.9k
      iso_speed =
163
62.9k
          libraw_powf64l(2.0f, (get2() + get2()) / 32.0f - 5.0f) * 100.0f;
164
62.9k
      ilm.CurAp = aperture = _CanonConvertAperture((get2(), get2()));
165
62.9k
      shutter = libraw_powf64l(2.0f, -float((short)get2()) / 32.f);
166
62.9k
      imCanon.wbi = wbi = (get2(), get2());
167
62.9k
      if (wbi >= (int)Canon_wbi2std.size())
168
21.9k
        wbi = 0;
169
62.9k
      fseek(ifp, 32, SEEK_CUR);
170
62.9k
      if (shutter > 1e6)
171
2.20k
        shutter = float(get2()) / 10.f;
172
62.9k
    }
173
1.25M
    else if (type == 0x102c) // CanonColorInfo2 / Appendix A: Pro90IS, G1, G2, S30, S40
174
17.1k
    {
175
17.1k
      int CanonColorInfo2_type = get2(); // G1 1028, G2 272, Pro90 IS 769, S30 274, S40 273, EOS D30 276
176
17.1k
      if (CanonColorInfo2_type > 512) { /* Pro90 IS, G1 */
177
5.39k
        fseek(ifp, 118, SEEK_CUR);
178
21.5k
        FORC4 cam_mul[BG2RG1_2_RGBG(c)] = get2();
179
5.39k
      }
180
11.7k
      else if (CanonColorInfo2_type != 276) { /* G2, S30, S40 */
181
9.45k
        Appendix_A = 1;
182
9.45k
        WB_table_offset = -14;
183
9.45k
        fseek(ifp, 98, SEEK_CUR);
184
37.8k
        FORC4 cam_mul[GRBG_2_RGBG(c)] = get2();
185
9.45k
        if (cam_mul[0] > 0.001f) Got_AsShotWB = 1;
186
9.45k
      }
187
17.1k
    }
188
1.23M
    else if (type == 0x10a9) // ColorBalance: Canon D60, 10D, 300D, and clones
189
24.5k
    {
190
24.5k
      int bls = 0;
191
/*
192
      int table[] = {
193
          LIBRAW_WBI_Auto,     // 0
194
          LIBRAW_WBI_Daylight, // 1
195
          LIBRAW_WBI_Cloudy,   // 2
196
          LIBRAW_WBI_Tungsten, // 3
197
          LIBRAW_WBI_FL_W,     // 4
198
          LIBRAW_WBI_Flash,    // 5
199
          LIBRAW_WBI_Custom,   // 6, absent in Canon D60
200
          LIBRAW_WBI_Auto,     // 7, use this if camera is set to b/w JPEG
201
          LIBRAW_WBI_Shade,    // 8
202
          LIBRAW_WBI_Kelvin    // 9, absent in Canon D60
203
      };
204
*/
205
24.5k
      int nWB =
206
24.5k
          ((get2() - 2) / 8) -
207
24.5k
          1; // 2 bytes this, N recs 4*2bytes each, last rec is black level
208
24.5k
      if (nWB)
209
85.5k
        FORC4 icWBC[LIBRAW_WBI_Auto][RGGB_2_RGBG(c)] = get2();
210
24.5k
      if (nWB >= 7)
211
18.5k
        Canon_WBpresets(0, 0);
212
5.94k
      else
213
23.7k
        FORC4 cam_mul[c] = float(icWBC[LIBRAW_WBI_Auto][c]);
214
24.5k
      if (nWB == 7) // mostly Canon EOS D60 + some fw#s for 300D;
215
                    // check for 0x1668000 is unreliable
216
11.5k
      {
217
11.5k
        if ((wbi >= 0) && (wbi < 9) && (wbi != 6))
218
2.83k
        {
219
11.3k
          FORC4 cam_mul[c] = float(icWBC[Canon_wbi2std[wbi]][c]);
220
2.83k
        }
221
8.74k
        else
222
8.74k
        {
223
34.9k
          FORC4 cam_mul[c] = float(icWBC[LIBRAW_WBI_Auto][c]);
224
8.74k
        }
225
11.5k
      }
226
12.9k
      else if (nWB == 9) // Canon 10D, 300D
227
6.41k
      {
228
25.6k
        FORC4 icWBC[LIBRAW_WBI_Custom][RGGB_2_RGBG(c)] = get2();
229
25.6k
        FORC4 icWBC[LIBRAW_WBI_Kelvin][RGGB_2_RGBG(c)] = get2();
230
6.41k
        if ((wbi >= 0) && (wbi < 10))
231
3.65k
        {
232
14.6k
          FORC4 cam_mul[c] = float(icWBC[Canon_wbi2std[wbi]][c]);
233
3.65k
        }
234
2.75k
        else
235
2.75k
        {
236
11.0k
          FORC4 cam_mul[c] = float(icWBC[LIBRAW_WBI_Auto][c]);
237
2.75k
        }
238
6.41k
      }
239
24.5k
      FORC4
240
98.1k
      bls += (imCanon.ChannelBlackLevel[RGGB_2_RGBG(c)] = get2());
241
24.5k
      imCanon.AverageBlackLevel = bls / 4;
242
24.5k
    }
243
1.21M
    else if (type == 0x102d)
244
8.75k
    {
245
8.75k
      Canon_CameraSettings(len >> 1);
246
8.75k
    }
247
248
1.20M
    else if (type == 0x10b4) {
249
10.9k
      switch (get2()) {
250
1.88k
      case 1:
251
1.88k
        imCommon.ColorSpace = LIBRAW_COLORSPACE_sRGB;
252
1.88k
        break;
253
2.99k
      case 2:
254
2.99k
        imCommon.ColorSpace = LIBRAW_COLORSPACE_AdobeRGB;
255
2.99k
        break;
256
6.08k
      default:
257
6.08k
        imCommon.ColorSpace = LIBRAW_COLORSPACE_Unknown;
258
6.08k
        break;
259
10.9k
      }
260
261
1.19M
    } else if (type == 0x580b)
262
3.24k
    {
263
3.24k
      if (strcmp(model, "Canon EOS D30"))
264
3.24k
        sprintf(imgdata.shootinginfo.BodySerial, "%d", len);
265
0
      else
266
0
        sprintf(imgdata.shootinginfo.BodySerial, "%0x-%05d", len >> 16,
267
0
                len & 0xffff);
268
3.24k
    }
269
1.18M
    else if (type == 0x0032) // CanonColorInfo1
270
55.7k
    {
271
55.7k
      if (len == 768) { // EOS D30
272
273
12.5k
        ushort q;
274
12.5k
        fseek(ifp, 4, SEEK_CUR);
275
87.6k
        for (unsigned linenum = 0; linenum < Canon_D30_linenums_2_StdWBi.size(); linenum++) {
276
75.1k
          if (Canon_D30_linenums_2_StdWBi[linenum] != LIBRAW_WBI_Unknown) {
277
300k
            FORC4 {
278
300k
              q = get2();
279
300k
              icWBC[Canon_D30_linenums_2_StdWBi[linenum]][RGGB_2_RGBG(c)] =
280
300k
                (int)(roundf(1024000.0f / (float)MAX(1, q)));
281
300k
            }
282
//         if (Canon_wbi2std[imCanon.wbi] == *(Canon_D30_linenums_2_StdWBi + linenum)) {
283
//           FORC4 cam_mul[c] = icWBC[*(Canon_D30_linenums_2_StdWBi + linenum)][c];
284
//           Got_AsShotWB = 1;
285
//           }
286
75.1k
          }
287
75.1k
        }
288
12.5k
        fseek (ifp, 68-int(Canon_D30_linenums_2_StdWBi.size())*8, SEEK_CUR);
289
290
50.1k
        FORC4 {
291
50.1k
          q = get2();
292
50.1k
          cam_mul[RGGB_2_RGBG(c)] = 1024.f / float(MAX(1, q));
293
50.1k
        }
294
12.5k
        if (!wbi)
295
8.91k
          cam_mul[0] = -1; // use my auto white balance
296
297
12.5k
      }
298
43.2k
      else if ((cam_mul[0] <= 0.001f) || // Pro1, G3, G5, G6, S45, S50, S60, S70
299
12.4k
               Appendix_A)               // G2, S30, S40
300
35.5k
      {
301
35.5k
        libraw_static_table_t linenums_2_StdWBi;
302
35.5k
        unsigned AsShotWB_linenum = Canon_wbi2std.size();
303
304
35.5k
        CanonColorInfo1_key = get2();
305
35.5k
        if ((CanonColorInfo1_key == key[0]) && (len == 2048)) { // Pro1
306
6.61k
          linenums_2_StdWBi = Canon_KeyIs0x0410_Len2048_linenums_2_StdWBi;
307
6.61k
          WB_table_offset = 8;
308
309
28.8k
        } else if ((CanonColorInfo1_key == key[0]) && (len == 3072)) { // S60, S70, G6
310
5.74k
          linenums_2_StdWBi = Canon_KeyIs0x0410_Len3072_linenums_2_StdWBi;
311
5.74k
          WB_table_offset = 16;
312
313
23.1k
        } else if (!CanonColorInfo1_key && (len == 2048)) { // G2, S30, S40; S45, S50, G3, G5
314
7.63k
          key[0] = key[1] = 0;
315
7.63k
          linenums_2_StdWBi = Canon_KeyIsZero_Len2048_linenums_2_StdWBi;
316
7.63k
          if (atof(imCommon.firmware) < 1.02f)
317
7.63k
            UseWBfromTable_as_AsShot = 0;
318
319
15.5k
        } else goto next_tag;
320
321
19.9k
        if ((Canon_wbi2std[wbi] == LIBRAW_WBI_Auto)    ||
322
10.4k
            (Canon_wbi2std[wbi] == LIBRAW_WBI_Unknown) ||
323
8.90k
            Got_AsShotWB)
324
12.3k
          UseWBfromTable_as_AsShot = 0;
325
326
19.9k
        if (UseWBfromTable_as_AsShot) {
327
4.41k
          int temp_wbi;
328
4.41k
          if (Canon_wbi2std[wbi] == LIBRAW_WBI_Custom) temp_wbi = LIBRAW_WBI_Daylight;
329
3.50k
          else temp_wbi = wbi;
330
40.7k
          for (AsShotWB_linenum = 0; AsShotWB_linenum < linenums_2_StdWBi.size(); AsShotWB_linenum++) {
331
37.6k
            if (Canon_wbi2std[temp_wbi] == linenums_2_StdWBi[AsShotWB_linenum]) {
332
1.33k
              break;
333
1.33k
            }
334
37.6k
          }
335
4.41k
        }
336
337
19.9k
        fseek (ifp, 78LL+WB_table_offset, SEEK_CUR);
338
217k
        for (unsigned linenum = 0; linenum < linenums_2_StdWBi.size(); linenum++) {
339
197k
          if (linenums_2_StdWBi[linenum] != LIBRAW_WBI_Unknown) {
340
605k
            FORC4 icWBC[linenums_2_StdWBi[linenum]][GRBG_2_RGBG(c)] = get2() ^ key[c & 1];
341
151k
            if (UseWBfromTable_as_AsShot && (AsShotWB_linenum == linenum)) {
342
5.34k
              FORC4 cam_mul[c] = float(icWBC[linenums_2_StdWBi[linenum]][c]);
343
1.33k
              Got_AsShotWB = 1;
344
1.33k
            }
345
151k
          } else {
346
45.5k
            fseek(ifp, 8, SEEK_CUR);
347
45.5k
          }
348
197k
        }
349
19.9k
        if (!Got_AsShotWB)
350
15.6k
          cam_mul[0] = -1;
351
19.9k
      }
352
55.7k
    }
353
1.13M
    else if (type == 0x1030 && wbi >= 0 && (0x18040 >> wbi & 1))
354
15.1k
    {
355
15.1k
      ciff_block_1030(); // all that don't have 0x10a9
356
15.1k
    }
357
1.11M
    else if (type == 0x1031)
358
4.33k
    {
359
4.33k
      raw_width  = imCanon.SensorWidth = (get2(), get2());
360
4.33k
      raw_height = imCanon.SensorHeight = get2();
361
4.33k
      fseek(ifp, 4, SEEK_CUR);
362
4.33k
      imCanon.DefaultCropAbsolute = get_CanonArea();
363
4.33k
      imCanon.LeftOpticalBlack    = get_CanonArea();
364
4.33k
    }
365
1.11M
    else if (type == 0x501c)
366
3.31k
    {
367
3.31k
      iso_speed = float(len & 0xffff);
368
3.31k
    }
369
1.10M
    else if (type == 0x5029)
370
10.3k
    {
371
10.3k
      ilm.CurFocal = float( len >> 16);
372
10.3k
      ilm.FocalType = len & 0xffff;
373
10.3k
      if (ilm.FocalType == LIBRAW_FT_ZOOM_LENS)
374
3.40k
      {
375
3.40k
        ilm.FocalUnits = 32;
376
3.40k
        if (ilm.FocalUnits > 1)
377
3.40k
          ilm.CurFocal /= (float)ilm.FocalUnits;
378
3.40k
      }
379
10.3k
      focal_len = ilm.CurFocal;
380
10.3k
    }
381
1.09M
    else if (type == 0x5813)
382
5.04k
    {
383
5.04k
      flash_used = int_to_float(len);
384
5.04k
    }
385
1.09M
    else if (type == 0x5814)
386
3.79k
    {
387
3.79k
      canon_ev = int_to_float(len);
388
3.79k
    }
389
1.09M
    else if (type == 0x5817)
390
2.41k
    {
391
2.41k
      shot_order = len;
392
2.41k
    }
393
1.08M
    else if (type == 0x5834)
394
5.98k
    {
395
5.98k
      unique_id = ((unsigned long long)len << 32) >> 32;
396
5.98k
      setCanonBodyFeatures(unique_id);
397
5.98k
    }
398
1.08M
    else if (type == 0x580e)
399
1.66k
    {
400
1.66k
      timestamp = len;
401
1.66k
    }
402
1.08M
    else if (type == 0x180e)
403
888
    {
404
888
      timestamp = get4();
405
888
    }
406
407
1.37M
next_tag:;
408
#ifdef LOCALTIME
409
    if ((type | 0x4000) == 0x580e)
410
      timestamp = mktime(gmtime(&timestamp));
411
#endif
412
1.36M
    fseek(ifp, save, SEEK_SET);
413
1.36M
  }
414
138k
}