/src/libraw/src/metadata/kodak.cpp
Line | Count | Source |
1 | | /* -*- C++ -*- |
2 | | * Copyright 2019-2025 LibRaw LLC (info@libraw.org) |
3 | | * |
4 | | LibRaw is free software; you can redistribute it and/or modify |
5 | | it under the terms of the one of two licenses as you choose: |
6 | | |
7 | | 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1 |
8 | | (See file LICENSE.LGPL provided in LibRaw distribution archive for details). |
9 | | |
10 | | 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0 |
11 | | (See file LICENSE.CDDL provided in LibRaw distribution archive for details). |
12 | | |
13 | | */ |
14 | | |
15 | | #include "../../internal/dcraw_defs.h" |
16 | | |
17 | | void LibRaw::Kodak_KDC_WBtags(int wb, int wbi) |
18 | 4.34k | { |
19 | 4.34k | int c; |
20 | 13.0k | FORC3 icWBC[wb][c] = get4(); |
21 | 4.34k | icWBC[wb][3] = icWBC[wb][1]; |
22 | 4.34k | if (wbi == wb) |
23 | 1.76k | FORC4 cam_mul[c] = float(icWBC[wb][c]); |
24 | 4.34k | return; |
25 | 4.34k | } |
26 | | |
27 | | void LibRaw::Kodak_DCR_WBtags(int wb, unsigned type, int wbi) |
28 | 3.44k | { |
29 | 3.44k | float mul[3] = {1.0f, 1.0f, 1.0f}, num, mul2; |
30 | 3.44k | int c; |
31 | 10.3k | FORC3 mul[c] = (num = getrealf(type)) <= 0.001f ? 1.0f : num; |
32 | 3.44k | icWBC[wb][1] = icWBC[wb][3] = int(mul[1]); |
33 | 3.44k | mul2 = mul[1] * mul[1]; |
34 | 3.44k | icWBC[wb][0] = int(mul2 / mul[0]); |
35 | 3.44k | icWBC[wb][2] = int(mul2 / mul[2]); |
36 | 3.44k | if (wbi == wb) |
37 | 4.44k | FORC4 cam_mul[c] = float(icWBC[wb][c]); |
38 | 3.44k | return; |
39 | 3.44k | } |
40 | | |
41 | | short LibRaw::KodakIllumMatrix(unsigned type, float *romm_camIllum) |
42 | 4.60k | { |
43 | 4.60k | int c, j, romm_camTemp[9], romm_camScale[3]; |
44 | 4.60k | if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_SRATIONAL)) |
45 | 160 | { |
46 | 1.60k | for (j = 0; j < 9; j++) |
47 | 1.44k | ((float *)romm_camIllum)[j] = getrealf(type); |
48 | 160 | return 1; |
49 | 160 | } |
50 | 4.44k | else if (tagtypeIs(LIBRAW_EXIFTAG_TYPE_SLONG)) |
51 | 2.84k | { |
52 | 2.84k | FORC3 |
53 | 8.53k | { |
54 | 8.53k | romm_camScale[c] = 0; |
55 | 34.1k | for (j = 0; j < 3; j++) |
56 | 25.5k | { |
57 | 25.5k | romm_camTemp[c * 3 + j] = get4(); |
58 | 25.5k | romm_camScale[c] += romm_camTemp[c * 3 + j]; |
59 | 25.5k | } |
60 | 8.53k | } |
61 | 2.84k | if ((romm_camScale[0] > 0x1fff) && (romm_camScale[1] > 0x1fff) && |
62 | 1.23k | (romm_camScale[2] > 0x1fff)) |
63 | 978 | { |
64 | 11.7k | FORC3 for (j = 0; j < 3; j++)((float *)romm_camIllum)[c * 3 + j] = |
65 | 8.80k | ((float)romm_camTemp[c * 3 + j]) / ((float)romm_camScale[c]); |
66 | 978 | return 1; |
67 | 978 | } |
68 | 2.84k | } |
69 | 3.46k | return 0; |
70 | 4.60k | } |
71 | | |
72 | | /* Thanks to Alexey Danilchenko for wb as-shot parsing code */ |
73 | | void LibRaw::parse_kodak_ifd(INT64 base) |
74 | 12.5k | { |
75 | 12.5k | unsigned entries, tag, type, len; |
76 | 12.5k | INT64 save; |
77 | 12.5k | int c, wbi = -1; |
78 | | |
79 | 12.5k | static const int wbtag_kdc[] = { |
80 | 12.5k | LIBRAW_WBI_Auto, // 64037 / 0xfa25 |
81 | 12.5k | LIBRAW_WBI_Fluorescent, // 64040 / 0xfa28 |
82 | 12.5k | LIBRAW_WBI_Tungsten, // 64039 / 0xfa27 |
83 | 12.5k | LIBRAW_WBI_Daylight, // 64041 / 0xfa29 |
84 | 12.5k | -1, |
85 | 12.5k | -1, |
86 | 12.5k | LIBRAW_WBI_Shade // 64042 / 0xfa2a |
87 | 12.5k | }; |
88 | | |
89 | 12.5k | static const int wbtag_dcr[] = { |
90 | 12.5k | LIBRAW_WBI_Daylight, // 2120 / 0x0848 |
91 | 12.5k | LIBRAW_WBI_Tungsten, // 2121 / 0x0849 |
92 | 12.5k | LIBRAW_WBI_Fluorescent, // 2122 / 0x084a |
93 | 12.5k | LIBRAW_WBI_Flash, // 2123 / 0x084b |
94 | 12.5k | LIBRAW_WBI_Custom, // 2124 / 0x084c |
95 | 12.5k | LIBRAW_WBI_Auto // 2125 / 0x084d |
96 | 12.5k | }; |
97 | | |
98 | | // int a_blck = 0; |
99 | | |
100 | 12.5k | entries = get2(); |
101 | 12.5k | if (entries > 1024) |
102 | 4.22k | return; |
103 | 8.36k | INT64 fsize = ifp->size(); |
104 | 1.27M | while (entries--) |
105 | 1.26M | { |
106 | 1.26M | tiff_get(base, &tag, &type, &len, &save); |
107 | 1.26M | INT64 savepos = ftell(ifp); |
108 | 1.26M | if (len > 8 && len + savepos > 2 * fsize) |
109 | 1.00M | { |
110 | 1.00M | fseek(ifp, save, SEEK_SET); // Recover tiff-read position!! |
111 | 1.00M | continue; |
112 | 1.00M | } |
113 | 262k | if (callbacks.exif_cb) |
114 | 0 | { |
115 | 0 | callbacks.exif_cb(callbacks.exifparser_data, tag | 0x20000, type, len, |
116 | 0 | order, ifp, base); |
117 | 0 | fseek(ifp, savepos, SEEK_SET); |
118 | 0 | } |
119 | 262k | if (tag == 0x03eb) // 1003 |
120 | 154 | imgdata.sizes.raw_inset_crops[0].cleft = get2(); |
121 | 262k | else if (tag == 0x03ec) // 1004 |
122 | 294 | imgdata.sizes.raw_inset_crops[0].ctop = get2(); |
123 | 262k | else if (tag == 0x03ed) // 1005 |
124 | 35 | imgdata.sizes.raw_inset_crops[0].cwidth = get2(); |
125 | 262k | else if (tag == 0x03ee) // 1006 |
126 | 84 | imgdata.sizes.raw_inset_crops[0].cheight = get2(); |
127 | 261k | else if (tag == 0x03ef) // 1007 |
128 | 288 | { |
129 | 288 | if (!strcmp(model, "EOS D2000C")) |
130 | 36 | black = get2(); |
131 | 252 | else |
132 | 252 | imKodak.BlackLevelTop = get2(); |
133 | 288 | } |
134 | 261k | else if (tag == 0x03f0) // 1008 |
135 | 432 | { |
136 | 432 | if (!strcmp(model, "EOS D2000C")) |
137 | 80 | { |
138 | 80 | if (black) // already set by tag 1007 (0x03ef) |
139 | 10 | black = (black + get2()) / 2; |
140 | 70 | else |
141 | 70 | black = get2(); |
142 | 80 | } |
143 | 352 | else |
144 | 352 | imKodak.BlackLevelBottom = get2(); |
145 | 432 | } |
146 | | |
147 | 261k | else if (tag == 0x03f1) |
148 | 2.36k | { // 1009 Kodak TextualInfo |
149 | 2.36k | if (len > 0) |
150 | 1.90k | { |
151 | 1.90k | char kti[1024]; |
152 | 1.90k | char *pkti; |
153 | 1.90k | int nsym = MIN(len, 1023); |
154 | 1.90k | fread(kti, 1, nsym, ifp); |
155 | 1.90k | kti[nsym] = 0; |
156 | | #ifdef LIBRAW_WIN32_CALLS |
157 | | pkti = strtok(kti, "\x0a"); |
158 | | #else |
159 | 1.90k | char *last = 0; |
160 | 1.90k | pkti = strtok_r(kti, "\x0a", &last); |
161 | 1.90k | #endif |
162 | 4.76k | while (pkti != NULL) |
163 | 2.86k | { |
164 | 2.86k | c = 12; |
165 | 2.86k | if (((int)strlen(pkti) > c) && (!strncasecmp(pkti, "Camera body:", c))) |
166 | 295 | { |
167 | 547 | while ((pkti[c] == ' ') && (c < (int)strlen(pkti))) |
168 | 252 | { |
169 | 252 | c++; |
170 | 252 | } |
171 | 295 | strcpy(ilm.body, pkti + c); |
172 | 295 | } |
173 | 2.86k | c = 5; |
174 | 2.86k | if (((int)strlen(pkti) > c) && (!strncasecmp(pkti, "Lens:", c))) |
175 | 103 | { |
176 | 103 | ilm.CurFocal = float(atoi(pkti + c)); |
177 | 103 | } |
178 | 2.86k | c = 9; |
179 | 2.86k | if (((int)strlen(pkti) > c) && (!strncasecmp(pkti, "Aperture:", c))) |
180 | 220 | { |
181 | 945 | while (((pkti[c] == ' ') || (pkti[c] == 'f')) && (c < (int)strlen(pkti))) |
182 | 725 | { |
183 | 725 | c++; |
184 | 725 | } |
185 | 220 | ilm.CurAp = float(atof(pkti + c)); |
186 | 220 | } |
187 | 2.86k | c = 10; |
188 | 2.86k | if (((int)strlen(pkti) > c) && (!strncasecmp(pkti, "ISO Speed:", c))) |
189 | 235 | { |
190 | 235 | iso_speed = float(atoi(pkti + c)); |
191 | 235 | } |
192 | 2.86k | c = 13; |
193 | 2.86k | if (((int)strlen(pkti) > c) && (!strncasecmp(pkti, "Focal Length:", c))) |
194 | 217 | { |
195 | 217 | ilm.CurFocal = float(atoi(pkti + c)); |
196 | 217 | } |
197 | 2.86k | c = 13; |
198 | 2.86k | if (((int)strlen(pkti) > c) && (!strncasecmp(pkti, "Max Aperture:", c))) |
199 | 99 | { |
200 | 794 | while (((pkti[c] == ' ') || (pkti[c] == 'f')) && (c < (int)strlen(pkti))) |
201 | 695 | { |
202 | 695 | c++; |
203 | 695 | } |
204 | 99 | ilm.MaxAp4CurFocal = float(atof(pkti + c)); |
205 | 99 | } |
206 | 2.86k | c = 13; |
207 | 2.86k | if (((int)strlen(pkti) > c) && (!strncasecmp(pkti, "Min Aperture:", c))) |
208 | 187 | { |
209 | 414 | while (((pkti[c] == ' ') || (pkti[c] == 'f')) && (c < (int)strlen(pkti))) |
210 | 227 | { |
211 | 227 | c++; |
212 | 227 | } |
213 | 187 | ilm.MinAp4CurFocal = float(atof(pkti + c)); |
214 | 187 | } |
215 | | #ifdef LIBRAW_WIN32_CALLS |
216 | | pkti = strtok(NULL, "\x0a"); |
217 | | #else |
218 | 2.86k | pkti = strtok_r(NULL, "\x0a", &last); |
219 | 2.86k | #endif |
220 | 2.86k | } |
221 | 1.90k | } |
222 | 2.36k | } |
223 | | |
224 | 258k | else if (tag == 0x03f3) // 1011 |
225 | 127 | imCommon.FlashEC = getrealf(type); |
226 | | |
227 | 258k | else if (tag == 0x03fc) // 1020 |
228 | 1.44k | { |
229 | 1.44k | wbi = getint(type); |
230 | 1.44k | if ((wbi >= 0) && (wbi < 6) && (wbi != -2)) |
231 | 400 | wbi = wbtag_dcr[wbi]; |
232 | 1.44k | } |
233 | 257k | else if (tag == 0x03fd && len == 72) // 1021 |
234 | 317 | { /* WB set in software */ |
235 | 317 | fseek(ifp, 40, SEEK_CUR); |
236 | 951 | FORC3 cam_mul[c] = 2048.0f / fMAX(1.0f, get2()); |
237 | 317 | wbi = -2; |
238 | 317 | } |
239 | | |
240 | 256k | else if ((tag == 0x0406) && (len == 1)) // 1030 |
241 | 234 | imCommon.CameraTemperature = getrealf(type); |
242 | 256k | else if ((tag == 0x0413) && (len == 1)) // 1043 |
243 | 131 | imCommon.SensorTemperature = getrealf(type); |
244 | 256k | else if (tag == 0x0848) // 2120 |
245 | 254 | Kodak_DCR_WBtags(LIBRAW_WBI_Daylight, type, wbi); |
246 | 256k | else if (tag == 0x0849) // 2121 |
247 | 294 | Kodak_DCR_WBtags(LIBRAW_WBI_Tungsten, type, wbi); |
248 | 256k | else if (tag == 0x084a) // 2122 |
249 | 245 | Kodak_DCR_WBtags(LIBRAW_WBI_Fluorescent, type, wbi); |
250 | 255k | else if (tag == 0x084b) // 2123 |
251 | 822 | Kodak_DCR_WBtags(LIBRAW_WBI_Flash, type, wbi); |
252 | 254k | else if (tag == 0x084c) // 2124 |
253 | 559 | Kodak_DCR_WBtags(LIBRAW_WBI_Custom, type, wbi); |
254 | 254k | else if (tag == 0x084d) // 2125 |
255 | 1.27k | { |
256 | 1.27k | if (wbi == -1) |
257 | 559 | wbi = LIBRAW_WBI_Auto; |
258 | 1.27k | Kodak_DCR_WBtags(LIBRAW_WBI_Auto, type, wbi); |
259 | 1.27k | } |
260 | 253k | else if (tag == 0x089f) // 2207 |
261 | 96 | imKodak.ISOCalibrationGain = getrealf(type); |
262 | 253k | else if (tag == 0x0903) // 2307 |
263 | 254 | imKodak.AnalogISO = iso_speed = getrealf(type); |
264 | 252k | else if (tag == 0x090d) // 2317 |
265 | 71 | linear_table(len); |
266 | 252k | else if (tag == 0x09ce) // 2510 |
267 | 649 | stmread(imgdata.shootinginfo.InternalBodySerial, len, ifp); |
268 | 252k | else if (tag == 0x0e92) // 3730 |
269 | 88 | { |
270 | 88 | imKodak.val018percent = get2(); |
271 | 88 | imgdata.color.linear_max[0] = imgdata.color.linear_max[1] = |
272 | 88 | imgdata.color.linear_max[2] = imgdata.color.linear_max[3] = |
273 | 88 | (int)(((float)imKodak.val018percent) / 18.0f * 170.0f); |
274 | 88 | } |
275 | 251k | else if (tag == 0x0e93) // 3731 |
276 | 130 | imgdata.color.linear_max[0] = imgdata.color.linear_max[1] = |
277 | 130 | imgdata.color.linear_max[2] = imgdata.color.linear_max[3] = |
278 | 130 | imKodak.val170percent = get2(); |
279 | 251k | else if (tag == 0x0e94) // 3732 |
280 | 220 | imKodak.val100percent = get2(); |
281 | | /* |
282 | | else if (tag == 0x1784) // 6020 |
283 | | iso_speed = getint(type); |
284 | | */ |
285 | 251k | else if (tag == 0xfa00) // 64000 |
286 | 749 | stmread(imgdata.shootinginfo.BodySerial, len, ifp); |
287 | 250k | else if (tag == 0xfa0d) // 64013 |
288 | 1.32k | { |
289 | 1.32k | wbi = fgetc(ifp); |
290 | 1.32k | if ((wbi >= 0) && (wbi < 7)) |
291 | 750 | wbi = wbtag_kdc[wbi]; |
292 | 1.32k | } |
293 | 249k | else if (tag == 0xfa13) // 64019 |
294 | 1.28k | width = getint(type); |
295 | 248k | else if (tag == 0xfa14) // 64020 |
296 | 297 | height = (getint(type) + 1) & -2; |
297 | | /* |
298 | | height = getint(type); |
299 | | |
300 | | else if (tag == 0xfa16) // 64022 |
301 | | raw_width = get2(); |
302 | | else if (tag == 0xfa17) // 64023 |
303 | | raw_height = get2(); |
304 | | */ |
305 | 247k | else if (tag == 0xfa18) // 64024 |
306 | 410 | { |
307 | 410 | imKodak.offset_left = getint(LIBRAW_EXIFTAG_TYPE_SSHORT); |
308 | 410 | if (type != LIBRAW_EXIFTAG_TYPE_SSHORT) |
309 | 183 | imKodak.offset_left += 1; |
310 | 410 | } |
311 | 247k | else if (tag == 0xfa19) // 64025 |
312 | 644 | { |
313 | 644 | imKodak.offset_top = getint(LIBRAW_EXIFTAG_TYPE_SSHORT); |
314 | 644 | if (type != LIBRAW_EXIFTAG_TYPE_SSHORT) |
315 | 606 | imKodak.offset_top += 1; |
316 | 644 | } |
317 | | |
318 | 246k | else if (tag == 0xfa25) // 64037 |
319 | 730 | Kodak_KDC_WBtags(LIBRAW_WBI_Auto, wbi); |
320 | 246k | else if (tag == 0xfa27) // 64039 |
321 | 377 | Kodak_KDC_WBtags(LIBRAW_WBI_Tungsten, wbi); |
322 | 245k | else if (tag == 0xfa28) // 64040 |
323 | 960 | Kodak_KDC_WBtags(LIBRAW_WBI_Fluorescent, wbi); |
324 | 244k | else if (tag == 0xfa29) // 64041 |
325 | 612 | Kodak_KDC_WBtags(LIBRAW_WBI_Daylight, wbi); |
326 | 244k | else if (tag == 0xfa2a) // 64042 |
327 | 1.66k | Kodak_KDC_WBtags(LIBRAW_WBI_Shade, wbi); |
328 | | |
329 | 242k | else if (tag == 0xfa31) // 64049 |
330 | 1.26k | imgdata.sizes.raw_inset_crops[0].cwidth = get2(); |
331 | 241k | else if (tag == 0xfa32) // 64050 |
332 | 612 | imgdata.sizes.raw_inset_crops[0].cheight = get2(); |
333 | 240k | else if (tag == 0xfa3e) // 64062 |
334 | 497 | imgdata.sizes.raw_inset_crops[0].cleft = get2(); |
335 | 240k | else if (tag == 0xfa3f) // 64063 |
336 | 1.47k | imgdata.sizes.raw_inset_crops[0].ctop = get2(); |
337 | | |
338 | 238k | else if (((tag == 0x07e4) || (tag == 0xfb01)) && |
339 | 1.89k | (len == 9)) // 2020 or 64257 |
340 | 913 | { |
341 | 913 | if (KodakIllumMatrix(type, (float *)imKodak.romm_camDaylight)) |
342 | 472 | { |
343 | 472 | romm_coeff(imKodak.romm_camDaylight); |
344 | 472 | } |
345 | 913 | } |
346 | 237k | else if (((tag == 0x07e5) || (tag == 0xfb02)) && |
347 | 788 | (len == 9)) // 2021 or 64258 |
348 | 653 | KodakIllumMatrix(type, (float *)imKodak.romm_camTungsten); |
349 | 237k | else if (((tag == 0x07e6) || (tag == 0xfb03)) && |
350 | 1.28k | (len == 9)) // 2022 or 64259 |
351 | 960 | KodakIllumMatrix(type, (float *)imKodak.romm_camFluorescent); |
352 | 236k | else if (((tag == 0x07e7) || (tag == 0xfb04)) && |
353 | 988 | (len == 9)) // 2023 or 64260 |
354 | 495 | KodakIllumMatrix(type, (float *)imKodak.romm_camFlash); |
355 | 235k | else if (((tag == 0x07e8) || (tag == 0xfb05)) && |
356 | 1.27k | (len == 9)) // 2024 or 64261 |
357 | 823 | KodakIllumMatrix(type, (float *)imKodak.romm_camCustom); |
358 | 234k | else if (((tag == 0x07e9) || (tag == 0xfb06)) && |
359 | 1.28k | (len == 9)) // 2025 or 64262 |
360 | 759 | KodakIllumMatrix(type, (float *)imKodak.romm_camAuto); |
361 | | |
362 | 262k | fseek(ifp, save, SEEK_SET); |
363 | 262k | } |
364 | 8.36k | } |