Coverage Report

Created: 2026-05-16 07:22

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