/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 |