Coverage Report

Created: 2026-04-01 07:24

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