Coverage Report

Created: 2025-07-11 06:35

/src/libraw/src/metadata/ciff.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- C++ -*-
2
 * Copyright 2019-2024 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
3.78k
{
36
3.78k
  static const ushort key[] = {0x410, 0x45f3};
37
3.78k
  int i, bpp, row, col, vbits = 0;
38
3.78k
  unsigned long bitbuf = 0;
39
40
3.78k
  if ((get2(), get4()) != 0x80008 || !get4())
41
2.28k
    return;
42
1.50k
  bpp = get2();
43
1.50k
  if (bpp != 10 && bpp != 12)
44
685
    return;
45
7.38k
  for (i = row = 0; row < 8; row++)
46
59.0k
    for (col = 0; col < 8; col++)
47
52.4k
    {
48
52.4k
      if (vbits < bpp)
49
36.1k
      {
50
36.1k
        bitbuf = bitbuf << 16 | (get2() ^ key[i++ & 1]);
51
36.1k
        vbits += 16;
52
36.1k
      }
53
52.4k
      white[row][col] = bitbuf >> (vbits -= bpp) & ~(-1 << bpp);
54
52.4k
    }
55
820
}
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
75.8k
{
62
75.8k
  int nrecs, c, type, len, wbi = -1;
63
75.8k
  INT64 save, tboff;
64
75.8k
  ushort key[] = {0x410, 0x45f3};
65
75.8k
  ushort CanonColorInfo1_key;
66
75.8k
  ushort Appendix_A = 0;
67
75.8k
  INT64 WB_table_offset = 0;
68
75.8k
  int UseWBfromTable_as_AsShot = 1;
69
75.8k
  int Got_AsShotWB = 0;
70
75.8k
  INT64 fsize = ifp->size();
71
75.8k
  if (metadata_blocks++ > LIBRAW_MAX_METADATA_BLOCKS)
72
42
    throw LIBRAW_EXCEPTION_IO_CORRUPT;
73
74
75.8k
  fseek(ifp, offset + length - 4, SEEK_SET);
75
75.8k
  tboff = INT64(get4()) + offset;
76
75.8k
  fseek(ifp, tboff, SEEK_SET);
77
75.8k
  nrecs = get2();
78
75.8k
  if (nrecs < 1)
79
2.09k
    return;
80
73.7k
  if ((nrecs | depth) > 127)
81
39.3k
    return;
82
83
34.3k
  if (nrecs * 10 + offset > fsize)
84
1.15k
    return;
85
86
1.69M
  while (nrecs--)
87
1.66M
  {
88
1.66M
    type = get2();
89
1.66M
    len = get4();
90
1.66M
    INT64 see = offset + get4();
91
1.66M
    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
1.66M
    if ((type != 0x2007) && (type != 0x580b) && (type != 0x501c) &&
98
1.66M
        (type != 0x5029) && (type != 0x5813) && (type != 0x5814) &&
99
1.66M
        (type != 0x5817) && (type != 0x5834) && (type != 0x580e))
100
1.65M
    {
101
102
1.65M
      if (see >= fsize)
103
1.24M
      { // At least one byte
104
1.24M
        fseek(ifp, save, SEEK_SET);
105
1.24M
        continue;
106
1.24M
      }
107
411k
      fseek(ifp, see, SEEK_SET);
108
411k
      if ((((type >> 8) + 8) | 8) == 0x38)
109
62.3k
      {
110
62.3k
        parse_ciff(ftell(ifp), len, depth + 1); /* Parse a sub-table */
111
62.3k
      }
112
411k
    }
113
114
421k
    if (type == 0x3004)
115
12.4k
    {
116
12.4k
      parse_ciff(ftell(ifp), len, depth + 1);
117
12.4k
    }
118
408k
    else if (type == 0x0810)
119
551
    {
120
551
      fread(artist, 64, 1, ifp);
121
551
    }
122
408k
    else if (type == 0x080a)
123
1.83k
    {
124
1.83k
      fread(make, 64, 1, ifp);
125
1.83k
      fseek(ifp, strbuflen(make) - 63, SEEK_CUR);
126
1.83k
      fread(model, 64, 1, ifp);
127
128
406k
    } else if (type == 0x080b) {
129
2.40k
      stmread(imCommon.firmware, (unsigned)len, ifp);
130
2.40k
      if (!strncasecmp(imCommon.firmware, "Firmware Version", 16))
131
34
        memmove(imCommon.firmware, imCommon.firmware + 16, strlen(imCommon.firmware) - 15);
132
2.40k
      trimSpaces(imCommon.firmware);
133
134
403k
    } else if (type == 0x1810)
135
916
    {
136
916
      width = get4();
137
916
      height = get4();
138
916
      pixel_aspect = int_to_float(get4());
139
916
      flip = get4();
140
916
    }
141
402k
    else if (type == 0x1835)
142
310
    { /* Get the decoder table */
143
310
      tiff_compress = get4();
144
310
    }
145
402k
    else if (type == 0x2007)
146
2.76k
    {
147
2.76k
      thumb_offset = see;
148
2.76k
      thumb_length = len;
149
2.76k
    }
150
399k
    else if (type == 0x1818)
151
2.90k
    {
152
2.90k
      shutter = libraw_powf64l(2.0f, -int_to_float((get4(), get4())));
153
2.90k
      ilm.CurAp = aperture = libraw_powf64l(2.0f, int_to_float(get4()) / 2);
154
2.90k
    }
155
396k
    else if (type == 0x102a) // CanonShotInfo
156
18.5k
    {
157
      //      iso_speed = pow (2.0, (get4(),get2())/32.0 - 4) * 50;
158
18.5k
      get2(); // skip one
159
18.5k
      iso_speed =
160
18.5k
          libraw_powf64l(2.0f, (get2() + get2()) / 32.0f - 5.0f) * 100.0f;
161
18.5k
      ilm.CurAp = aperture = _CanonConvertAperture((get2(), get2()));
162
18.5k
      shutter = libraw_powf64l(2.0f, -float((short)get2()) / 32.f);
163
18.5k
      imCanon.wbi = wbi = (get2(), get2());
164
18.5k
      if (wbi >= (int)Canon_wbi2std.size())
165
6.78k
        wbi = 0;
166
18.5k
      fseek(ifp, 32, SEEK_CUR);
167
18.5k
      if (shutter > 1e6)
168
979
        shutter = float(get2()) / 10.f;
169
18.5k
    }
170
378k
    else if (type == 0x102c) // CanonColorInfo2 / Appendix A: Pro90IS, G1, G2, S30, S40
171
5.32k
    {
172
5.32k
      int CanonColorInfo2_type = get2(); // G1 1028, G2 272, Pro90 IS 769, S30 274, S40 273, EOS D30 276
173
5.32k
      if (CanonColorInfo2_type > 512) { /* Pro90 IS, G1 */
174
851
        fseek(ifp, 118, SEEK_CUR);
175
3.40k
        FORC4 cam_mul[BG2RG1_2_RGBG(c)] = get2();
176
851
      }
177
4.47k
      else if (CanonColorInfo2_type != 276) { /* G2, S30, S40 */
178
3.60k
        Appendix_A = 1;
179
3.60k
        WB_table_offset = -14;
180
3.60k
        fseek(ifp, 98, SEEK_CUR);
181
14.4k
        FORC4 cam_mul[GRBG_2_RGBG(c)] = get2();
182
3.60k
        if (cam_mul[0] > 0.001f) Got_AsShotWB = 1;
183
3.60k
      }
184
5.32k
    }
185
373k
    else if (type == 0x10a9) // ColorBalance: Canon D60, 10D, 300D, and clones
186
5.24k
    {
187
5.24k
      int bls = 0;
188
/*
189
      int table[] = {
190
          LIBRAW_WBI_Auto,     // 0
191
          LIBRAW_WBI_Daylight, // 1
192
          LIBRAW_WBI_Cloudy,   // 2
193
          LIBRAW_WBI_Tungsten, // 3
194
          LIBRAW_WBI_FL_W,     // 4
195
          LIBRAW_WBI_Flash,    // 5
196
          LIBRAW_WBI_Custom,   // 6, absent in Canon D60
197
          LIBRAW_WBI_Auto,     // 7, use this if camera is set to b/w JPEG
198
          LIBRAW_WBI_Shade,    // 8
199
          LIBRAW_WBI_Kelvin    // 9, absent in Canon D60
200
      };
201
*/
202
5.24k
      int nWB =
203
5.24k
          ((get2() - 2) / 8) -
204
5.24k
          1; // 2 bytes this, N recs 4*2bytes each, last rec is black level
205
5.24k
      if (nWB)
206
20.2k
        FORC4 icWBC[LIBRAW_WBI_Auto][RGGB_2_RGBG(c)] = get2();
207
5.24k
      if (nWB >= 7)
208
4.64k
        Canon_WBpresets(0, 0);
209
604
      else
210
2.41k
        FORC4 cam_mul[c] = float(icWBC[LIBRAW_WBI_Auto][c]);
211
5.24k
      if (nWB == 7) // mostly Canon EOS D60 + some fw#s for 300D;
212
                    // check for 0x1668000 is unreliable
213
2.35k
      {
214
2.35k
        if ((wbi >= 0) && (wbi < 9) && (wbi != 6))
215
1.12k
        {
216
4.50k
          FORC4 cam_mul[c] = float(icWBC[Canon_wbi2std[wbi]][c]);
217
1.12k
        }
218
1.23k
        else
219
1.23k
        {
220
4.92k
          FORC4 cam_mul[c] = float(icWBC[LIBRAW_WBI_Auto][c]);
221
1.23k
        }
222
2.35k
      }
223
2.88k
      else if (nWB == 9) // Canon 10D, 300D
224
2.11k
      {
225
8.47k
        FORC4 icWBC[LIBRAW_WBI_Custom][RGGB_2_RGBG(c)] = get2();
226
8.47k
        FORC4 icWBC[LIBRAW_WBI_Kelvin][RGGB_2_RGBG(c)] = get2();
227
2.11k
        if ((wbi >= 0) && (wbi < 10))
228
1.14k
        {
229
4.57k
          FORC4 cam_mul[c] = float(icWBC[Canon_wbi2std[wbi]][c]);
230
1.14k
        }
231
975
        else
232
975
        {
233
3.90k
          FORC4 cam_mul[c] = float(icWBC[LIBRAW_WBI_Auto][c]);
234
975
        }
235
2.11k
      }
236
5.24k
      FORC4
237
20.9k
      bls += (imCanon.ChannelBlackLevel[RGGB_2_RGBG(c)] = get2());
238
5.24k
      imCanon.AverageBlackLevel = bls / 4;
239
5.24k
    }
240
367k
    else if (type == 0x102d)
241
2.43k
    {
242
2.43k
      Canon_CameraSettings(len >> 1);
243
2.43k
    }
244
245
365k
    else if (type == 0x10b4) {
246
3.80k
      switch (get2()) {
247
441
      case 1:
248
441
        imCommon.ColorSpace = LIBRAW_COLORSPACE_sRGB;
249
441
        break;
250
685
      case 2:
251
685
        imCommon.ColorSpace = LIBRAW_COLORSPACE_AdobeRGB;
252
685
        break;
253
2.68k
      default:
254
2.68k
        imCommon.ColorSpace = LIBRAW_COLORSPACE_Unknown;
255
2.68k
        break;
256
3.80k
      }
257
258
361k
    } else if (type == 0x580b)
259
755
    {
260
755
      if (strcmp(model, "Canon EOS D30"))
261
755
        sprintf(imgdata.shootinginfo.BodySerial, "%d", len);
262
0
      else
263
0
        sprintf(imgdata.shootinginfo.BodySerial, "%0x-%05d", len >> 16,
264
0
                len & 0xffff);
265
755
    }
266
360k
    else if (type == 0x0032) // CanonColorInfo1
267
12.9k
    {
268
12.9k
      if (len == 768) { // EOS D30
269
270
1.32k
        ushort q;
271
1.32k
        fseek(ifp, 4, SEEK_CUR);
272
9.24k
        for (unsigned linenum = 0; linenum < Canon_D30_linenums_2_StdWBi.size(); linenum++) {
273
7.92k
          if (Canon_D30_linenums_2_StdWBi[linenum] != LIBRAW_WBI_Unknown) {
274
31.6k
            FORC4 {
275
31.6k
              q = get2();
276
31.6k
              icWBC[Canon_D30_linenums_2_StdWBi[linenum]][RGGB_2_RGBG(c)] =
277
31.6k
                (int)(roundf(1024000.0f / (float)MAX(1, q)));
278
31.6k
            }
279
//         if (Canon_wbi2std[imCanon.wbi] == *(Canon_D30_linenums_2_StdWBi + linenum)) {
280
//           FORC4 cam_mul[c] = icWBC[*(Canon_D30_linenums_2_StdWBi + linenum)][c];
281
//           Got_AsShotWB = 1;
282
//           }
283
7.92k
          }
284
7.92k
        }
285
1.32k
        fseek (ifp, 68-int(Canon_D30_linenums_2_StdWBi.size())*8, SEEK_CUR);
286
287
5.28k
        FORC4 {
288
5.28k
          q = get2();
289
5.28k
          cam_mul[RGGB_2_RGBG(c)] = 1024.f / float(MAX(1, q));
290
5.28k
        }
291
1.32k
        if (!wbi)
292
754
          cam_mul[0] = -1; // use my auto white balance
293
294
1.32k
      }
295
11.6k
      else if ((cam_mul[0] <= 0.001f) || // Pro1, G3, G5, G6, S45, S50, S60, S70
296
11.6k
               Appendix_A)               // G2, S30, S40
297
10.2k
      {
298
10.2k
        libraw_static_table_t linenums_2_StdWBi;
299
10.2k
        unsigned AsShotWB_linenum = Canon_wbi2std.size();
300
301
10.2k
        CanonColorInfo1_key = get2();
302
10.2k
        if ((CanonColorInfo1_key == key[0]) && (len == 2048)) { // Pro1
303
1.01k
          linenums_2_StdWBi = Canon_KeyIs0x0410_Len2048_linenums_2_StdWBi;
304
1.01k
          WB_table_offset = 8;
305
306
9.19k
        } else if ((CanonColorInfo1_key == key[0]) && (len == 3072)) { // S60, S70, G6
307
2.39k
          linenums_2_StdWBi = Canon_KeyIs0x0410_Len3072_linenums_2_StdWBi;
308
2.39k
          WB_table_offset = 16;
309
310
6.79k
        } else if (!CanonColorInfo1_key && (len == 2048)) { // G2, S30, S40; S45, S50, G3, G5
311
2.51k
          key[0] = key[1] = 0;
312
2.51k
          linenums_2_StdWBi = Canon_KeyIsZero_Len2048_linenums_2_StdWBi;
313
2.51k
          if (atof(imCommon.firmware) < 1.02f)
314
2.51k
            UseWBfromTable_as_AsShot = 0;
315
316
4.27k
        } else goto next_tag;
317
318
5.92k
        if ((Canon_wbi2std[wbi] == LIBRAW_WBI_Auto)    ||
319
5.92k
            (Canon_wbi2std[wbi] == LIBRAW_WBI_Unknown) ||
320
5.92k
            Got_AsShotWB)
321
3.61k
          UseWBfromTable_as_AsShot = 0;
322
323
5.92k
        if (UseWBfromTable_as_AsShot) {
324
1.30k
          int temp_wbi;
325
1.30k
          if (Canon_wbi2std[wbi] == LIBRAW_WBI_Custom) temp_wbi = LIBRAW_WBI_Daylight;
326
908
          else temp_wbi = wbi;
327
8.69k
          for (AsShotWB_linenum = 0; AsShotWB_linenum < linenums_2_StdWBi.size(); AsShotWB_linenum++) {
328
8.17k
            if (Canon_wbi2std[temp_wbi] == linenums_2_StdWBi[AsShotWB_linenum]) {
329
782
              break;
330
782
            }
331
8.17k
          }
332
1.30k
        }
333
334
5.92k
        fseek (ifp, 78LL+WB_table_offset, SEEK_CUR);
335
63.5k
        for (unsigned linenum = 0; linenum < linenums_2_StdWBi.size(); linenum++) {
336
57.6k
          if (linenums_2_StdWBi[linenum] != LIBRAW_WBI_Unknown) {
337
185k
            FORC4 icWBC[linenums_2_StdWBi[linenum]][GRBG_2_RGBG(c)] = get2() ^ key[c & 1];
338
46.2k
            if (UseWBfromTable_as_AsShot && (AsShotWB_linenum == linenum)) {
339
3.12k
              FORC4 cam_mul[c] = float(icWBC[linenums_2_StdWBi[linenum]][c]);
340
782
              Got_AsShotWB = 1;
341
782
            }
342
46.2k
          } else {
343
11.3k
            fseek(ifp, 8, SEEK_CUR);
344
11.3k
          }
345
57.6k
        }
346
5.92k
        if (!Got_AsShotWB)
347
4.21k
          cam_mul[0] = -1;
348
5.92k
      }
349
12.9k
    }
350
347k
    else if (type == 0x1030 && wbi >= 0 && (0x18040 >> wbi & 1))
351
3.78k
    {
352
3.78k
      ciff_block_1030(); // all that don't have 0x10a9
353
3.78k
    }
354
344k
    else if (type == 0x1031)
355
1.69k
    {
356
1.69k
      raw_width  = imCanon.SensorWidth = (get2(), get2());
357
1.69k
      raw_height = imCanon.SensorHeight = get2();
358
1.69k
      fseek(ifp, 4, SEEK_CUR);
359
1.69k
      imCanon.DefaultCropAbsolute = get_CanonArea();
360
1.69k
      imCanon.LeftOpticalBlack    = get_CanonArea();
361
1.69k
    }
362
342k
    else if (type == 0x501c)
363
457
    {
364
457
      iso_speed = float(len & 0xffff);
365
457
    }
366
341k
    else if (type == 0x5029)
367
1.20k
    {
368
1.20k
      ilm.CurFocal = float( len >> 16);
369
1.20k
      ilm.FocalType = len & 0xffff;
370
1.20k
      if (ilm.FocalType == LIBRAW_FT_ZOOM_LENS)
371
435
      {
372
435
        ilm.FocalUnits = 32;
373
435
        if (ilm.FocalUnits > 1)
374
435
          ilm.CurFocal /= (float)ilm.FocalUnits;
375
435
      }
376
1.20k
      focal_len = ilm.CurFocal;
377
1.20k
    }
378
340k
    else if (type == 0x5813)
379
702
    {
380
702
      flash_used = int_to_float(len);
381
702
    }
382
340k
    else if (type == 0x5814)
383
880
    {
384
880
      canon_ev = int_to_float(len);
385
880
    }
386
339k
    else if (type == 0x5817)
387
765
    {
388
765
      shot_order = len;
389
765
    }
390
338k
    else if (type == 0x5834)
391
1.01k
    {
392
1.01k
      unique_id = ((unsigned long long)len << 32) >> 32;
393
1.01k
      setCanonBodyFeatures(unique_id);
394
1.01k
    }
395
337k
    else if (type == 0x580e)
396
1.52k
    {
397
1.52k
      timestamp = len;
398
1.52k
    }
399
335k
    else if (type == 0x180e)
400
686
    {
401
686
      timestamp = get4();
402
686
    }
403
404
416k
next_tag:;
405
#ifdef LOCALTIME
406
    if ((type | 0x4000) == 0x580e)
407
      timestamp = mktime(gmtime(&timestamp));
408
#endif
409
416k
    fseek(ifp, save, SEEK_SET);
410
416k
  }
411
33.2k
}