Coverage Report

Created: 2026-09-14 07:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/LibRaw/src/metadata/misc_parsers.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
21
/*
22
   Returns 1 for a Coolpix 2100, 0 for anything else.
23
 */
24
int LibRaw::nikon_e2100()
25
0
{
26
0
  uchar t[12];
27
0
  int i;
28
29
0
  fseek(ifp, 0, SEEK_SET);
30
0
  for (i = 0; i < 1024; i++)
31
0
  {
32
0
    fread(t, 1, 12, ifp);
33
0
    if (((t[2] & t[4] & t[7] & t[9]) >> 4 & t[1] & t[6] & t[8] & t[11] & 3) !=
34
0
        3)
35
0
      return 0;
36
0
  }
37
0
  return 1;
38
0
}
39
40
void LibRaw::nikon_3700()
41
0
{
42
0
  int bits, i;
43
0
  uchar dp[24];
44
0
  static const struct
45
0
  {
46
0
    int bits;
47
0
    char t_make[12], t_model[15];
48
0
    int t_maker_idx;
49
0
  } table[] = {{0x00, "Pentax", "Optio 33WR", LIBRAW_CAMERAMAKER_Pentax},
50
0
               {0x03, "Nikon", "E3200", LIBRAW_CAMERAMAKER_Nikon},
51
0
               {0x32, "Nikon", "E3700", LIBRAW_CAMERAMAKER_Nikon},
52
0
               {0x33, "Olympus", "C-740UZ", LIBRAW_CAMERAMAKER_Olympus}};
53
54
0
  fseek(ifp, 3072, SEEK_SET);
55
0
  fread(dp, 1, 24, ifp);
56
0
  bits = (dp[8] & 3) << 4 | (dp[20] & 3);
57
0
  for (i = 0; i < int(sizeof table / sizeof *table); i++)
58
0
    if (bits == table[i].bits)
59
0
    {
60
0
      strcpy(make, table[i].t_make);
61
0
      maker_index = table[i].t_maker_idx;
62
0
      strcpy(model, table[i].t_model);
63
0
    }
64
0
}
65
66
/*
67
   Separates a Minolta DiMAGE Z2 from a Nikon E4300.
68
 */
69
int LibRaw::minolta_z2()
70
0
{
71
0
  int i, nz;
72
0
  char tail[424];
73
0
  memset(tail,0,sizeof(tail));
74
0
  fseek(ifp, -int(sizeof tail), SEEK_END);
75
0
  fread(tail, 1, sizeof tail, ifp);
76
0
  for (nz = i = 0; i < int(sizeof tail); i++)
77
0
    if (tail[i])
78
0
      nz++;
79
0
  return nz > 20;
80
0
}
81
82
int LibRaw::canon_s2is()
83
12
{
84
12
  unsigned row;
85
86
336
  for (row = 0; row < 100; row++)
87
334
  {
88
334
    fseek(ifp, row * 3340 + 3284, SEEK_SET);
89
334
    if (getc(ifp) > 15)
90
10
      return 1;
91
334
  }
92
2
  return 0;
93
12
}
94
95
void LibRaw::parse_cine()
96
96
{
97
96
  unsigned off_head, off_setup, off_image, i, temp;
98
99
96
  order = 0x4949;
100
96
  fseek(ifp, 4, SEEK_SET);
101
96
  is_raw = get2() == 2;
102
96
  fseek(ifp, 14, SEEK_CUR);
103
96
  is_raw *= get4();
104
96
  off_head = get4();
105
96
  off_setup = get4();
106
96
  off_image = get4();
107
96
  timestamp = get4();
108
96
  if ((i = get4()))
109
94
    timestamp = i;
110
96
  fseek(ifp, off_head + 4, SEEK_SET);
111
96
  raw_width = get4();
112
96
  raw_height = get4();
113
96
  switch (get2(), get2())
114
96
  {
115
48
  case 8:
116
48
    load_raw = &LibRaw::eight_bit_load_raw;
117
48
    break;
118
4
  case 16:
119
4
    load_raw = &LibRaw::unpacked_load_raw;
120
96
  }
121
96
  fseek(ifp, off_setup + 792, SEEK_SET);
122
96
  strcpy(make, "CINE");
123
96
  sprintf(model, "%d", get4());
124
96
  fseek(ifp, 12, SEEK_CUR);
125
96
  switch ((i = get4()) & 0xffffff)
126
96
  {
127
48
  case 3:
128
48
    filters = 0x94949494;
129
48
    break;
130
6
  case 4:
131
6
    filters = 0x49494949;
132
6
    break;
133
42
  default:
134
42
    is_raw = 0;
135
96
  }
136
96
  fseek(ifp, 72, SEEK_CUR);
137
96
  switch ((get4() + 3600) % 360)
138
96
  {
139
2
  case 270:
140
2
    flip = 4;
141
2
    break;
142
2
  case 180:
143
2
    flip = 1;
144
2
    break;
145
2
  case 90:
146
2
    flip = 7;
147
2
    break;
148
22
  case 0:
149
22
    flip = 2;
150
96
  }
151
96
  cam_mul[0] = getrealf(LIBRAW_EXIFTAG_TYPE_FLOAT);
152
96
  cam_mul[2] = getrealf(LIBRAW_EXIFTAG_TYPE_FLOAT);
153
96
  temp = get4();
154
96
  maximum = ~((~0u) << LIM(temp, 1, 31));
155
96
  fseek(ifp, 668, SEEK_CUR);
156
96
  shutter = float(get4()) / 1000000000.f;
157
96
  fseek(ifp, off_image, SEEK_SET);
158
96
  if (shot_select < is_raw)
159
50
    fseek(ifp, shot_select * 8, SEEK_CUR);
160
96
  data_offset = (INT64)get4() + 8;
161
96
  data_offset += (INT64)get4() << 32;
162
96
}
163
164
void LibRaw::parse_qt(INT64 end)
165
5.66k
{
166
5.66k
  unsigned size;
167
5.66k
  INT64 save;
168
5.66k
  char tag[4];
169
5.66k
  if (libraw_internal_data.unpacker_data.CR3_Version-- < 1)
170
112
    throw LIBRAW_EXCEPTION_IO_CORRUPT;
171
172
5.55k
  order = 0x4d4d;
173
23.1k
  while (ftell(ifp) + 7 < end)
174
19.5k
  {
175
19.5k
    save = ftell(ifp);
176
19.5k
    if ((size = get4()) < 8)
177
432
      return;
178
19.1k
    if ((int)size < 0)
179
1.58k
      return; // 2+GB is too much
180
17.5k
    if (save + size < save)
181
0
      return; // 32bit overflow
182
17.5k
    memset(tag,0,sizeof(tag));
183
17.5k
    fread(tag, 4, 1, ifp);
184
17.5k
    if (!memcmp(tag, "moov", 4) || !memcmp(tag, "udta", 4) ||
185
13.8k
        !memcmp(tag, "CNTH", 4))
186
5.42k
      parse_qt(save + size);
187
17.5k
    if (!memcmp(tag, "CNDA", 4))
188
1.43k
      parse_jpeg(ftell(ifp));
189
17.5k
    fseek(ifp, save + INT64(size), SEEK_SET);
190
17.5k
  }
191
5.55k
}
192
193
void LibRaw::parse_smal(INT64 offset, INT64 fsize)
194
4.80k
{
195
4.80k
  int ver;
196
197
4.80k
  fseek(ifp, offset + 2LL, SEEK_SET);
198
4.80k
  order = 0x4949;
199
4.80k
  ver = fgetc(ifp);
200
4.80k
  if (ver == 6)
201
54
    fseek(ifp, 5, SEEK_CUR);
202
4.80k
  if (INT64(get4()) != fsize)
203
4.51k
    return;
204
292
  if (ver > 6)
205
236
    data_offset = get4();
206
292
  raw_height = height = get2();
207
292
  raw_width = width = get2();
208
292
  strcpy(make, "SMaL");
209
292
  sprintf(model, "v%d %dx%d", ver, width, height);
210
292
  if (ver == 6)
211
52
    load_raw = &LibRaw::smal_v6_load_raw;
212
292
  if (ver == 9)
213
212
    load_raw = &LibRaw::smal_v9_load_raw;
214
292
}
215
216
void LibRaw::parse_riff(int maxdepth)
217
4.29k
{
218
4.29k
  unsigned i, size;
219
4.29k
  INT64 end;
220
4.29k
  char tag[4] = {0, 0, 0, 0}, date[64], month[64];
221
4.29k
  static const char mon[12][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
222
4.29k
                                  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
223
4.29k
  struct tm t;
224
4.29k
  if (maxdepth < 1)
225
0
    throw LIBRAW_EXCEPTION_IO_CORRUPT;
226
227
4.29k
  order = 0x4949;
228
4.29k
  fread(tag, 4, 1, ifp);
229
4.29k
  size = get4();
230
4.29k
  end = ftell(ifp) + size;
231
4.29k
  if (!memcmp(tag, "RIFF", 4) || !memcmp(tag, "LIST", 4))
232
468
  {
233
468
    int maxloop = 1000;
234
468
    get4();
235
4.66k
    while (ftell(ifp) + 7 < end && !feof(ifp) && maxloop--)
236
4.19k
      parse_riff(maxdepth-1);
237
468
  }
238
3.82k
  else if (!memcmp(tag, "nctg", 4))
239
130
  {
240
1.45k
    while (ftell(ifp) + 7 < end)
241
1.36k
    {
242
1.36k
    if (feof(ifp))
243
32
      break;
244
1.32k
      i = get2();
245
1.32k
      size = get2();
246
1.32k
      if ((i + 1) >> 1 == 10 && size == 20)
247
344
        get_timestamp(0);
248
984
      else
249
984
        fseek(ifp, size, SEEK_CUR);
250
1.32k
    }
251
130
  }
252
3.69k
  else if (!memcmp(tag, "IDIT", 4) && size < 64)
253
120
  {
254
120
    memset(date,0,sizeof(date));
255
120
    fread(date, 64, 1, ifp);
256
120
    date[size] = 0;
257
120
    memset(&t, 0, sizeof t);
258
120
    if (sscanf(date, "%*s %s %d %d:%d:%d %d", month, &t.tm_mday, &t.tm_hour,
259
120
               &t.tm_min, &t.tm_sec, &t.tm_year) == 6)
260
0
    {
261
0
      for (i = 0; i < 12 && strcasecmp(mon[i], month); i++)
262
0
        ;
263
0
      t.tm_mon = i;
264
0
      t.tm_year -= 1900;
265
0
      if (mktime(&t) > 0)
266
0
        timestamp = mktime(&t);
267
0
    }
268
120
  }
269
3.57k
  else
270
3.57k
    fseek(ifp, size, SEEK_CUR);
271
4.29k
}
272
273
void LibRaw::parse_rollei()
274
146
{
275
146
  char line[128], *val;
276
146
  struct tm t;
277
278
146
  fseek(ifp, 0, SEEK_SET);
279
146
  memset(&t, 0, sizeof t);
280
146
  do
281
8.49k
  {
282
8.49k
  memset(line, 0, sizeof(line));
283
8.49k
    if (!fgets(line, 128, ifp))
284
140
      break;
285
8.35k
    line[127] = 0;
286
8.35k
    if(!line[0]) break; // zero-length
287
8.34k
    if ((val = strchr(line, '=')))
288
708
      *val++ = 0;
289
7.63k
    else
290
7.63k
      val = line + strbuflen(line);
291
8.34k
    if (!strcmp(line, "DAT"))
292
440
      sscanf(val, "%d.%d.%d", &t.tm_mday, &t.tm_mon, &t.tm_year);
293
8.34k
    if (!strcmp(line, "TIM"))
294
14
      sscanf(val, "%d:%d:%d", &t.tm_hour, &t.tm_min, &t.tm_sec);
295
8.34k
    if (!strcmp(line, "HDR"))
296
0
      thumb_offset = atoi(val);
297
8.34k
    if (!strcmp(line, "X  "))
298
114
      raw_width = atoi(val);
299
8.34k
    if (!strcmp(line, "Y  "))
300
330
      raw_height = atoi(val);
301
8.34k
    if (!strcmp(line, "TX "))
302
290
      thumb_width = atoi(val);
303
8.34k
    if (!strcmp(line, "TY "))
304
288
      thumb_height = atoi(val);
305
8.34k
    if (!strcmp(line, "APT"))
306
160
      aperture = float(atof(val));
307
8.34k
    if (!strcmp(line, "SPE"))
308
0
      shutter = float(atof(val));
309
8.34k
    if (!strcmp(line, "FOCLEN"))
310
72
      focal_len = float(atof(val));
311
8.34k
    if (!strcmp(line, "BLKOFS"))
312
70
      black = atoi(val) +1;
313
8.34k
    if (!strcmp(line, "ORI"))
314
66
      switch (atoi(val)) {
315
0
      case 1:
316
0
        flip = 6;
317
0
        break;
318
0
      case 2:
319
0
        flip = 3;
320
0
        break;
321
0
      case 3:
322
0
        flip = 5;
323
0
        break;
324
66
      }
325
8.34k
    if (!strcmp(line, "CUTRECT")) {
326
80
      sscanf(val, "%hu %hu %hu %hu",
327
80
             &imgdata.sizes.raw_inset_crops[0].cleft,
328
80
             &imgdata.sizes.raw_inset_crops[0].ctop,
329
80
             &imgdata.sizes.raw_inset_crops[0].cwidth,
330
80
             &imgdata.sizes.raw_inset_crops[0].cheight);
331
80
    }
332
8.34k
  } while (strncmp(line, "EOHD", 4));
333
146
  data_offset = thumb_offset + thumb_width * thumb_height * 2;
334
146
  t.tm_year -= 1900;
335
146
  t.tm_mon -= 1;
336
146
  if (mktime(&t) > 0)
337
6
    timestamp = mktime(&t);
338
146
  strcpy(make, "Rollei");
339
146
  strcpy(model, "d530flex");
340
146
  thumb_format = LIBRAW_INTERNAL_THUMBNAIL_ROLLEI;
341
146
}
342
343
void LibRaw::parse_sinar_ia()
344
316
{
345
316
  int entries, off;
346
316
  char str[8], *cp;
347
348
316
  order = 0x4949;
349
316
  fseek(ifp, 4, SEEK_SET);
350
316
  entries = get4();
351
316
  if (entries < 1 || entries > 8192)
352
14
    return;
353
302
  fseek(ifp, get4(), SEEK_SET);
354
127k
  while (entries--)
355
127k
  {
356
127k
    off = get4();
357
127k
    get4();
358
127k
  memset(str, 0, sizeof(str));
359
127k
    fread(str, 8, 1, ifp);
360
127k
    str[7] = 0; // Ensure end of string
361
127k
    if (!strcmp(str, "META"))
362
6
      meta_offset = off;
363
127k
    if (!strcmp(str, "THUMB"))
364
32
      thumb_offset = off;
365
127k
    if (!strcmp(str, "RAW0"))
366
14
      data_offset = off;
367
127k
  }
368
302
  fseek(ifp, meta_offset + 20, SEEK_SET);
369
302
  fread(make, 64, 1, ifp);
370
302
  make[63] = 0;
371
302
  if ((cp = strchr(make, ' ')))
372
166
  {
373
166
    strcpy(model, cp + 1);
374
166
    *cp = 0;
375
166
  }
376
302
  raw_width = get2();
377
302
  raw_height = get2();
378
302
  load_raw = &LibRaw::unpacked_load_raw;
379
302
  thumb_width = (get4(), get2());
380
302
  thumb_height = get2();
381
302
  thumb_format = LIBRAW_INTERNAL_THUMBNAIL_PPM;
382
302
  maximum = 0x3fff;
383
302
}
384
385
void LibRaw::parse_kyocera()
386
28
{
387
388
28
  int c;
389
28
  static const ushort table[13] = {25,  32,  40,  50,  64,  80, 100,
390
28
                                   125, 160, 200, 250, 320, 400};
391
392
28
  fseek(ifp, 33, SEEK_SET);
393
28
  get_timestamp(1);
394
28
  fseek(ifp, 52, SEEK_SET);
395
28
  c = get4();
396
28
  if ((c > 6) && (c < 20))
397
4
    iso_speed = table[c - 7];
398
28
  shutter = libraw_powf64l(2.0f, (((float)get4()) / 8.0f)) / 16000.0f;
399
112
  FORC4 cam_mul[RGGB_2_RGBG(c)] = float(get4());
400
28
  fseek(ifp, 88, SEEK_SET);
401
28
  aperture = libraw_powf64l(2.0f, ((float)get4()) / 16.0f);
402
28
  fseek(ifp, 112, SEEK_SET);
403
28
  focal_len = float(get4());
404
405
28
  fseek(ifp, 104, SEEK_SET);
406
28
  ilm.MaxAp4CurFocal = libraw_powf64l(2.0f, ((float)get4()) / 16.0f);
407
28
  fseek(ifp, 124, SEEK_SET);
408
28
  stmread(ilm.Lens, 32, ifp);
409
28
  ilm.CameraMount = LIBRAW_MOUNT_Contax_N;
410
28
  ilm.CameraFormat = LIBRAW_FORMAT_FF;
411
28
  if (ilm.Lens[0])
412
8
  {
413
8
    ilm.LensMount = LIBRAW_MOUNT_Contax_N;
414
8
    ilm.LensFormat = LIBRAW_FORMAT_FF;
415
8
  }
416
28
}
417
418
int LibRaw::parse_jpeg(INT64 offset)
419
5.95k
{
420
5.95k
  int len, hlen, mark;
421
5.95k
  INT64 save;
422
423
5.95k
  fseek(ifp, offset, SEEK_SET);
424
5.95k
  if (fgetc(ifp) != 0xff || fgetc(ifp) != 0xd8)
425
3.26k
    return 0;
426
427
10.5k
  while (fgetc(ifp) == 0xff && (mark = fgetc(ifp)) != 0xda)
428
7.83k
  {
429
7.83k
    order = 0x4d4d;
430
7.83k
    len = get2() - 2;
431
7.83k
    save = ftell(ifp);
432
7.83k
    if (mark == 0xc0 || mark == 0xc3 || mark == 0xc9)
433
562
    {
434
562
      fgetc(ifp);
435
562
      raw_height = get2();
436
562
      raw_width = get2();
437
562
    }
438
7.83k
    order = get2();
439
7.83k
    hlen = get4();
440
7.83k
    if (get4() == 0x48454150 && (save + INT64(hlen)) >= 0 &&
441
576
        (save + INT64(hlen)) <= ifp->size()) /* "HEAP" */
442
550
    {
443
550
      parse_ciff(save + hlen, len - hlen, 0);
444
550
    }
445
7.83k
    if (parse_tiff(save + 6))
446
3.63k
      apply_tiff();
447
7.83k
    fseek(ifp, save + INT64(len), SEEK_SET);
448
7.83k
  }
449
2.69k
  return 1;
450
5.95k
}
451
452
void LibRaw::parse_thumb_note(INT64 base, unsigned toff, unsigned tlen)
453
0
{
454
0
  unsigned entries, tag, type, len;
455
0
  INT64 save;
456
457
0
  entries = get2();
458
0
  while (entries--)
459
0
  {
460
0
    tiff_get(base, &tag, &type, &len, &save);
461
0
    if (tag == toff)
462
0
      thumb_offset = get4() + base;
463
0
    if (tag == tlen)
464
0
      thumb_length = get4();
465
0
    fseek(ifp, save, SEEK_SET);
466
0
  }
467
0
}
468
469
void LibRaw::parse_broadcom()
470
0
{
471
472
  /* This structure is at offset 0xb0 from the 'BRCM' ident. */
473
0
  struct
474
0
  {
475
0
    uint8_t umode[32];
476
0
    uint16_t uwidth;
477
0
    uint16_t uheight;
478
0
    uint16_t padding_right;
479
0
    uint16_t padding_down;
480
0
    uint32_t unknown_block[6];
481
0
    uint16_t transform;
482
0
    uint16_t format;
483
0
    uint8_t bayer_order;
484
0
    uint8_t bayer_format;
485
0
  } header;
486
487
0
  header.bayer_order = 0;
488
0
  fseek(ifp, 0xb0 - 0x20, SEEK_CUR);
489
0
  fread(&header, 1, sizeof(header), ifp);
490
0
  raw_stride =
491
0
      ((((((header.uwidth + header.padding_right) * 5) + 3) >> 2) + 0x1f) &
492
0
       (~0x1f));
493
0
  raw_width = width = header.uwidth;
494
0
  raw_height = height = header.uheight;
495
0
  filters = 0x16161616; /* default Bayer order is 2, BGGR */
496
497
0
  switch (header.bayer_order)
498
0
  {
499
0
  case 0: /* RGGB */
500
0
    filters = 0x94949494;
501
0
    break;
502
0
  case 1: /* GBRG */
503
0
    filters = 0x49494949;
504
0
    break;
505
0
  case 3: /* GRBG */
506
0
    filters = 0x61616161;
507
0
    break;
508
0
  }
509
0
}
510
511
/*
512
   Returns 1 for a Coolpix 995, 0 for anything else.
513
 */
514
int LibRaw::nikon_e995()
515
0
{
516
0
  int i, histo[256];
517
0
  const uchar often[] = {0x00, 0x55, 0xaa, 0xff};
518
519
0
  memset(histo, 0, sizeof histo);
520
0
  fseek(ifp, -2000, SEEK_END);
521
0
  for (i = 0; i < 2000; i++)
522
0
    histo[fgetc(ifp)]++;
523
0
  for (i = 0; i < 4; i++)
524
0
    if (histo[often[i]] < 200)
525
0
      return 0;
526
0
  return 1;
527
0
}
528
529
/*
530
   Since the TIFF DateTime string has no timezone information,
531
   assume that the camera's clock was set to Universal Time.
532
 */
533
void LibRaw::get_timestamp(int reversed)
534
19.8k
{
535
19.8k
  struct tm t;
536
19.8k
  char str[20];
537
19.8k
  int i;
538
539
19.8k
  str[19] = 0;
540
19.8k
  if (reversed)
541
560
    for (i = 19; i--;)
542
532
      str[i] = fgetc(ifp);
543
19.7k
  else
544
19.7k
    fread(str, 19, 1, ifp);
545
19.8k
  memset(&t, 0, sizeof t);
546
19.8k
  if (sscanf(str, "%d:%d:%d %d:%d:%d", &t.tm_year, &t.tm_mon, &t.tm_mday,
547
19.8k
             &t.tm_hour, &t.tm_min, &t.tm_sec) != 6)
548
17.2k
    return;
549
2.57k
  t.tm_year -= 1900;
550
2.57k
  t.tm_mon -= 1;
551
2.57k
  t.tm_isdst = -1;
552
2.57k
  if (mktime(&t) > 0)
553
2.07k
    timestamp = mktime(&t);
554
2.57k
}
555
556
#ifdef USE_6BY9RPI
557
void LibRaw::parse_raspberrypi()
558
{
559
  //This structure is at offset 0xB0 from the 'BRCM' ident.
560
  struct brcm_raw_header {
561
    uint8_t name[32];
562
    uint16_t h_width;
563
    uint16_t h_height;
564
    uint16_t padding_right;
565
    uint16_t padding_down;
566
    uint32_t dummy[6];
567
    uint16_t transform;
568
    uint16_t format;
569
    uint8_t bayer_order;
570
    uint8_t bayer_format;
571
  };
572
  //Values taken from https://github.com/raspberrypi/userland/blob/master/interface/vctypes/vc_image_types.h
573
#define BRCM_FORMAT_BAYER  33
574
#define BRCM_BAYER_RAW8    2
575
#define BRCM_BAYER_RAW10   3
576
#define BRCM_BAYER_RAW12   4
577
#define BRCM_BAYER_RAW14   5
578
#define BRCM_BAYER_RAW16   6
579
580
  struct brcm_raw_header header;
581
  uint8_t brcm_tag[4];
582
583
    if (ftell(ifp) > 22LL) // 22 bytes is minimum jpeg size
584
    {
585
        thumb_length = unsigned(ftell(ifp));
586
        thumb_offset = 0;
587
        thumb_width = thumb_height = 0;
588
        load_flags |= 0x4000; // flag: we have JPEG from beginning to meta_offset
589
    }
590
591
  // Sanity check that the caller has found a BRCM header
592
  if (!fread(brcm_tag, 1, sizeof(brcm_tag), ifp) ||
593
    memcmp(brcm_tag, "BRCM", sizeof(brcm_tag)))
594
    return;
595
596
  width = raw_width;
597
  data_offset = ftell(ifp) + 0x8000 - sizeof(brcm_tag);
598
599
  if (!fseek(ifp, 0xB0 - int(sizeof(brcm_tag)), SEEK_CUR) &&
600
    fread(&header, 1, sizeof(header), ifp)) {
601
    switch (header.bayer_order) {
602
    case 0: //RGGB
603
      filters = 0x94949494;
604
      break;
605
    case 1: //GBRG
606
      filters = 0x49494949;
607
      break;
608
    default:
609
    case 2: //BGGR
610
      filters = 0x16161616;
611
      break;
612
    case 3: //GRBG
613
      filters = 0x61616161;
614
      break;
615
    }
616
617
    if (header.format == BRCM_FORMAT_BAYER) {
618
      switch (header.bayer_format) {
619
      case BRCM_BAYER_RAW8:
620
        load_raw = &LibRaw::rpi_load_raw8;
621
        //1 pixel per byte
622
        raw_stride = ((header.h_width + header.padding_right) + 31)&(~31);
623
        width = header.h_width;
624
        raw_height = height = header.h_height;
625
        is_raw = 1;
626
        order = 0x4d4d;
627
        break;
628
      case BRCM_BAYER_RAW10:
629
        load_raw = &LibRaw::nokia_load_raw;
630
        //4 pixels per 5 bytes
631
        raw_stride = (((((header.h_width + header.padding_right) * 5) + 3) >> 2) + 31)&(~31);
632
        width = header.h_width;
633
        raw_height = height = header.h_height;
634
        is_raw = 1;
635
        order = 0x4d4d;
636
        break;
637
      case BRCM_BAYER_RAW12:
638
        load_raw = &LibRaw::rpi_load_raw12;
639
        //2 pixels per 3 bytes
640
        raw_stride = (((((header.h_width + header.padding_right) * 3) + 1) >> 1) + 31)&(~31);
641
        width = header.h_width;
642
        raw_height = height = header.h_height;
643
        is_raw = 1;
644
        order = 0x4d4d;
645
        break;
646
      case BRCM_BAYER_RAW14:
647
        load_raw = &LibRaw::rpi_load_raw14;
648
        //4 pixels per 7 bytes
649
        raw_stride = (((((header.h_width + header.padding_right) * 7) + 3) >> 2) + 31)&(~31);
650
        width = header.h_width;
651
        raw_height = height = header.h_height;
652
        is_raw = 1;
653
        order = 0x4d4d;
654
        break;
655
      case BRCM_BAYER_RAW16:
656
        load_raw = &LibRaw::rpi_load_raw16;
657
        //1 pixel per 2 bytes
658
        raw_stride = (((header.h_width + header.padding_right) << 1) + 31)&(~31);
659
        width = header.h_width;
660
        raw_height = height = header.h_height;
661
        is_raw = 1;
662
        order = 0x4d4d;
663
        break;
664
      default:
665
        break;
666
      }
667
    }
668
  }
669
}
670
#endif