Coverage Report

Created: 2025-08-12 07:37

/src/libraw/src/metadata/exif_gps.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
#include "../../internal/libraw_cameraids.h"
21
22
void LibRaw::parse_exif_interop(INT64 base)
23
1.50k
{
24
1.50k
  unsigned entries, tag, type, len;
25
1.50k
  INT64 save;
26
1.50k
  char value[4] = { 0,0,0,0 };
27
1.50k
  entries = get2();
28
1.50k
  INT64 fsize = ifp->size();
29
196k
  while (entries--)
30
194k
  {
31
194k
    tiff_get(base, &tag, &type, &len, &save);
32
33
194k
    INT64 savepos = ftell(ifp);
34
194k
    if (len > 8 && savepos + len > fsize * 2)
35
154k
    {
36
154k
      fseek(ifp, save, SEEK_SET); // Recover tiff-read position!!
37
154k
      continue;
38
154k
    }
39
40.7k
        if (callbacks.exif_cb)
40
0
        {
41
0
            callbacks.exif_cb(callbacks.exifparser_data, tag | 0x40000, type, len, order, ifp, base);
42
0
            fseek(ifp, savepos, SEEK_SET);
43
0
        }
44
45
40.7k
    switch (tag)
46
40.7k
    {
47
2.39k
    case 0x0001: // InteropIndex
48
2.39k
      fread(value, 1, MIN(4, len), ifp);
49
2.39k
      if (strncmp(value, "R98", 3) == 0 &&
50
        // Canon bug, when [Canon].ColorSpace = AdobeRGB,
51
        // but [ExifIFD].ColorSpace = Uncalibrated and
52
        // [InteropIFD].InteropIndex = "R98"
53
2.39k
        imgdata.color.ExifColorSpace == LIBRAW_COLORSPACE_Unknown)
54
10
        imgdata.color.ExifColorSpace = LIBRAW_COLORSPACE_sRGB;
55
2.38k
      else if (strncmp(value, "R03", 3) == 0)
56
116
        imgdata.color.ExifColorSpace = LIBRAW_COLORSPACE_AdobeRGB;
57
2.39k
      break;
58
40.7k
    }
59
40.6k
    fseek(ifp, save, SEEK_SET);
60
40.6k
  }
61
1.50k
}
62
63
void LibRaw::parse_exif(INT64 base)
64
167k
{
65
167k
  unsigned entries, tag, type, len, c;
66
167k
  double expo, ape;
67
167k
  INT64 save;
68
69
167k
  unsigned kodak = !strncmp(make, "EASTMAN", 7) && tiff_nifds < 3;
70
71
167k
  if (!libraw_internal_data.unpacker_data.exif_subdir_offset)
72
18.0k
  {
73
18.0k
    libraw_internal_data.unpacker_data.exif_offset = base;
74
18.0k
    libraw_internal_data.unpacker_data.exif_subdir_offset = ftell(ifp);
75
18.0k
  }
76
77
167k
  entries = get2();
78
167k
  if (!strncmp(make, "Hasselblad", 10) && (tiff_nifds > 3) && (entries > 512))
79
860
    return;
80
166k
  INT64 fsize = ifp->size();
81
20.7M
  while (entries--)
82
20.5M
  {
83
20.5M
    tiff_get(base, &tag, &type, &len, &save);
84
85
20.5M
    INT64 savepos = ftell(ifp);
86
20.5M
    if (len > 8 && savepos + INT64(len) > fsize * 2LL)
87
16.4M
    {
88
16.4M
      fseek(ifp, save, SEEK_SET); // Recover tiff-read position!!
89
16.4M
      continue;
90
16.4M
    }
91
4.14M
    if (callbacks.exif_cb)
92
0
    {
93
0
      callbacks.exif_cb(callbacks.exifparser_data, tag, type, len, order, ifp,
94
0
                        base);
95
0
      fseek(ifp, savepos, SEEK_SET);
96
0
    }
97
98
4.14M
    switch (tag)
99
4.14M
    {
100
1.50k
  case 0xA005: // Interoperability IFD
101
1.50k
    fseek(ifp, get4() + base, SEEK_SET);
102
1.50k
    parse_exif_interop(base);
103
1.50k
    break;
104
1.13k
  case 0xA001: // ExifIFD.ColorSpace
105
1.13k
    c = get2();
106
1.13k
    if (c == 1 && imgdata.color.ExifColorSpace == LIBRAW_COLORSPACE_Unknown)
107
38
      imgdata.color.ExifColorSpace = LIBRAW_COLORSPACE_sRGB;
108
1.09k
    else if (c == 2)
109
165
      imgdata.color.ExifColorSpace = LIBRAW_COLORSPACE_AdobeRGB;
110
1.13k
    break;
111
2.38k
    case 0x9400:
112
2.38k
      imCommon.exifAmbientTemperature = getrealf(type);
113
2.38k
      if ((imCommon.CameraTemperature > -273.15f) &&
114
2.38k
          ((OlyID == OlyID_TG_5) ||
115
599
           (OlyID == OlyID_TG_6))
116
2.38k
      )
117
0
        imCommon.CameraTemperature += imCommon.exifAmbientTemperature;
118
2.38k
      break;
119
615
    case 0x9401:
120
615
      imCommon.exifHumidity = getrealf(type);
121
615
      break;
122
1.78k
    case 0x9402:
123
1.78k
      imCommon.exifPressure = getrealf(type);
124
1.78k
      break;
125
480
    case 0x9403:
126
480
      imCommon.exifWaterDepth = getrealf(type);
127
480
      break;
128
339
    case 0x9404:
129
339
      imCommon.exifAcceleration = getrealf(type);
130
339
      break;
131
940
    case 0x9405:
132
940
      imCommon.exifCameraElevationAngle = getrealf(type);
133
940
      break;
134
135
407
    case 0xa405: // FocalLengthIn35mmFormat
136
407
      imgdata.lens.FocalLengthIn35mmFormat = get2();
137
407
      break;
138
3.05k
    case 0xa431: // BodySerialNumber
139
3.05k
      stmread(imgdata.shootinginfo.BodySerial, len, ifp);
140
3.05k
      break;
141
1.18k
    case 0xa432: // LensInfo, 42034dec, Lens Specification per EXIF standard
142
1.18k
      imgdata.lens.MinFocal = getrealf(type);
143
1.18k
      imgdata.lens.MaxFocal = getrealf(type);
144
1.18k
      imgdata.lens.MaxAp4MinFocal = getrealf(type);
145
1.18k
      imgdata.lens.MaxAp4MaxFocal = getrealf(type);
146
1.18k
      break;
147
1.90k
    case 0xa435: // LensSerialNumber
148
1.90k
      stmread(imgdata.lens.LensSerial, len, ifp);
149
1.90k
      if (!strncmp(imgdata.lens.LensSerial, "----", 4))
150
461
        imgdata.lens.LensSerial[0] = '\0';
151
1.90k
      break;
152
627
    case 0xa420: /* 42016, ImageUniqueID */
153
627
      stmread(imgdata.color.ImageUniqueID, len, ifp);
154
627
      break;
155
186
    case 0xc65d: /* 50781, RawDataUniqueID */
156
186
      imgdata.color.RawDataUniqueID[16] = 0;
157
186
      fread(imgdata.color.RawDataUniqueID, 1, 16, ifp);
158
186
      break;
159
591
    case 0xc630: // DNG LensInfo, Lens Specification per EXIF standard
160
591
      imgdata.lens.dng.MinFocal = getrealf(type);
161
591
      imgdata.lens.dng.MaxFocal = getrealf(type);
162
591
      imgdata.lens.dng.MaxAp4MinFocal = getrealf(type);
163
591
      imgdata.lens.dng.MaxAp4MaxFocal = getrealf(type);
164
591
      break;
165
462
    case 0xc68b: /* 50827, OriginalRawFileName */
166
462
      stmread(imgdata.color.OriginalRawFileName, len, ifp);
167
462
      break;
168
7.24k
    case 0xa433: // LensMake
169
7.24k
      stmread(imgdata.lens.LensMake, len, ifp);
170
7.24k
      break;
171
1.67k
    case 0xa434: // LensModel
172
1.67k
      stmread(imgdata.lens.Lens, len, ifp);
173
1.67k
      if (!strncmp(imgdata.lens.Lens, "----", 4))
174
288
        imgdata.lens.Lens[0] = '\0';
175
1.67k
      break;
176
7.42k
    case 0x9205:
177
7.42k
      imgdata.lens.EXIF_MaxAp = libraw_powf64l(2.0f, getrealf(type) / 2.0f);
178
7.42k
      break;
179
790
    case 0x829a: // 33434
180
790
      shutter = getrealf(type);
181
790
      if (tiff_nifds > 0 && tiff_nifds <= LIBRAW_IFD_MAXCOUNT)
182
790
          tiff_ifd[tiff_nifds - 1].t_shutter = shutter;
183
790
      break;
184
841
    case 0x829d: // 33437, FNumber
185
841
      aperture = getrealf(type);
186
841
      break;
187
2.09k
    case 0x8827: // 34855
188
2.09k
      iso_speed = get2();
189
2.09k
      break;
190
666
    case 0x8831: // 34865
191
666
      if (iso_speed == 0xffff && !strncasecmp(make, "FUJI", 4))
192
74
        iso_speed = getrealf(type);
193
666
      break;
194
834
    case 0x8832: // 34866
195
834
      if (iso_speed == 0xffff &&
196
834
          (!strncasecmp(make, "SONY", 4) || !strncasecmp(make, "CANON", 5)))
197
175
        iso_speed = getrealf(type);
198
834
      break;
199
2.14k
    case 0x9003: // 36867
200
3.29k
    case 0x9004: // 36868
201
3.29k
      get_timestamp(0);
202
3.29k
      break;
203
2.32k
    case 0x9201: // 37377
204
2.32k
       if ((expo = -getreal(type)) < 128 && shutter == 0.)
205
1.29k
       {
206
1.29k
            shutter = libraw_powf64l(2.0f, float(expo));
207
1.29k
            if (tiff_nifds > 0 && tiff_nifds <= LIBRAW_IFD_MAXCOUNT)
208
1.29k
              tiff_ifd[tiff_nifds - 1].t_shutter = shutter;
209
1.29k
       }
210
2.32k
      break;
211
2.61k
    case 0x9202: // 37378 ApertureValue
212
2.61k
      if ((fabs(ape = getreal(type)) < 256.0) && (!aperture))
213
979
        aperture = libraw_powf64l(2.0f, float(ape / 2.0));
214
2.61k
      break;
215
744
    case 0x9209: // 37385
216
744
      flash_used = getrealf(type);
217
744
      break;
218
968
    case 0x920a: // 37386
219
968
      focal_len = getrealf(type);
220
968
      break;
221
569k
    case 0x927c: // 37500
222
569k
#ifndef USE_6BY9RPI
223
569k
      if (((make[0] == '\0') && !strncmp(model, "ov5647", 6)) ||
224
569k
          (!strncmp(make, "RaspberryPi", 11) &&
225
569k
           (!strncmp(model, "RP_OV5647", 9) ||
226
2.17k
            !strncmp(model, "RP_imx219", 9))))
227
#else
228
      if (((make[0] == '\0') && !strncmp(model, "ov5647", 6)) ||
229
          (!strncmp(make, "RaspberryPi", 11) &&
230
              (!strncmp(model, "RP_", 3) || !strncmp(model,"imx477",6))))
231
#endif
232
1.70k
      {
233
1.70k
        char mn_text[512];
234
1.70k
        char *pos;
235
1.70k
        char ccms[512];
236
1.70k
        ushort l;
237
1.70k
        float num;
238
239
1.70k
        fgets(mn_text, MIN(len, 511), ifp);
240
1.70k
        mn_text[511] = 0;
241
242
1.70k
        pos = strstr(mn_text, "ev=");
243
1.70k
        if (pos)
244
32
          imCommon.ExposureCalibrationShift = float(atof(pos + 3));
245
246
1.70k
        pos = strstr(mn_text, "gain_r=");
247
1.70k
        if (pos)
248
100
          cam_mul[0] = float(atof(pos + 7));
249
1.70k
        pos = strstr(mn_text, "gain_b=");
250
1.70k
        if (pos)
251
30
          cam_mul[2] = float(atof(pos + 7));
252
1.70k
        if ((cam_mul[0] > 0.001f) && (cam_mul[2] > 0.001f))
253
83
          cam_mul[1] = cam_mul[3] = 1.0f;
254
1.61k
        else
255
1.61k
          cam_mul[0] = cam_mul[2] = 0.0f;
256
257
1.70k
        pos = strstr(mn_text, "ccm=");
258
1.70k
        if (pos)
259
131
        {
260
131
          pos += 4;
261
131
          char *pos2 = strstr(pos, " ");
262
131
          if (pos2)
263
90
          {
264
90
            l = LIM(ushort(pos2 - pos), 0, 511);
265
90
            memcpy(ccms, pos, l);
266
90
            ccms[l] = '\0';
267
#ifdef LIBRAW_WIN32_CALLS
268
            // Win32 strtok is already thread-safe
269
            pos = strtok(ccms, ",");
270
#else
271
90
            char *last = 0;
272
90
            pos = strtok_r(ccms, ",", &last);
273
90
#endif
274
90
            if (pos)
275
86
            {
276
262
              for (l = 0; l < 3; l++) // skip last row
277
229
              {
278
229
                num = 0.0;
279
785
                for (c = 0; c < 3; c++)
280
609
                {
281
609
                  cmatrix[l][c] = (float)atoi(pos);
282
609
                  num += cmatrix[c][l];
283
#ifdef LIBRAW_WIN32_CALLS
284
                  pos = strtok(NULL, ",");
285
#else
286
609
                  pos = strtok_r(NULL, ",", &last);
287
609
#endif
288
609
                  if (!pos)
289
53
                    goto end; // broken
290
609
                }
291
176
                if (num > 0.01)
292
201
                    FORC3 cmatrix[l][c] = cmatrix[l][c] / num;
293
176
              }
294
86
            }
295
90
          }
296
131
        }
297
1.70k
      end:;
298
1.70k
      }
299
568k
      else if (!strncmp(make, "SONY", 4) &&
300
568k
               (!strncmp(model, "DSC-V3", 6) || !strncmp(model, "DSC-F828", 8)))
301
1.04k
      {
302
1.04k
        parseSonySRF(len);
303
1.04k
        break;
304
1.04k
      }
305
567k
      else if ((len == 1) && !strncmp(make, "NIKON", 5))
306
18.2k
      {
307
18.2k
        c = get4();
308
18.2k
        if (c)
309
16.7k
          fseek(ifp, c, SEEK_SET);
310
18.2k
        is_NikonTransfer = 1;
311
18.2k
      }
312
568k
      parse_makernote(base, 0);
313
568k
      break;
314
1.23k
    case 0xa002: // 40962
315
1.23k
      if (kodak)
316
32
        raw_width = get4();
317
1.23k
      break;
318
1.12k
    case 0xa003: // 40963
319
1.12k
      if (kodak)
320
48
        raw_height = get4();
321
1.12k
      break;
322
341
    case 0xa302: // 41730
323
341
      if (get4() == 0x20002)
324
435
        for (exif_cfa = c = 0; c < 8; c += 2)
325
348
          exif_cfa |= fgetc(ifp) * 0x01010101U << c;
326
4.14M
    }
327
4.13M
    fseek(ifp, save, SEEK_SET);
328
4.13M
  }
329
166k
}
330
331
void LibRaw::parse_gps_libraw(INT64 base)
332
4.83k
{
333
4.83k
  unsigned entries, tag, type, len, c;
334
4.83k
  INT64 save;
335
336
4.83k
  entries = get2();
337
4.83k
  if (entries > 40)
338
2.18k
    return;
339
2.64k
  if (entries > 0)
340
2.44k
    imgdata.other.parsed_gps.gpsparsed = 1;
341
2.64k
  INT64 fsize = ifp->size();
342
67.5k
  while (entries--)
343
64.9k
  {
344
64.9k
    tiff_get(base, &tag, &type, &len, &save);
345
64.9k
    if (len > 1024)
346
41.7k
    {
347
41.7k
      fseek(ifp, save, SEEK_SET); // Recover tiff-read position!!
348
41.7k
      continue;                   // no GPS tags are 1k or larger
349
41.7k
    }
350
23.2k
    INT64 savepos = ftell(ifp);
351
23.2k
    if (len > 8 && savepos + len > fsize * 2)
352
2.69k
    {
353
2.69k
        fseek(ifp, save, SEEK_SET); // Recover tiff-read position!!
354
2.69k
        continue;
355
2.69k
    }
356
357
20.5k
    if (callbacks.exif_cb)
358
0
    {
359
0
        callbacks.exif_cb(callbacks.exifparser_data, tag | 0x50000, type, len, order, ifp, base);
360
0
        fseek(ifp, savepos, SEEK_SET);
361
0
    }
362
363
20.5k
    switch (tag)
364
20.5k
    {
365
395
    case 0x0001:
366
395
      imgdata.other.parsed_gps.latref = getc(ifp);
367
395
      break;
368
717
    case 0x0003:
369
717
      imgdata.other.parsed_gps.longref = getc(ifp);
370
717
      break;
371
359
    case 0x0005:
372
359
      imgdata.other.parsed_gps.altref = getc(ifp);
373
359
      break;
374
1.47k
    case 0x0002:
375
1.47k
      if (len == 3)
376
2.43k
        FORC(3) imgdata.other.parsed_gps.latitude[c] = getrealf(type);
377
1.47k
      break;
378
963
    case 0x0004:
379
963
      if (len == 3)
380
1.27k
        FORC(3) imgdata.other.parsed_gps.longitude[c] = getrealf(type);
381
963
      break;
382
715
    case 0x0007:
383
715
      if (len == 3)
384
1.33k
        FORC(3) imgdata.other.parsed_gps.gpstimestamp[c] = getrealf(type);
385
715
      break;
386
558
    case 0x0006:
387
558
      imgdata.other.parsed_gps.altitude = getrealf(type);
388
558
      break;
389
132
    case 0x0009:
390
132
      imgdata.other.parsed_gps.gpsstatus = getc(ifp);
391
132
      break;
392
20.5k
    }
393
20.5k
    fseek(ifp, save, SEEK_SET);
394
20.5k
  }
395
2.64k
}
396
397
void LibRaw::parse_gps(INT64 base)
398
4.86k
{
399
4.86k
  unsigned entries, tag, type, len, c;
400
4.86k
  INT64 save;
401
402
4.86k
  entries = get2();
403
4.86k
  if (entries > 40)
404
2.18k
    return;
405
67.9k
  while (entries--)
406
65.2k
  {
407
65.2k
    tiff_get(base, &tag, &type, &len, &save);
408
65.2k
    if (len > 1024)
409
41.8k
    {
410
41.8k
      fseek(ifp, save, SEEK_SET); // Recover tiff-read position!!
411
41.8k
      continue;                   // no GPS tags are 1k or larger
412
41.8k
    }
413
23.3k
    switch (tag)
414
23.3k
    {
415
483
    case 0x0001:
416
1.28k
    case 0x0003:
417
1.65k
    case 0x0005:
418
1.65k
      gpsdata[29 + tag / 2] = getc(ifp);
419
1.65k
      break;
420
1.50k
    case 0x0002:
421
2.48k
    case 0x0004:
422
3.25k
    case 0x0007:
423
19.5k
      FORC(6) gpsdata[tag / 3 * 6 + c] = get4();
424
3.25k
      break;
425
562
    case 0x0006:
426
1.12k
      FORC(2) gpsdata[18 + c] = get4();
427
562
      break;
428
257
    case 0x0012: // 18
429
516
    case 0x001d: // 29
430
516
      fgets((char *)(gpsdata + 14 + tag / 3), MIN(len, 12), ifp);
431
23.3k
    }
432
23.3k
    fseek(ifp, save, SEEK_SET);
433
23.3k
  }
434
2.68k
}