Coverage Report

Created: 2026-02-14 07:11

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
2
{
84
2
  unsigned row;
85
86
103
  for (row = 0; row < 100; row++)
87
102
  {
88
102
    fseek(ifp, row * 3340 + 3284, SEEK_SET);
89
102
    if (getc(ifp) > 15)
90
1
      return 1;
91
102
  }
92
1
  return 0;
93
2
}
94
95
void LibRaw::parse_cine()
96
15
{
97
15
  unsigned off_head, off_setup, off_image, i, temp;
98
99
15
  order = 0x4949;
100
15
  fseek(ifp, 4, SEEK_SET);
101
15
  is_raw = get2() == 2;
102
15
  fseek(ifp, 14, SEEK_CUR);
103
15
  is_raw *= get4();
104
15
  off_head = get4();
105
15
  off_setup = get4();
106
15
  off_image = get4();
107
15
  timestamp = get4();
108
15
  if ((i = get4()))
109
14
    timestamp = i;
110
15
  fseek(ifp, off_head + 4, SEEK_SET);
111
15
  raw_width = get4();
112
15
  raw_height = get4();
113
15
  switch (get2(), get2())
114
15
  {
115
1
  case 8:
116
1
    load_raw = &LibRaw::eight_bit_load_raw;
117
1
    break;
118
1
  case 16:
119
1
    load_raw = &LibRaw::unpacked_load_raw;
120
15
  }
121
15
  fseek(ifp, off_setup + 792, SEEK_SET);
122
15
  strcpy(make, "CINE");
123
15
  sprintf(model, "%d", get4());
124
15
  fseek(ifp, 12, SEEK_CUR);
125
15
  switch ((i = get4()) & 0xffffff)
126
15
  {
127
2
  case 3:
128
2
    filters = 0x94949494;
129
2
    break;
130
1
  case 4:
131
1
    filters = 0x49494949;
132
1
    break;
133
12
  default:
134
12
    is_raw = 0;
135
15
  }
136
15
  fseek(ifp, 72, SEEK_CUR);
137
15
  switch ((get4() + 3600) % 360)
138
15
  {
139
1
  case 270:
140
1
    flip = 4;
141
1
    break;
142
0
  case 180:
143
0
    flip = 1;
144
0
    break;
145
2
  case 90:
146
2
    flip = 7;
147
2
    break;
148
1
  case 0:
149
1
    flip = 2;
150
15
  }
151
15
  cam_mul[0] = getrealf(LIBRAW_EXIFTAG_TYPE_FLOAT);
152
15
  cam_mul[2] = getrealf(LIBRAW_EXIFTAG_TYPE_FLOAT);
153
15
  temp = get4();
154
15
  maximum = ~((~0u) << LIM(temp, 1, 31));
155
15
  fseek(ifp, 668, SEEK_CUR);
156
15
  shutter = float(get4()) / 1000000000.f;
157
15
  fseek(ifp, off_image, SEEK_SET);
158
15
  if (shot_select < is_raw)
159
0
    fseek(ifp, shot_select * 8, SEEK_CUR);
160
15
  data_offset = (INT64)get4() + 8;
161
15
  data_offset += (INT64)get4() << 32;
162
15
}
163
164
void LibRaw::parse_qt(INT64 end)
165
53.8k
{
166
53.8k
  unsigned size;
167
53.8k
  INT64 save;
168
53.8k
  char tag[4];
169
170
53.8k
  order = 0x4d4d;
171
146k
  while (ftell(ifp) + 7 < end)
172
107k
  {
173
107k
    save = ftell(ifp);
174
107k
    if ((size = get4()) < 8)
175
17
      return;
176
107k
    if ((int)size < 0)
177
14.9k
      return; // 2+GB is too much
178
92.8k
    if (save + size < save)
179
0
      return; // 32bit overflow
180
92.8k
    memset(tag,0,sizeof(tag));
181
92.8k
    fread(tag, 4, 1, ifp);
182
92.8k
    if (!memcmp(tag, "moov", 4) || !memcmp(tag, "udta", 4) ||
183
67.5k
        !memcmp(tag, "CNTH", 4))
184
53.2k
      parse_qt(save + size);
185
92.8k
    if (!memcmp(tag, "CNDA", 4))
186
13.5k
      parse_jpeg(ftell(ifp));
187
92.8k
    fseek(ifp, save + INT64(size), SEEK_SET);
188
92.8k
  }
189
53.8k
}
190
191
void LibRaw::parse_smal(INT64 offset, INT64 fsize)
192
3.18k
{
193
3.18k
  int ver;
194
195
3.18k
  fseek(ifp, offset + 2LL, SEEK_SET);
196
3.18k
  order = 0x4949;
197
3.18k
  ver = fgetc(ifp);
198
3.18k
  if (ver == 6)
199
23
    fseek(ifp, 5, SEEK_CUR);
200
3.18k
  if (INT64(get4()) != fsize)
201
3.05k
    return;
202
123
  if (ver > 6)
203
103
    data_offset = get4();
204
123
  raw_height = height = get2();
205
123
  raw_width = width = get2();
206
123
  strcpy(make, "SMaL");
207
123
  sprintf(model, "v%d %dx%d", ver, width, height);
208
123
  if (ver == 6)
209
18
    load_raw = &LibRaw::smal_v6_load_raw;
210
123
  if (ver == 9)
211
95
    load_raw = &LibRaw::smal_v9_load_raw;
212
123
}
213
214
void LibRaw::parse_riff(int maxdepth)
215
785
{
216
785
  unsigned i, size;
217
785
  INT64 end;
218
785
  char tag[4] = {0, 0, 0, 0}, date[64], month[64];
219
785
  static const char mon[12][4] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
220
785
                                  "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
221
785
  struct tm t;
222
785
  if (maxdepth < 1)
223
0
    throw LIBRAW_EXCEPTION_IO_CORRUPT;
224
225
785
  order = 0x4949;
226
785
  fread(tag, 4, 1, ifp);
227
785
  size = get4();
228
785
  end = ftell(ifp) + size;
229
785
  if (!memcmp(tag, "RIFF", 4) || !memcmp(tag, "LIST", 4))
230
232
  {
231
232
    int maxloop = 1000;
232
232
    get4();
233
973
    while (ftell(ifp) + 7 < end && !feof(ifp) && maxloop--)
234
741
      parse_riff(maxdepth-1);
235
232
  }
236
553
  else if (!memcmp(tag, "nctg", 4))
237
48
  {
238
143k
    while (ftell(ifp) + 7 < end)
239
143k
    {
240
143k
    if (feof(ifp))
241
1
      break;
242
143k
      i = get2();
243
143k
      size = get2();
244
143k
      if ((i + 1) >> 1 == 10 && size == 20)
245
2
        get_timestamp(0);
246
143k
      else
247
143k
        fseek(ifp, size, SEEK_CUR);
248
143k
    }
249
48
  }
250
505
  else if (!memcmp(tag, "IDIT", 4) && size < 64)
251
75
  {
252
75
    memset(date,0,sizeof(date));
253
75
    fread(date, 64, 1, ifp);
254
75
    date[size] = 0;
255
75
    memset(&t, 0, sizeof t);
256
75
    if (sscanf(date, "%*s %s %d %d:%d:%d %d", month, &t.tm_mday, &t.tm_hour,
257
75
               &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
75
  }
267
430
  else
268
430
    fseek(ifp, size, SEEK_CUR);
269
785
}
270
271
void LibRaw::parse_rollei()
272
114
{
273
114
  char line[128], *val;
274
114
  struct tm t;
275
276
114
  fseek(ifp, 0, SEEK_SET);
277
114
  memset(&t, 0, sizeof t);
278
114
  do
279
4.94k
  {
280
4.94k
    line[0] = 0;
281
4.94k
    if (!fgets(line, 128, ifp))
282
107
      break;
283
4.83k
    line[127] = 0;
284
4.83k
    if(!line[0]) break; // zero-length
285
4.82k
    if ((val = strchr(line, '=')))
286
1.16k
      *val++ = 0;
287
3.66k
    else
288
3.66k
      val = line + strbuflen(line);
289
4.82k
    if (!strcmp(line, "DAT"))
290
78
      sscanf(val, "%d.%d.%d", &t.tm_mday, &t.tm_mon, &t.tm_year);
291
4.82k
    if (!strcmp(line, "TIM"))
292
210
      sscanf(val, "%d:%d:%d", &t.tm_hour, &t.tm_min, &t.tm_sec);
293
4.82k
    if (!strcmp(line, "HDR"))
294
31
      thumb_offset = atoi(val);
295
4.82k
    if (!strcmp(line, "X  "))
296
139
      raw_width = atoi(val);
297
4.82k
    if (!strcmp(line, "Y  "))
298
232
      raw_height = atoi(val);
299
4.82k
    if (!strcmp(line, "TX "))
300
275
      thumb_width = atoi(val);
301
4.82k
    if (!strcmp(line, "TY "))
302
276
      thumb_height = atoi(val);
303
4.82k
    if (!strcmp(line, "APT"))
304
193
      aperture = float(atof(val));
305
4.82k
    if (!strcmp(line, "SPE"))
306
187
      shutter = float(atof(val));
307
4.82k
    if (!strcmp(line, "FOCLEN"))
308
43
      focal_len = float(atof(val));
309
4.82k
    if (!strcmp(line, "BLKOFS"))
310
31
      black = atoi(val) +1;
311
4.82k
    if (!strcmp(line, "ORI"))
312
911
      switch (atoi(val)) {
313
37
      case 1:
314
37
        flip = 6;
315
37
        break;
316
179
      case 2:
317
179
        flip = 3;
318
179
        break;
319
276
      case 3:
320
276
        flip = 5;
321
276
        break;
322
911
      }
323
4.82k
    if (!strcmp(line, "CUTRECT")) {
324
57
      sscanf(val, "%hu %hu %hu %hu",
325
57
             &imgdata.sizes.raw_inset_crops[0].cleft,
326
57
             &imgdata.sizes.raw_inset_crops[0].ctop,
327
57
             &imgdata.sizes.raw_inset_crops[0].cwidth,
328
57
             &imgdata.sizes.raw_inset_crops[0].cheight);
329
57
    }
330
4.82k
  } while (strncmp(line, "EOHD", 4));
331
114
  data_offset = thumb_offset + thumb_width * thumb_height * 2;
332
114
  t.tm_year -= 1900;
333
114
  t.tm_mon -= 1;
334
114
  if (mktime(&t) > 0)
335
0
    timestamp = mktime(&t);
336
114
  strcpy(make, "Rollei");
337
114
  strcpy(model, "d530flex");
338
114
  thumb_format = LIBRAW_INTERNAL_THUMBNAIL_ROLLEI;
339
114
}
340
341
void LibRaw::parse_sinar_ia()
342
420
{
343
420
  int entries, off;
344
420
  char str[8], *cp;
345
346
420
  order = 0x4949;
347
420
  fseek(ifp, 4, SEEK_SET);
348
420
  entries = get4();
349
420
  if (entries < 1 || entries > 8192)
350
9
    return;
351
411
  fseek(ifp, get4(), SEEK_SET);
352
593k
  while (entries--)
353
592k
  {
354
592k
    off = get4();
355
592k
    get4();
356
592k
  memset(str, 0, sizeof(str));
357
592k
    fread(str, 8, 1, ifp);
358
592k
    str[7] = 0; // Ensure end of string
359
592k
    if (!strcmp(str, "META"))
360
6
      meta_offset = off;
361
592k
    if (!strcmp(str, "THUMB"))
362
24
      thumb_offset = off;
363
592k
    if (!strcmp(str, "RAW0"))
364
6
      data_offset = off;
365
592k
  }
366
411
  fseek(ifp, meta_offset + 20, SEEK_SET);
367
411
  fread(make, 64, 1, ifp);
368
411
  make[63] = 0;
369
411
  if ((cp = strchr(make, ' ')))
370
358
  {
371
358
    strcpy(model, cp + 1);
372
358
    *cp = 0;
373
358
  }
374
411
  raw_width = get2();
375
411
  raw_height = get2();
376
411
  load_raw = &LibRaw::unpacked_load_raw;
377
411
  thumb_width = (get4(), get2());
378
411
  thumb_height = get2();
379
411
  thumb_format = LIBRAW_INTERNAL_THUMBNAIL_PPM;
380
411
  maximum = 0x3fff;
381
411
}
382
383
void LibRaw::parse_kyocera()
384
16
{
385
386
16
  int c;
387
16
  static const ushort table[13] = {25,  32,  40,  50,  64,  80, 100,
388
16
                                   125, 160, 200, 250, 320, 400};
389
390
16
  fseek(ifp, 33, SEEK_SET);
391
16
  get_timestamp(1);
392
16
  fseek(ifp, 52, SEEK_SET);
393
16
  c = get4();
394
16
  if ((c > 6) && (c < 20))
395
1
    iso_speed = table[c - 7];
396
16
  shutter = libraw_powf64l(2.0f, (((float)get4()) / 8.0f)) / 16000.0f;
397
64
  FORC4 cam_mul[RGGB_2_RGBG(c)] = float(get4());
398
16
  fseek(ifp, 88, SEEK_SET);
399
16
  aperture = libraw_powf64l(2.0f, ((float)get4()) / 16.0f);
400
16
  fseek(ifp, 112, SEEK_SET);
401
16
  focal_len = float(get4());
402
403
16
  fseek(ifp, 104, SEEK_SET);
404
16
  ilm.MaxAp4CurFocal = libraw_powf64l(2.0f, ((float)get4()) / 16.0f);
405
16
  fseek(ifp, 124, SEEK_SET);
406
16
  stmread(ilm.Lens, 32, ifp);
407
16
  ilm.CameraMount = LIBRAW_MOUNT_Contax_N;
408
16
  ilm.CameraFormat = LIBRAW_FORMAT_FF;
409
16
  if (ilm.Lens[0])
410
2
  {
411
2
    ilm.LensMount = LIBRAW_MOUNT_Contax_N;
412
2
    ilm.LensFormat = LIBRAW_FORMAT_FF;
413
2
  }
414
16
}
415
416
int LibRaw::parse_jpeg(INT64 offset)
417
16.5k
{
418
16.5k
  int len, hlen, mark;
419
16.5k
  INT64 save;
420
421
16.5k
  fseek(ifp, offset, SEEK_SET);
422
16.5k
  if (fgetc(ifp) != 0xff || fgetc(ifp) != 0xd8)
423
2.92k
    return 0;
424
425
57.2k
  while (fgetc(ifp) == 0xff && (mark = fgetc(ifp)) != 0xda)
426
43.5k
  {
427
43.5k
    order = 0x4d4d;
428
43.5k
    len = get2() - 2;
429
43.5k
    save = ftell(ifp);
430
43.5k
    if (mark == 0xc0 || mark == 0xc3 || mark == 0xc9)
431
16.1k
    {
432
16.1k
      fgetc(ifp);
433
16.1k
      raw_height = get2();
434
16.1k
      raw_width = get2();
435
16.1k
    }
436
43.5k
    order = get2();
437
43.5k
    hlen = get4();
438
43.5k
    if (get4() == 0x48454150 && (save + INT64(hlen)) >= 0 &&
439
530
        (save + INT64(hlen)) <= ifp->size()) /* "HEAP" */
440
342
    {
441
342
      parse_ciff(save + hlen, len - hlen, 0);
442
342
    }
443
43.5k
    if (parse_tiff(save + 6))
444
16.4k
      apply_tiff();
445
43.5k
    fseek(ifp, save + INT64(len), SEEK_SET);
446
43.5k
  }
447
13.6k
  return 1;
448
16.5k
}
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
2.81k
{
533
2.81k
  struct tm t;
534
2.81k
  char str[20];
535
2.81k
  int i;
536
537
2.81k
  str[19] = 0;
538
2.81k
  if (reversed)
539
320
    for (i = 19; i--;)
540
304
      str[i] = fgetc(ifp);
541
2.79k
  else
542
2.79k
    fread(str, 19, 1, ifp);
543
2.81k
  memset(&t, 0, sizeof t);
544
2.81k
  if (sscanf(str, "%d:%d:%d %d:%d:%d", &t.tm_year, &t.tm_mon, &t.tm_mday,
545
2.81k
             &t.tm_hour, &t.tm_min, &t.tm_sec) != 6)
546
2.43k
    return;
547
376
  t.tm_year -= 1900;
548
376
  t.tm_mon -= 1;
549
376
  t.tm_isdst = -1;
550
376
  if (mktime(&t) > 0)
551
59
    timestamp = mktime(&t);
552
376
}
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