/src/libraw/src/metadata/ciff.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 | | #ifdef _MSC_VER |
21 | | #if _MSC_VER < 1800 /* below MSVC 2013 */ |
22 | | float roundf(float f) |
23 | | { |
24 | | return floorf(f + 0.5); |
25 | | } |
26 | | |
27 | | #endif |
28 | | #endif |
29 | | |
30 | | /* |
31 | | CIFF block 0x1030 contains an 8x8 white sample. |
32 | | Load this into white[][] for use in scale_colors(). |
33 | | */ |
34 | | void LibRaw::ciff_block_1030() |
35 | 1.63k | { |
36 | 1.63k | static const ushort key[] = {0x410, 0x45f3}; |
37 | 1.63k | int i, bpp, row, col, vbits = 0; |
38 | 1.63k | unsigned long bitbuf = 0; |
39 | | |
40 | 1.63k | if ((get2(), get4()) != 0x80008 || !get4()) |
41 | 1.17k | return; |
42 | 466 | bpp = get2(); |
43 | 466 | if (bpp != 10 && bpp != 12) |
44 | 336 | return; |
45 | 1.17k | for (i = row = 0; row < 8; row++) |
46 | 9.36k | for (col = 0; col < 8; col++) |
47 | 8.32k | { |
48 | 8.32k | if (vbits < bpp) |
49 | 6.24k | { |
50 | 6.24k | bitbuf = bitbuf << 16 | (get2() ^ key[i++ & 1]); |
51 | 6.24k | vbits += 16; |
52 | 6.24k | } |
53 | 8.32k | white[row][col] = bitbuf >> (vbits -= bpp) & ~(-1 << bpp); |
54 | 8.32k | } |
55 | 130 | } |
56 | | |
57 | | /* |
58 | | Parse a CIFF file, better known as Canon CRW format. |
59 | | */ |
60 | | void LibRaw::parse_ciff(INT64 offset, int length, int depth) |
61 | 145k | { |
62 | 145k | int nrecs, c, type, len, wbi = -1; |
63 | 145k | INT64 save, tboff; |
64 | 145k | ushort key[] = {0x410, 0x45f3}; |
65 | 145k | ushort CanonColorInfo1_key; |
66 | 145k | ushort Appendix_A = 0; |
67 | 145k | INT64 WB_table_offset = 0; |
68 | 145k | int UseWBfromTable_as_AsShot = 1; |
69 | 145k | int Got_AsShotWB = 0; |
70 | 145k | INT64 fsize = ifp->size(); |
71 | 145k | if (metadata_blocks++ > LIBRAW_MAX_METADATA_BLOCKS) |
72 | 102 | throw LIBRAW_EXCEPTION_IO_CORRUPT; |
73 | | |
74 | 145k | fseek(ifp, offset + length - 4, SEEK_SET); |
75 | 145k | tboff = INT64(get4()) + offset; |
76 | 145k | fseek(ifp, tboff, SEEK_SET); |
77 | 145k | nrecs = get2(); |
78 | 145k | if (nrecs < 1) |
79 | 14.1k | return; |
80 | 130k | if ((nrecs | depth) > 127) |
81 | 69.3k | return; |
82 | | |
83 | 61.5k | if (nrecs * 10 + offset > fsize) |
84 | 3.00k | return; |
85 | | |
86 | 2.36M | while (nrecs--) |
87 | 2.32M | { |
88 | 2.32M | type = get2(); |
89 | 2.32M | len = get4(); |
90 | 2.32M | INT64 see = offset + get4(); |
91 | 2.32M | save = ftell(ifp); |
92 | | |
93 | | /* the following tags are not sub-tables |
94 | | * they contain the value in the "len" field |
95 | | * for such tags skip the check against filesize |
96 | | */ |
97 | 2.32M | if ((type != 0x2007) && (type != 0x580b) && (type != 0x501c) && |
98 | 2.31M | (type != 0x5029) && (type != 0x5813) && (type != 0x5814) && |
99 | 2.31M | (type != 0x5817) && (type != 0x5834) && (type != 0x580e)) |
100 | 2.31M | { |
101 | | |
102 | 2.31M | if (see >= fsize) |
103 | 1.75M | { // At least one byte |
104 | 1.75M | fseek(ifp, save, SEEK_SET); |
105 | 1.75M | continue; |
106 | 1.75M | } |
107 | 560k | fseek(ifp, see, SEEK_SET); |
108 | 560k | if ((((type >> 8) + 8) | 8) == 0x38) |
109 | 123k | { |
110 | 123k | parse_ciff(ftell(ifp), len, depth + 1); /* Parse a sub-table */ |
111 | 123k | } |
112 | 560k | } |
113 | | |
114 | 571k | if (type == 0x3004) |
115 | 20.6k | { |
116 | 20.6k | parse_ciff(ftell(ifp), len, depth + 1); |
117 | 20.6k | } |
118 | 550k | else if (type == 0x0810) |
119 | 944 | { |
120 | 944 | fread(artist, 64, 1, ifp); |
121 | 944 | artist[63] = 0; |
122 | 944 | } |
123 | 549k | else if (type == 0x080a) |
124 | 2.25k | { |
125 | 2.25k | fread(make, 64, 1, ifp); |
126 | 2.25k | make[63] = 0; |
127 | 2.25k | int mlen = (int)strbuflen(make); |
128 | 2.25k | fseek(ifp, mlen - 63, SEEK_CUR); |
129 | 2.25k | fread(model, 64, 1, ifp); |
130 | 2.25k | model[63] = 0; |
131 | | |
132 | 547k | } else if (type == 0x080b) { |
133 | 11.9k | stmread(imCommon.firmware, (unsigned)len, ifp); |
134 | 11.9k | if (!strncasecmp(imCommon.firmware, "Firmware Version", 16)) |
135 | 40 | memmove(imCommon.firmware, imCommon.firmware + 16, strlen(imCommon.firmware) - 15); |
136 | 11.9k | trimSpaces(imCommon.firmware); |
137 | | |
138 | 535k | } else if (type == 0x1810) |
139 | 3.10k | { |
140 | 3.10k | width = get4(); |
141 | 3.10k | height = get4(); |
142 | 3.10k | pixel_aspect = int_to_float(get4()); |
143 | 3.10k | flip = get4(); |
144 | 3.10k | } |
145 | 532k | else if (type == 0x1835) |
146 | 283 | { /* Get the decoder table */ |
147 | 283 | tiff_compress = get4(); |
148 | 283 | } |
149 | 531k | else if (type == 0x2007) |
150 | 309 | { |
151 | 309 | thumb_offset = see; |
152 | 309 | thumb_length = len; |
153 | 309 | } |
154 | 531k | else if (type == 0x1818) |
155 | 5.85k | { |
156 | 5.85k | shutter = libraw_powf64l(2.0f, -int_to_float((get4(), get4()))); |
157 | 5.85k | ilm.CurAp = aperture = libraw_powf64l(2.0f, int_to_float(get4()) / 2); |
158 | 5.85k | } |
159 | 525k | else if (type == 0x102a) // CanonShotInfo |
160 | 11.1k | { |
161 | | // iso_speed = pow (2.0, (get4(),get2())/32.0 - 4) * 50; |
162 | 11.1k | get2(); // skip one |
163 | 11.1k | iso_speed = |
164 | 11.1k | libraw_powf64l(2.0f, (get2() + get2()) / 32.0f - 5.0f) * 100.0f; |
165 | 11.1k | ilm.CurAp = aperture = _CanonConvertAperture((get2(), get2())); |
166 | 11.1k | shutter = libraw_powf64l(2.0f, -float((short)get2()) / 32.f); |
167 | 11.1k | imCanon.wbi = wbi = (get2(), get2()); |
168 | 11.1k | if (wbi >= (int)Canon_wbi2std.size()) |
169 | 4.32k | wbi = 0; |
170 | 11.1k | fseek(ifp, 32, SEEK_CUR); |
171 | 11.1k | if (shutter > 1e6) |
172 | 2.35k | shutter = float(get2()) / 10.f; |
173 | 11.1k | } |
174 | 514k | else if (type == 0x102c) // CanonColorInfo2 / Appendix A: Pro90IS, G1, G2, S30, S40 |
175 | 8.11k | { |
176 | 8.11k | int CanonColorInfo2_type = get2(); // G1 1028, G2 272, Pro90 IS 769, S30 274, S40 273, EOS D30 276 |
177 | 8.11k | if (CanonColorInfo2_type > 512) { /* Pro90 IS, G1 */ |
178 | 1.83k | fseek(ifp, 118, SEEK_CUR); |
179 | 7.33k | FORC4 cam_mul[BG2RG1_2_RGBG(c)] = get2(); |
180 | 1.83k | } |
181 | 6.27k | else if (CanonColorInfo2_type != 276) { /* G2, S30, S40 */ |
182 | 5.25k | Appendix_A = 1; |
183 | 5.25k | WB_table_offset = -14; |
184 | 5.25k | fseek(ifp, 98, SEEK_CUR); |
185 | 21.0k | FORC4 cam_mul[GRBG_2_RGBG(c)] = get2(); |
186 | 5.25k | if (cam_mul[0] > 0.001f) Got_AsShotWB = 1; |
187 | 5.25k | } |
188 | 8.11k | } |
189 | 506k | else if (type == 0x10a9) // ColorBalance: Canon D60, 10D, 300D, and clones |
190 | 5.87k | { |
191 | 5.87k | int bls = 0; |
192 | | /* |
193 | | int table[] = { |
194 | | LIBRAW_WBI_Auto, // 0 |
195 | | LIBRAW_WBI_Daylight, // 1 |
196 | | LIBRAW_WBI_Cloudy, // 2 |
197 | | LIBRAW_WBI_Tungsten, // 3 |
198 | | LIBRAW_WBI_FL_W, // 4 |
199 | | LIBRAW_WBI_Flash, // 5 |
200 | | LIBRAW_WBI_Custom, // 6, absent in Canon D60 |
201 | | LIBRAW_WBI_Auto, // 7, use this if camera is set to b/w JPEG |
202 | | LIBRAW_WBI_Shade, // 8 |
203 | | LIBRAW_WBI_Kelvin // 9, absent in Canon D60 |
204 | | }; |
205 | | */ |
206 | 5.87k | int nWB = |
207 | 5.87k | ((get2() - 2) / 8) - |
208 | 5.87k | 1; // 2 bytes this, N recs 4*2bytes each, last rec is black level |
209 | 5.87k | if (nWB) |
210 | 21.3k | FORC4 icWBC[LIBRAW_WBI_Auto][RGGB_2_RGBG(c)] = get2(); |
211 | 5.87k | if (nWB >= 7) |
212 | 4.77k | Canon_WBpresets(0, 0); |
213 | 1.10k | else |
214 | 4.40k | FORC4 cam_mul[c] = float(icWBC[LIBRAW_WBI_Auto][c]); |
215 | 5.87k | if (nWB == 7) // mostly Canon EOS D60 + some fw#s for 300D; |
216 | | // check for 0x1668000 is unreliable |
217 | 3.05k | { |
218 | 3.05k | if ((wbi >= 0) && (wbi < 9) && (wbi != 6)) |
219 | 1.12k | { |
220 | 4.48k | FORC4 cam_mul[c] = float(icWBC[Canon_wbi2std[wbi]][c]); |
221 | 1.12k | } |
222 | 1.93k | else |
223 | 1.93k | { |
224 | 7.74k | FORC4 cam_mul[c] = float(icWBC[LIBRAW_WBI_Auto][c]); |
225 | 1.93k | } |
226 | 3.05k | } |
227 | 2.81k | else if (nWB == 9) // Canon 10D, 300D |
228 | 1.23k | { |
229 | 4.95k | FORC4 icWBC[LIBRAW_WBI_Custom][RGGB_2_RGBG(c)] = get2(); |
230 | 4.95k | FORC4 icWBC[LIBRAW_WBI_Kelvin][RGGB_2_RGBG(c)] = get2(); |
231 | 1.23k | if ((wbi >= 0) && (wbi < 10)) |
232 | 418 | { |
233 | 1.67k | FORC4 cam_mul[c] = float(icWBC[Canon_wbi2std[wbi]][c]); |
234 | 418 | } |
235 | 821 | else |
236 | 821 | { |
237 | 3.28k | FORC4 cam_mul[c] = float(icWBC[LIBRAW_WBI_Auto][c]); |
238 | 821 | } |
239 | 1.23k | } |
240 | 5.87k | FORC4 |
241 | 23.4k | bls += (imCanon.ChannelBlackLevel[RGGB_2_RGBG(c)] = get2()); |
242 | 5.87k | imCanon.AverageBlackLevel = bls / 4; |
243 | 5.87k | } |
244 | 500k | else if (type == 0x102d) |
245 | 5.19k | { |
246 | 5.19k | Canon_CameraSettings(len >> 1); |
247 | 5.19k | } |
248 | | |
249 | 495k | else if (type == 0x10b4) { |
250 | 5.42k | switch (get2()) { |
251 | 452 | case 1: |
252 | 452 | imCommon.ColorSpace = LIBRAW_COLORSPACE_sRGB; |
253 | 452 | break; |
254 | 678 | case 2: |
255 | 678 | imCommon.ColorSpace = LIBRAW_COLORSPACE_AdobeRGB; |
256 | 678 | break; |
257 | 4.29k | default: |
258 | 4.29k | imCommon.ColorSpace = LIBRAW_COLORSPACE_Unknown; |
259 | 4.29k | break; |
260 | 5.42k | } |
261 | | |
262 | 490k | } else if (type == 0x580b) |
263 | 1.66k | { |
264 | 1.66k | if (strcmp(model, "Canon EOS D30")) |
265 | 1.66k | sprintf(imgdata.shootinginfo.BodySerial, "%d", len); |
266 | 0 | else |
267 | 0 | sprintf(imgdata.shootinginfo.BodySerial, "%0x-%05d", len >> 16, |
268 | 0 | len & 0xffff); |
269 | 1.66k | } |
270 | 488k | else if (type == 0x0032) // CanonColorInfo1 |
271 | 19.6k | { |
272 | 19.6k | if (len == 768) { // EOS D30 |
273 | | |
274 | 1.74k | ushort q; |
275 | 1.74k | fseek(ifp, 4, SEEK_CUR); |
276 | 12.2k | for (unsigned linenum = 0; linenum < Canon_D30_linenums_2_StdWBi.size(); linenum++) { |
277 | 10.4k | if (Canon_D30_linenums_2_StdWBi[linenum] != LIBRAW_WBI_Unknown) { |
278 | 41.9k | FORC4 { |
279 | 41.9k | q = get2(); |
280 | 41.9k | icWBC[Canon_D30_linenums_2_StdWBi[linenum]][RGGB_2_RGBG(c)] = |
281 | 41.9k | (int)(roundf(1024000.0f / (float)MAX(1, q))); |
282 | 41.9k | } |
283 | | // if (Canon_wbi2std[imCanon.wbi] == *(Canon_D30_linenums_2_StdWBi + linenum)) { |
284 | | // FORC4 cam_mul[c] = icWBC[*(Canon_D30_linenums_2_StdWBi + linenum)][c]; |
285 | | // Got_AsShotWB = 1; |
286 | | // } |
287 | 10.4k | } |
288 | 10.4k | } |
289 | 1.74k | fseek (ifp, 68-int(Canon_D30_linenums_2_StdWBi.size())*8, SEEK_CUR); |
290 | | |
291 | 6.99k | FORC4 { |
292 | 6.99k | q = get2(); |
293 | 6.99k | cam_mul[RGGB_2_RGBG(c)] = 1024.f / float(MAX(1, q)); |
294 | 6.99k | } |
295 | 1.74k | if (!wbi) |
296 | 508 | cam_mul[0] = -1; // use my auto white balance |
297 | | |
298 | 1.74k | } |
299 | 17.8k | else if ((cam_mul[0] <= 0.001f) || // Pro1, G3, G5, G6, S45, S50, S60, S70 |
300 | 3.32k | Appendix_A) // G2, S30, S40 |
301 | 16.0k | { |
302 | 16.0k | libraw_static_table_t linenums_2_StdWBi; |
303 | 16.0k | unsigned AsShotWB_linenum = Canon_wbi2std.size(); |
304 | | |
305 | 16.0k | CanonColorInfo1_key = get2(); |
306 | 16.0k | if ((CanonColorInfo1_key == key[0]) && (len == 2048)) { // Pro1 |
307 | 1.53k | linenums_2_StdWBi = Canon_KeyIs0x0410_Len2048_linenums_2_StdWBi; |
308 | 1.53k | WB_table_offset = 8; |
309 | | |
310 | 14.5k | } else if ((CanonColorInfo1_key == key[0]) && (len == 3072)) { // S60, S70, G6 |
311 | 1.21k | linenums_2_StdWBi = Canon_KeyIs0x0410_Len3072_linenums_2_StdWBi; |
312 | 1.21k | WB_table_offset = 16; |
313 | | |
314 | 13.3k | } else if (!CanonColorInfo1_key && (len == 2048)) { // G2, S30, S40; S45, S50, G3, G5 |
315 | 5.68k | key[0] = key[1] = 0; |
316 | 5.68k | linenums_2_StdWBi = Canon_KeyIsZero_Len2048_linenums_2_StdWBi; |
317 | 5.68k | if (atof(imCommon.firmware) < 1.02f) |
318 | 4.48k | UseWBfromTable_as_AsShot = 0; |
319 | | |
320 | 7.63k | } else goto next_tag; |
321 | | |
322 | 8.43k | if ((Canon_wbi2std[wbi] == LIBRAW_WBI_Auto) || |
323 | 2.25k | (Canon_wbi2std[wbi] == LIBRAW_WBI_Unknown) || |
324 | 1.86k | Got_AsShotWB) |
325 | 7.08k | UseWBfromTable_as_AsShot = 0; |
326 | | |
327 | 8.43k | if (UseWBfromTable_as_AsShot) { |
328 | 539 | int temp_wbi; |
329 | 539 | if (Canon_wbi2std[wbi] == LIBRAW_WBI_Custom) temp_wbi = LIBRAW_WBI_Daylight; |
330 | 395 | else temp_wbi = wbi; |
331 | 5.13k | for (AsShotWB_linenum = 0; AsShotWB_linenum < linenums_2_StdWBi.size(); AsShotWB_linenum++) { |
332 | 4.74k | if (Canon_wbi2std[temp_wbi] == linenums_2_StdWBi[AsShotWB_linenum]) { |
333 | 146 | break; |
334 | 146 | } |
335 | 4.74k | } |
336 | 539 | } |
337 | | |
338 | 8.43k | fseek (ifp, 78LL+WB_table_offset, SEEK_CUR); |
339 | 84.1k | for (unsigned linenum = 0; linenum < linenums_2_StdWBi.size(); linenum++) { |
340 | 75.7k | if (linenums_2_StdWBi[linenum] != LIBRAW_WBI_Unknown) { |
341 | 245k | FORC4 icWBC[linenums_2_StdWBi[linenum]][GRBG_2_RGBG(c)] = get2() ^ key[c & 1]; |
342 | 61.4k | if (UseWBfromTable_as_AsShot && (AsShotWB_linenum == linenum)) { |
343 | 584 | FORC4 cam_mul[c] = float(icWBC[linenums_2_StdWBi[linenum]][c]); |
344 | 146 | Got_AsShotWB = 1; |
345 | 146 | } |
346 | 61.4k | } else { |
347 | 14.2k | fseek(ifp, 8, SEEK_CUR); |
348 | 14.2k | } |
349 | 75.7k | } |
350 | 8.43k | if (!Got_AsShotWB) |
351 | 7.77k | cam_mul[0] = -1; |
352 | 8.43k | } |
353 | 19.6k | } |
354 | 468k | else if (type == 0x1030 && wbi >= 0 && (0x18040 >> wbi & 1)) |
355 | 1.63k | { |
356 | 1.63k | ciff_block_1030(); // all that don't have 0x10a9 |
357 | 1.63k | } |
358 | 467k | else if (type == 0x1031) |
359 | 377 | { |
360 | 377 | raw_width = imCanon.SensorWidth = (get2(), get2()); |
361 | 377 | raw_height = imCanon.SensorHeight = get2(); |
362 | 377 | fseek(ifp, 4, SEEK_CUR); |
363 | 377 | imCanon.DefaultCropAbsolute = get_CanonArea(); |
364 | 377 | imCanon.LeftOpticalBlack = get_CanonArea(); |
365 | 377 | } |
366 | 466k | else if (type == 0x501c) |
367 | 2.82k | { |
368 | 2.82k | iso_speed = float(len & 0xffff); |
369 | 2.82k | } |
370 | 463k | else if (type == 0x5029) |
371 | 1.20k | { |
372 | 1.20k | ilm.CurFocal = float( len >> 16); |
373 | 1.20k | ilm.FocalType = len & 0xffff; |
374 | 1.20k | if (ilm.FocalType == LIBRAW_FT_ZOOM_LENS) |
375 | 166 | { |
376 | 166 | ilm.FocalUnits = 32; |
377 | 166 | if (ilm.FocalUnits > 1) |
378 | 166 | ilm.CurFocal /= (float)ilm.FocalUnits; |
379 | 166 | } |
380 | 1.20k | focal_len = ilm.CurFocal; |
381 | 1.20k | } |
382 | 462k | else if (type == 0x5813) |
383 | 404 | { |
384 | 404 | flash_used = int_to_float(len); |
385 | 404 | } |
386 | 462k | else if (type == 0x5814) |
387 | 1.34k | { |
388 | 1.34k | canon_ev = int_to_float(len); |
389 | 1.34k | } |
390 | 460k | else if (type == 0x5817) |
391 | 408 | { |
392 | 408 | shot_order = len; |
393 | 408 | } |
394 | 460k | else if (type == 0x5834) |
395 | 344 | { |
396 | 344 | unique_id = ((unsigned long long)len << 32) >> 32; |
397 | 344 | setCanonBodyFeatures(unique_id); |
398 | 344 | } |
399 | 460k | else if (type == 0x580e) |
400 | 2.22k | { |
401 | 2.22k | timestamp = len; |
402 | 2.22k | } |
403 | 457k | else if (type == 0x180e) |
404 | 347 | { |
405 | 347 | timestamp = get4(); |
406 | 347 | } |
407 | | |
408 | 563k | next_tag:; |
409 | | #ifdef LOCALTIME |
410 | | if ((type | 0x4000) == 0x580e) |
411 | | timestamp = mktime(gmtime(×tamp)); |
412 | | #endif |
413 | 560k | fseek(ifp, save, SEEK_SET); |
414 | 560k | } |
415 | 58.5k | } |