/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 | 15.1k | { |
36 | 15.1k | static const ushort key[] = {0x410, 0x45f3}; |
37 | 15.1k | int i, bpp, row, col, vbits = 0; |
38 | 15.1k | unsigned long bitbuf = 0; |
39 | | |
40 | 15.1k | if ((get2(), get4()) != 0x80008 || !get4()) |
41 | 8.00k | return; |
42 | 7.12k | bpp = get2(); |
43 | 7.12k | if (bpp != 10 && bpp != 12) |
44 | 1.83k | return; |
45 | 47.5k | for (i = row = 0; row < 8; row++) |
46 | 380k | for (col = 0; col < 8; col++) |
47 | 338k | { |
48 | 338k | if (vbits < bpp) |
49 | 230k | { |
50 | 230k | bitbuf = bitbuf << 16 | (get2() ^ key[i++ & 1]); |
51 | 230k | vbits += 16; |
52 | 230k | } |
53 | 338k | white[row][col] = bitbuf >> (vbits -= bpp) & ~(-1 << bpp); |
54 | 338k | } |
55 | 5.28k | } |
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 | 307k | { |
62 | 307k | int nrecs, c, type, len, wbi = -1; |
63 | 307k | INT64 save, tboff; |
64 | 307k | ushort key[] = {0x410, 0x45f3}; |
65 | 307k | ushort CanonColorInfo1_key; |
66 | 307k | ushort Appendix_A = 0; |
67 | 307k | INT64 WB_table_offset = 0; |
68 | 307k | int UseWBfromTable_as_AsShot = 1; |
69 | 307k | int Got_AsShotWB = 0; |
70 | 307k | INT64 fsize = ifp->size(); |
71 | 307k | if (metadata_blocks++ > LIBRAW_MAX_METADATA_BLOCKS) |
72 | 194 | throw LIBRAW_EXCEPTION_IO_CORRUPT; |
73 | | |
74 | 307k | fseek(ifp, offset + length - 4, SEEK_SET); |
75 | 307k | tboff = INT64(get4()) + offset; |
76 | 307k | fseek(ifp, tboff, SEEK_SET); |
77 | 307k | nrecs = get2(); |
78 | 307k | if (nrecs < 1) |
79 | 12.5k | return; |
80 | 294k | if ((nrecs | depth) > 127) |
81 | 151k | return; |
82 | | |
83 | 143k | if (nrecs * 10 + offset > fsize) |
84 | 5.61k | return; |
85 | | |
86 | 6.28M | while (nrecs--) |
87 | 6.16M | { |
88 | 6.16M | type = get2(); |
89 | 6.16M | len = get4(); |
90 | 6.16M | INT64 see = offset + get4(); |
91 | 6.16M | 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 | 6.16M | if ((type != 0x2007) && (type != 0x580b) && (type != 0x501c) && |
98 | 6.15M | (type != 0x5029) && (type != 0x5813) && (type != 0x5814) && |
99 | 6.14M | (type != 0x5817) && (type != 0x5834) && (type != 0x580e)) |
100 | 6.13M | { |
101 | | |
102 | 6.13M | if (see >= fsize) |
103 | 4.78M | { // At least one byte |
104 | 4.78M | fseek(ifp, save, SEEK_SET); |
105 | 4.78M | continue; |
106 | 4.78M | } |
107 | 1.35M | fseek(ifp, see, SEEK_SET); |
108 | 1.35M | if ((((type >> 8) + 8) | 8) == 0x38) |
109 | 269k | { |
110 | 269k | parse_ciff(ftell(ifp), len, depth + 1); /* Parse a sub-table */ |
111 | 269k | } |
112 | 1.35M | } |
113 | | |
114 | 1.38M | if (type == 0x3004) |
115 | 35.7k | { |
116 | 35.7k | parse_ciff(ftell(ifp), len, depth + 1); |
117 | 35.7k | } |
118 | 1.35M | else if (type == 0x0810) |
119 | 3.51k | { |
120 | 3.51k | fread(artist, 64, 1, ifp); |
121 | 3.51k | artist[63] = 0; |
122 | 3.51k | } |
123 | 1.34M | else if (type == 0x080a) |
124 | 2.47k | { |
125 | 2.47k | fread(make, 64, 1, ifp); |
126 | 2.47k | make[63] = 0; |
127 | 2.47k | fseek(ifp, strbuflen(make) - 63, SEEK_CUR); |
128 | 2.47k | fread(model, 64, 1, ifp); |
129 | 2.47k | model[63] = 0; |
130 | | |
131 | 1.34M | } else if (type == 0x080b) { |
132 | 11.9k | stmread(imCommon.firmware, (unsigned)len, ifp); |
133 | 11.9k | if (!strncasecmp(imCommon.firmware, "Firmware Version", 16)) |
134 | 1.76k | memmove(imCommon.firmware, imCommon.firmware + 16, strlen(imCommon.firmware) - 15); |
135 | 11.9k | trimSpaces(imCommon.firmware); |
136 | | |
137 | 1.33M | } else if (type == 0x1810) |
138 | 4.47k | { |
139 | 4.47k | width = get4(); |
140 | 4.47k | height = get4(); |
141 | 4.47k | pixel_aspect = int_to_float(get4()); |
142 | 4.47k | flip = get4(); |
143 | 4.47k | } |
144 | 1.32M | else if (type == 0x1835) |
145 | 1.80k | { /* Get the decoder table */ |
146 | 1.80k | tiff_compress = get4(); |
147 | 1.80k | } |
148 | 1.32M | else if (type == 0x2007) |
149 | 1.89k | { |
150 | 1.89k | thumb_offset = see; |
151 | 1.89k | thumb_length = len; |
152 | 1.89k | } |
153 | 1.32M | else if (type == 0x1818) |
154 | 10.4k | { |
155 | 10.4k | shutter = libraw_powf64l(2.0f, -int_to_float((get4(), get4()))); |
156 | 10.4k | ilm.CurAp = aperture = libraw_powf64l(2.0f, int_to_float(get4()) / 2); |
157 | 10.4k | } |
158 | 1.31M | else if (type == 0x102a) // CanonShotInfo |
159 | 62.9k | { |
160 | | // iso_speed = pow (2.0, (get4(),get2())/32.0 - 4) * 50; |
161 | 62.9k | get2(); // skip one |
162 | 62.9k | iso_speed = |
163 | 62.9k | libraw_powf64l(2.0f, (get2() + get2()) / 32.0f - 5.0f) * 100.0f; |
164 | 62.9k | ilm.CurAp = aperture = _CanonConvertAperture((get2(), get2())); |
165 | 62.9k | shutter = libraw_powf64l(2.0f, -float((short)get2()) / 32.f); |
166 | 62.9k | imCanon.wbi = wbi = (get2(), get2()); |
167 | 62.9k | if (wbi >= (int)Canon_wbi2std.size()) |
168 | 21.9k | wbi = 0; |
169 | 62.9k | fseek(ifp, 32, SEEK_CUR); |
170 | 62.9k | if (shutter > 1e6) |
171 | 2.20k | shutter = float(get2()) / 10.f; |
172 | 62.9k | } |
173 | 1.25M | else if (type == 0x102c) // CanonColorInfo2 / Appendix A: Pro90IS, G1, G2, S30, S40 |
174 | 17.1k | { |
175 | 17.1k | int CanonColorInfo2_type = get2(); // G1 1028, G2 272, Pro90 IS 769, S30 274, S40 273, EOS D30 276 |
176 | 17.1k | if (CanonColorInfo2_type > 512) { /* Pro90 IS, G1 */ |
177 | 5.39k | fseek(ifp, 118, SEEK_CUR); |
178 | 21.5k | FORC4 cam_mul[BG2RG1_2_RGBG(c)] = get2(); |
179 | 5.39k | } |
180 | 11.7k | else if (CanonColorInfo2_type != 276) { /* G2, S30, S40 */ |
181 | 9.45k | Appendix_A = 1; |
182 | 9.45k | WB_table_offset = -14; |
183 | 9.45k | fseek(ifp, 98, SEEK_CUR); |
184 | 37.8k | FORC4 cam_mul[GRBG_2_RGBG(c)] = get2(); |
185 | 9.45k | if (cam_mul[0] > 0.001f) Got_AsShotWB = 1; |
186 | 9.45k | } |
187 | 17.1k | } |
188 | 1.23M | else if (type == 0x10a9) // ColorBalance: Canon D60, 10D, 300D, and clones |
189 | 24.5k | { |
190 | 24.5k | int bls = 0; |
191 | | /* |
192 | | int table[] = { |
193 | | LIBRAW_WBI_Auto, // 0 |
194 | | LIBRAW_WBI_Daylight, // 1 |
195 | | LIBRAW_WBI_Cloudy, // 2 |
196 | | LIBRAW_WBI_Tungsten, // 3 |
197 | | LIBRAW_WBI_FL_W, // 4 |
198 | | LIBRAW_WBI_Flash, // 5 |
199 | | LIBRAW_WBI_Custom, // 6, absent in Canon D60 |
200 | | LIBRAW_WBI_Auto, // 7, use this if camera is set to b/w JPEG |
201 | | LIBRAW_WBI_Shade, // 8 |
202 | | LIBRAW_WBI_Kelvin // 9, absent in Canon D60 |
203 | | }; |
204 | | */ |
205 | 24.5k | int nWB = |
206 | 24.5k | ((get2() - 2) / 8) - |
207 | 24.5k | 1; // 2 bytes this, N recs 4*2bytes each, last rec is black level |
208 | 24.5k | if (nWB) |
209 | 85.5k | FORC4 icWBC[LIBRAW_WBI_Auto][RGGB_2_RGBG(c)] = get2(); |
210 | 24.5k | if (nWB >= 7) |
211 | 18.5k | Canon_WBpresets(0, 0); |
212 | 5.94k | else |
213 | 23.7k | FORC4 cam_mul[c] = float(icWBC[LIBRAW_WBI_Auto][c]); |
214 | 24.5k | if (nWB == 7) // mostly Canon EOS D60 + some fw#s for 300D; |
215 | | // check for 0x1668000 is unreliable |
216 | 11.5k | { |
217 | 11.5k | if ((wbi >= 0) && (wbi < 9) && (wbi != 6)) |
218 | 2.83k | { |
219 | 11.3k | FORC4 cam_mul[c] = float(icWBC[Canon_wbi2std[wbi]][c]); |
220 | 2.83k | } |
221 | 8.74k | else |
222 | 8.74k | { |
223 | 34.9k | FORC4 cam_mul[c] = float(icWBC[LIBRAW_WBI_Auto][c]); |
224 | 8.74k | } |
225 | 11.5k | } |
226 | 12.9k | else if (nWB == 9) // Canon 10D, 300D |
227 | 6.41k | { |
228 | 25.6k | FORC4 icWBC[LIBRAW_WBI_Custom][RGGB_2_RGBG(c)] = get2(); |
229 | 25.6k | FORC4 icWBC[LIBRAW_WBI_Kelvin][RGGB_2_RGBG(c)] = get2(); |
230 | 6.41k | if ((wbi >= 0) && (wbi < 10)) |
231 | 3.65k | { |
232 | 14.6k | FORC4 cam_mul[c] = float(icWBC[Canon_wbi2std[wbi]][c]); |
233 | 3.65k | } |
234 | 2.75k | else |
235 | 2.75k | { |
236 | 11.0k | FORC4 cam_mul[c] = float(icWBC[LIBRAW_WBI_Auto][c]); |
237 | 2.75k | } |
238 | 6.41k | } |
239 | 24.5k | FORC4 |
240 | 98.1k | bls += (imCanon.ChannelBlackLevel[RGGB_2_RGBG(c)] = get2()); |
241 | 24.5k | imCanon.AverageBlackLevel = bls / 4; |
242 | 24.5k | } |
243 | 1.21M | else if (type == 0x102d) |
244 | 8.75k | { |
245 | 8.75k | Canon_CameraSettings(len >> 1); |
246 | 8.75k | } |
247 | | |
248 | 1.20M | else if (type == 0x10b4) { |
249 | 10.9k | switch (get2()) { |
250 | 1.88k | case 1: |
251 | 1.88k | imCommon.ColorSpace = LIBRAW_COLORSPACE_sRGB; |
252 | 1.88k | break; |
253 | 2.99k | case 2: |
254 | 2.99k | imCommon.ColorSpace = LIBRAW_COLORSPACE_AdobeRGB; |
255 | 2.99k | break; |
256 | 6.08k | default: |
257 | 6.08k | imCommon.ColorSpace = LIBRAW_COLORSPACE_Unknown; |
258 | 6.08k | break; |
259 | 10.9k | } |
260 | | |
261 | 1.19M | } else if (type == 0x580b) |
262 | 3.24k | { |
263 | 3.24k | if (strcmp(model, "Canon EOS D30")) |
264 | 3.24k | sprintf(imgdata.shootinginfo.BodySerial, "%d", len); |
265 | 0 | else |
266 | 0 | sprintf(imgdata.shootinginfo.BodySerial, "%0x-%05d", len >> 16, |
267 | 0 | len & 0xffff); |
268 | 3.24k | } |
269 | 1.18M | else if (type == 0x0032) // CanonColorInfo1 |
270 | 55.7k | { |
271 | 55.7k | if (len == 768) { // EOS D30 |
272 | | |
273 | 12.5k | ushort q; |
274 | 12.5k | fseek(ifp, 4, SEEK_CUR); |
275 | 87.6k | for (unsigned linenum = 0; linenum < Canon_D30_linenums_2_StdWBi.size(); linenum++) { |
276 | 75.1k | if (Canon_D30_linenums_2_StdWBi[linenum] != LIBRAW_WBI_Unknown) { |
277 | 300k | FORC4 { |
278 | 300k | q = get2(); |
279 | 300k | icWBC[Canon_D30_linenums_2_StdWBi[linenum]][RGGB_2_RGBG(c)] = |
280 | 300k | (int)(roundf(1024000.0f / (float)MAX(1, q))); |
281 | 300k | } |
282 | | // if (Canon_wbi2std[imCanon.wbi] == *(Canon_D30_linenums_2_StdWBi + linenum)) { |
283 | | // FORC4 cam_mul[c] = icWBC[*(Canon_D30_linenums_2_StdWBi + linenum)][c]; |
284 | | // Got_AsShotWB = 1; |
285 | | // } |
286 | 75.1k | } |
287 | 75.1k | } |
288 | 12.5k | fseek (ifp, 68-int(Canon_D30_linenums_2_StdWBi.size())*8, SEEK_CUR); |
289 | | |
290 | 50.1k | FORC4 { |
291 | 50.1k | q = get2(); |
292 | 50.1k | cam_mul[RGGB_2_RGBG(c)] = 1024.f / float(MAX(1, q)); |
293 | 50.1k | } |
294 | 12.5k | if (!wbi) |
295 | 8.91k | cam_mul[0] = -1; // use my auto white balance |
296 | | |
297 | 12.5k | } |
298 | 43.2k | else if ((cam_mul[0] <= 0.001f) || // Pro1, G3, G5, G6, S45, S50, S60, S70 |
299 | 12.4k | Appendix_A) // G2, S30, S40 |
300 | 35.5k | { |
301 | 35.5k | libraw_static_table_t linenums_2_StdWBi; |
302 | 35.5k | unsigned AsShotWB_linenum = Canon_wbi2std.size(); |
303 | | |
304 | 35.5k | CanonColorInfo1_key = get2(); |
305 | 35.5k | if ((CanonColorInfo1_key == key[0]) && (len == 2048)) { // Pro1 |
306 | 6.61k | linenums_2_StdWBi = Canon_KeyIs0x0410_Len2048_linenums_2_StdWBi; |
307 | 6.61k | WB_table_offset = 8; |
308 | | |
309 | 28.8k | } else if ((CanonColorInfo1_key == key[0]) && (len == 3072)) { // S60, S70, G6 |
310 | 5.74k | linenums_2_StdWBi = Canon_KeyIs0x0410_Len3072_linenums_2_StdWBi; |
311 | 5.74k | WB_table_offset = 16; |
312 | | |
313 | 23.1k | } else if (!CanonColorInfo1_key && (len == 2048)) { // G2, S30, S40; S45, S50, G3, G5 |
314 | 7.63k | key[0] = key[1] = 0; |
315 | 7.63k | linenums_2_StdWBi = Canon_KeyIsZero_Len2048_linenums_2_StdWBi; |
316 | 7.63k | if (atof(imCommon.firmware) < 1.02f) |
317 | 7.63k | UseWBfromTable_as_AsShot = 0; |
318 | | |
319 | 15.5k | } else goto next_tag; |
320 | | |
321 | 19.9k | if ((Canon_wbi2std[wbi] == LIBRAW_WBI_Auto) || |
322 | 10.4k | (Canon_wbi2std[wbi] == LIBRAW_WBI_Unknown) || |
323 | 8.90k | Got_AsShotWB) |
324 | 12.3k | UseWBfromTable_as_AsShot = 0; |
325 | | |
326 | 19.9k | if (UseWBfromTable_as_AsShot) { |
327 | 4.41k | int temp_wbi; |
328 | 4.41k | if (Canon_wbi2std[wbi] == LIBRAW_WBI_Custom) temp_wbi = LIBRAW_WBI_Daylight; |
329 | 3.50k | else temp_wbi = wbi; |
330 | 40.7k | for (AsShotWB_linenum = 0; AsShotWB_linenum < linenums_2_StdWBi.size(); AsShotWB_linenum++) { |
331 | 37.6k | if (Canon_wbi2std[temp_wbi] == linenums_2_StdWBi[AsShotWB_linenum]) { |
332 | 1.33k | break; |
333 | 1.33k | } |
334 | 37.6k | } |
335 | 4.41k | } |
336 | | |
337 | 19.9k | fseek (ifp, 78LL+WB_table_offset, SEEK_CUR); |
338 | 217k | for (unsigned linenum = 0; linenum < linenums_2_StdWBi.size(); linenum++) { |
339 | 197k | if (linenums_2_StdWBi[linenum] != LIBRAW_WBI_Unknown) { |
340 | 605k | FORC4 icWBC[linenums_2_StdWBi[linenum]][GRBG_2_RGBG(c)] = get2() ^ key[c & 1]; |
341 | 151k | if (UseWBfromTable_as_AsShot && (AsShotWB_linenum == linenum)) { |
342 | 5.34k | FORC4 cam_mul[c] = float(icWBC[linenums_2_StdWBi[linenum]][c]); |
343 | 1.33k | Got_AsShotWB = 1; |
344 | 1.33k | } |
345 | 151k | } else { |
346 | 45.5k | fseek(ifp, 8, SEEK_CUR); |
347 | 45.5k | } |
348 | 197k | } |
349 | 19.9k | if (!Got_AsShotWB) |
350 | 15.6k | cam_mul[0] = -1; |
351 | 19.9k | } |
352 | 55.7k | } |
353 | 1.13M | else if (type == 0x1030 && wbi >= 0 && (0x18040 >> wbi & 1)) |
354 | 15.1k | { |
355 | 15.1k | ciff_block_1030(); // all that don't have 0x10a9 |
356 | 15.1k | } |
357 | 1.11M | else if (type == 0x1031) |
358 | 4.33k | { |
359 | 4.33k | raw_width = imCanon.SensorWidth = (get2(), get2()); |
360 | 4.33k | raw_height = imCanon.SensorHeight = get2(); |
361 | 4.33k | fseek(ifp, 4, SEEK_CUR); |
362 | 4.33k | imCanon.DefaultCropAbsolute = get_CanonArea(); |
363 | 4.33k | imCanon.LeftOpticalBlack = get_CanonArea(); |
364 | 4.33k | } |
365 | 1.11M | else if (type == 0x501c) |
366 | 3.31k | { |
367 | 3.31k | iso_speed = float(len & 0xffff); |
368 | 3.31k | } |
369 | 1.10M | else if (type == 0x5029) |
370 | 10.3k | { |
371 | 10.3k | ilm.CurFocal = float( len >> 16); |
372 | 10.3k | ilm.FocalType = len & 0xffff; |
373 | 10.3k | if (ilm.FocalType == LIBRAW_FT_ZOOM_LENS) |
374 | 3.40k | { |
375 | 3.40k | ilm.FocalUnits = 32; |
376 | 3.40k | if (ilm.FocalUnits > 1) |
377 | 3.40k | ilm.CurFocal /= (float)ilm.FocalUnits; |
378 | 3.40k | } |
379 | 10.3k | focal_len = ilm.CurFocal; |
380 | 10.3k | } |
381 | 1.09M | else if (type == 0x5813) |
382 | 5.04k | { |
383 | 5.04k | flash_used = int_to_float(len); |
384 | 5.04k | } |
385 | 1.09M | else if (type == 0x5814) |
386 | 3.79k | { |
387 | 3.79k | canon_ev = int_to_float(len); |
388 | 3.79k | } |
389 | 1.09M | else if (type == 0x5817) |
390 | 2.41k | { |
391 | 2.41k | shot_order = len; |
392 | 2.41k | } |
393 | 1.08M | else if (type == 0x5834) |
394 | 5.98k | { |
395 | 5.98k | unique_id = ((unsigned long long)len << 32) >> 32; |
396 | 5.98k | setCanonBodyFeatures(unique_id); |
397 | 5.98k | } |
398 | 1.08M | else if (type == 0x580e) |
399 | 1.66k | { |
400 | 1.66k | timestamp = len; |
401 | 1.66k | } |
402 | 1.08M | else if (type == 0x180e) |
403 | 888 | { |
404 | 888 | timestamp = get4(); |
405 | 888 | } |
406 | | |
407 | 1.37M | next_tag:; |
408 | | #ifdef LOCALTIME |
409 | | if ((type | 0x4000) == 0x580e) |
410 | | timestamp = mktime(gmtime(×tamp)); |
411 | | #endif |
412 | 1.36M | fseek(ifp, save, SEEK_SET); |
413 | 1.36M | } |
414 | 138k | } |