1 /* -*- C++ -*-
2  * Copyright 2019-2020 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 
parseAdobeRAFMakernote()21 void LibRaw::parseAdobeRAFMakernote()
22 {
23 
24   uchar *PrivateMknBuf;
25   unsigned posPrivateMknBuf;
26   unsigned PrivateMknLength;
27   unsigned PrivateOrder;
28   unsigned PrivateEntries, PrivateTagID;
29   unsigned PrivateTagBytes;
30   unsigned wb_section_offset = 0;
31   int posWB;
32   int c;
33 
34 #define CHECKSPACE(s)                                                          \
35   if (posPrivateMknBuf + (s) > PrivateMknLength)                               \
36   {                                                                            \
37     free(PrivateMknBuf);                                                       \
38     return;                                                                    \
39   }
40 #define isWB(posWB)                                                            \
41   sget2(posWB) != 0 && sget2(posWB + 2) != 0 && sget2(posWB + 4) != 0 &&       \
42       sget2(posWB + 6) != 0 && sget2(posWB + 8) != 0 &&                        \
43       sget2(posWB + 10) != 0 && sget2(posWB) != 0xff &&                        \
44       sget2(posWB + 2) != 0xff && sget2(posWB + 4) != 0xff &&                  \
45       sget2(posWB + 6) != 0xff && sget2(posWB + 8) != 0xff &&                  \
46       sget2(posWB + 10) != 0xff && sget2(posWB) == sget2(posWB + 6) &&         \
47       sget2(posWB) < sget2(posWB + 2) && sget2(posWB) < sget2(posWB + 4) &&    \
48       sget2(posWB) < sget2(posWB + 8) && sget2(posWB) < sget2(posWB + 10)
49 #define imfRAFDataVersion imFuji.RAFDataVersion
50 #define imfRAFVersion imFuji.RAFVersion
51 
52   ushort use_WBcorr_coeffs = 0;
53   double wbR_corr = 1.0;
54   double wbB_corr = 1.0;
55 
56   if (strstr(model, "S7000") ||
57       strstr(model, "S5000") ||
58       strstr(model, "F700")  ||
59       strstr(model, "S2Pro") ||
60       strstr(model, "S20Pro")) {
61     use_WBcorr_coeffs = 1;
62     wbR_corr = 10.0 / 17.0 / 0.652941;
63     wbB_corr = 2.0 /3.0 / (3.0 / 4.0 + 1.0 / 300.0);
64   }
65 
66   order = 0x4d4d;
67   PrivateMknLength = get4();
68 
69   if ((PrivateMknLength > 4) && (PrivateMknLength < 10240000) &&
70       (PrivateMknBuf = (uchar *)malloc(PrivateMknLength + 1024)))
71   { // 1024b for safety
72     fread(PrivateMknBuf, PrivateMknLength, 1, ifp);
73     PrivateOrder = sget2(PrivateMknBuf);
74     posPrivateMknBuf = sget4(PrivateMknBuf + 2) + 12;
75 
76     memcpy(imFuji.SerialSignature, PrivateMknBuf + 6, 0x0c);
77     imFuji.SerialSignature[0x0c] = 0;
78     memcpy(model, PrivateMknBuf + 0x12, 0x20);
79     model[0x20] = 0;
80     memcpy(model2, PrivateMknBuf + 0x32, 4);
81     model2[4] = 0;
82     strcpy(imFuji.RAFVersion, model2);
83     PrivateEntries = sget2(PrivateMknBuf + posPrivateMknBuf);
84     if ((PrivateEntries > 1000) ||
85         ((PrivateOrder != 0x4d4d) && (PrivateOrder != 0x4949)))
86     {
87       free(PrivateMknBuf);
88       return;
89     }
90     posPrivateMknBuf += 2;
91     /*
92      * because Adobe DNG converter strips or misplaces 0xfnnn tags,
93      * Auto WB for following cameras is missing for now
94      * - F550EXR
95      * - F600EXR
96      * - F770EXR
97      * - F800EXR
98      * - F900EXR
99      * - HS10
100      * - HS11
101      * - HS20EXR
102      * - HS30EXR
103      * - HS50EXR
104      * - S1
105      * - SL1000
106      **/
107     while (PrivateEntries--)
108     {
109       order = 0x4d4d;
110       CHECKSPACE(4);
111       PrivateTagID = sget2(PrivateMknBuf + posPrivateMknBuf);
112       PrivateTagBytes = sget2(PrivateMknBuf + posPrivateMknBuf + 2);
113       posPrivateMknBuf += 4;
114       order = PrivateOrder;
115 
116       if (PrivateTagID == 0x2000)
117       {
118         FORC4 icWBC[LIBRAW_WBI_Auto][GRGB_2_RGBG(c)] =
119             sget2(PrivateMknBuf + posPrivateMknBuf + (c << 1));
120         if (use_WBcorr_coeffs) {
121           icWBC[LIBRAW_WBI_Auto][0] *= wbR_corr;
122           icWBC[LIBRAW_WBI_Auto][2] *= wbB_corr;
123         }
124       }
125       else if (PrivateTagID == 0x2100)
126       {
127         FORC4 icWBC[LIBRAW_WBI_FineWeather][GRGB_2_RGBG(c)] =
128             sget2(PrivateMknBuf + posPrivateMknBuf + (c << 1));
129         if (use_WBcorr_coeffs) {
130           icWBC[LIBRAW_WBI_FineWeather][0] *= wbR_corr;
131           icWBC[LIBRAW_WBI_FineWeather][2] *= wbB_corr;
132         }
133       }
134       else if (PrivateTagID == 0x2200)
135       {
136         FORC4 icWBC[LIBRAW_WBI_Shade][GRGB_2_RGBG(c)] =
137             sget2(PrivateMknBuf + posPrivateMknBuf + (c << 1));
138         if (use_WBcorr_coeffs) {
139           icWBC[LIBRAW_WBI_Shade][0] *= wbR_corr;
140           icWBC[LIBRAW_WBI_Shade][2] *= wbB_corr;
141         }
142       }
143       else if (PrivateTagID == 0x2300)
144       {
145         FORC4 icWBC[LIBRAW_WBI_FL_D][GRGB_2_RGBG(c)] =
146             sget2(PrivateMknBuf + posPrivateMknBuf + (c << 1));
147         if (use_WBcorr_coeffs) {
148           icWBC[LIBRAW_WBI_FL_D][0] *= wbR_corr;
149           icWBC[LIBRAW_WBI_FL_D][2] *= wbB_corr;
150         }
151       }
152       else if (PrivateTagID == 0x2301)
153       {
154         FORC4 icWBC[LIBRAW_WBI_FL_N][GRGB_2_RGBG(c)] =
155             sget2(PrivateMknBuf + posPrivateMknBuf + (c << 1));
156         if (use_WBcorr_coeffs) {
157           icWBC[LIBRAW_WBI_FL_N][0] *= wbR_corr;
158           icWBC[LIBRAW_WBI_FL_N][2] *= wbB_corr;
159         }
160       }
161       else if (PrivateTagID == 0x2302)
162       {
163         FORC4 icWBC[LIBRAW_WBI_FL_WW][GRGB_2_RGBG(c)] =
164             sget2(PrivateMknBuf + posPrivateMknBuf + (c << 1));
165         if (use_WBcorr_coeffs) {
166           icWBC[LIBRAW_WBI_FL_WW][0] *= wbR_corr;
167           icWBC[LIBRAW_WBI_FL_WW][2] *= wbB_corr;
168         }
169       }
170       else if (PrivateTagID == 0x2310)
171       {
172         FORC4 icWBC[LIBRAW_WBI_FL_L][GRGB_2_RGBG(c)] =
173             sget2(PrivateMknBuf + posPrivateMknBuf + (c << 1));
174         if (use_WBcorr_coeffs) {
175           icWBC[LIBRAW_WBI_FL_L][0] *= wbR_corr;
176           icWBC[LIBRAW_WBI_FL_L][2] *= wbB_corr;
177         }
178       }
179       else if (PrivateTagID == 0x2311)
180       {
181         FORC4 icWBC[LIBRAW_WBI_FL_W][GRGB_2_RGBG(c)] =
182             sget2(PrivateMknBuf + posPrivateMknBuf + (c << 1));
183         if (use_WBcorr_coeffs) {
184           icWBC[LIBRAW_WBI_FL_W][0] *= wbR_corr;
185           icWBC[LIBRAW_WBI_FL_W][2] *= wbB_corr;
186         }
187       }
188       else if (PrivateTagID == 0x2400)
189       {
190         FORC4 icWBC[LIBRAW_WBI_Tungsten][GRGB_2_RGBG(c)] =
191             sget2(PrivateMknBuf + posPrivateMknBuf + (c << 1));
192         if (use_WBcorr_coeffs) {
193           icWBC[LIBRAW_WBI_Tungsten][0] *= wbR_corr;
194           icWBC[LIBRAW_WBI_Tungsten][2] *= wbB_corr;
195         }
196       }
197       else if (PrivateTagID == 0x2410)
198       {
199         FORC4 icWBC[LIBRAW_WBI_Flash][GRGB_2_RGBG(c)] =
200             sget2(PrivateMknBuf + posPrivateMknBuf + (c << 1));
201         if (use_WBcorr_coeffs) {
202           icWBC[LIBRAW_WBI_Flash][0] *= wbR_corr;
203           icWBC[LIBRAW_WBI_Flash][2] *= wbB_corr;
204         }
205       }
206       else if (PrivateTagID == 0x2f00)
207       {
208         int nWBs = MIN(sget4(PrivateMknBuf + posPrivateMknBuf), 6);
209         posWB = posPrivateMknBuf + 4;
210         for (int wb_ind = 0; wb_ind < nWBs; wb_ind++)
211         {
212           FORC4 icWBC[LIBRAW_WBI_Custom1 + wb_ind][GRGB_2_RGBG(c)] =
213               sget2(PrivateMknBuf + posWB + (c << 1));
214           if (use_WBcorr_coeffs) {
215             icWBC[LIBRAW_WBI_Custom1 + wb_ind][0] *= wbR_corr;
216             icWBC[LIBRAW_WBI_Custom1 + wb_ind][2] *= wbB_corr;
217           }
218           posWB += 8;
219         }
220       }
221       else if (PrivateTagID == 0x2ff0)
222       {
223         FORC4 cam_mul[GRGB_2_RGBG(c)] =
224             sget2(PrivateMknBuf + posPrivateMknBuf + (c << 1));
225         if (use_WBcorr_coeffs) {
226          cam_mul[0] *= wbR_corr;
227          cam_mul[2] *= wbB_corr;
228         }
229       }
230 
231       else if (PrivateTagID == 0x9650)
232       {
233         CHECKSPACE(4);
234         short a = (short)sget2(PrivateMknBuf + posPrivateMknBuf);
235         float b = fMAX(1.0f, sget2(PrivateMknBuf + posPrivateMknBuf + 2));
236         imFuji.ExpoMidPointShift = a / b;
237       }
238       else if ((PrivateTagID == 0xc000) && (PrivateTagBytes > 3) &&
239                (PrivateTagBytes < 10240000))
240       {
241         order = 0x4949;
242         if (PrivateTagBytes != 4096) // not one of Fuji X-A3, X-A5, X-A7, X-A10, X-A20, X-T100, X-T200, XF10
243         {
244           if (!sget2(PrivateMknBuf + posPrivateMknBuf))
245             imfRAFDataVersion = sget2(PrivateMknBuf + posPrivateMknBuf + 2);
246 
247           for (posWB = 0; posWB < (int)PrivateTagBytes - 16; posWB++)
248           {
249             if ((!memcmp(PrivateMknBuf + posWB, "TSNERDTS", 8) &&
250                  (sget2(PrivateMknBuf + posWB + 10) > 125)))
251             {
252               posWB += 10;
253               icWBC[LIBRAW_WBI_Auto][1] =
254                   icWBC[LIBRAW_WBI_Auto][3] =
255                       sget2(PrivateMknBuf + posWB);
256               icWBC[LIBRAW_WBI_Auto][0] =
257                   sget2(PrivateMknBuf + posWB + 2);
258               icWBC[LIBRAW_WBI_Auto][2] =
259                   sget2(PrivateMknBuf + posWB + 4);
260               break;
261             }
262           }
263           if (imfRAFDataVersion == 0x0146 || // X20
264               imfRAFDataVersion == 0x0149 || // X100S
265               imfRAFDataVersion == 0x0249)   // X100S
266           {
267             wb_section_offset = 0x1410;
268           }
269           else if (imfRAFDataVersion == 0x014d || // X-M1
270                    imfRAFDataVersion == 0x014e)   // X-A1, X-A2
271           {
272             wb_section_offset = 0x1474;
273           }
274           else if (imfRAFDataVersion == 0x014f || // X-E2
275                    imfRAFDataVersion == 0x024f || // X-E2
276                    imfRAFDataVersion == 0x025d)   // X-H1
277           {
278             wb_section_offset = 0x1480;
279           }
280           else if (imfRAFDataVersion == 0x0150) // XQ1, XQ2
281           {
282             wb_section_offset = 0x1414;
283           }
284           else if (imfRAFDataVersion == 0x0151 || // X-T1 w/diff. fws
285                    imfRAFDataVersion == 0x0251 || imfRAFDataVersion == 0x0351 ||
286                    imfRAFDataVersion == 0x0451 || imfRAFDataVersion == 0x0551)
287           {
288             wb_section_offset = 0x14b0;
289           }
290           else if (imfRAFDataVersion == 0x0152 || // X30
291                    imfRAFDataVersion == 0x0153)   // X100T
292           {
293             wb_section_offset = 0x1444;
294           }
295           else if (imfRAFDataVersion == 0x0154) // X-T10
296           {
297             wb_section_offset = 0x1824;
298           }
299           else if (imfRAFDataVersion == 0x0155) // X70
300           {
301             wb_section_offset = 0x17b4;
302           }
303           else if (imfRAFDataVersion == 0x0255) // X-Pro2
304           {
305             wb_section_offset = 0x135c;
306           }
307           else if (imfRAFDataVersion == 0x0258 || // X-T2
308                    imfRAFDataVersion == 0x025b)   // X-T20
309           {
310             wb_section_offset = 0x13dc;
311           }
312           else if (imfRAFDataVersion == 0x0259) // X100F
313           {
314             wb_section_offset = 0x1370;
315           }
316           else if (imfRAFDataVersion == 0x025a) // GFX 50S
317           {
318             wb_section_offset = 0x1424;
319           }
320           else if (imfRAFDataVersion == 0x025c) // X-E3
321           {
322             wb_section_offset = 0x141c;
323           }
324           else if (imfRAFDataVersion == 0x025e) // X-T3
325           {
326             wb_section_offset = 0x2014;
327           }
328           else if (imfRAFDataVersion == 0x025f) // X-T30, GFX 50R, GFX 100
329           {
330             if (!strcmp(model, "X-T30")) {
331               if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x20b8))
332                 wb_section_offset = 0x20b8;
333               else if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x20c8))
334                 wb_section_offset = 0x20c8;
335             }
336             else if (!strcmp(model, "GFX 50R"))
337               wb_section_offset = 0x1424;
338             else if (!strcmp(model, "GFX 100"))
339               wb_section_offset = 0x20e4;
340           }
341           else if (imfRAFDataVersion == 0x0260) // X-Pro3
342           {
343             wb_section_offset = 0x20e8;
344           }
345           else if (imfRAFDataVersion == 0x0261) // X100V
346           {
347             wb_section_offset = 0x2078;
348           }
349           else if (imfRAFDataVersion == 0x0262) // X-T4
350           {
351             wb_section_offset = 0x21c8;
352           }
353 
354             /* try for unknown RAF Data versions */
355           else if (!strcmp(model, "X-Pro2"))
356           {
357             if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x135c))
358               wb_section_offset = 0x135c;
359           }
360           else if (!strcmp(model, "X100F"))
361           {
362             if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x1370))
363               wb_section_offset = 0x1370;
364           }
365           else if (!strcmp(model, "X-T2"))
366           {
367             if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x13dc))
368               wb_section_offset = 0x13dc;
369           }
370           else if (!strcmp(model, "X-T20"))
371           {
372             if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x13dc))
373               wb_section_offset = 0x13dc;
374           }
375           else if (!strcmp(model, "X20"))
376           {
377             if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x1410))
378               wb_section_offset = 0x1410;
379           }
380           else if (!strcmp(model, "X100S"))
381           {
382             if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x1410))
383               wb_section_offset = 0x1410;
384           }
385           else if (!strcmp(model, "XQ1"))
386           {
387             if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x1414))
388               wb_section_offset = 0x1414;
389           }
390           else if (!strcmp(model, "XQ2"))
391           {
392             if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x1414))
393               wb_section_offset = 0x1414;
394           }
395           else if (!strcmp(model, "X-E3"))
396           {
397             if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x141c))
398               wb_section_offset = 0x141c;
399           }
400           else if (!strcmp(model, "GFX 50S"))
401           {
402             if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x1424))
403               wb_section_offset = 0x1424;
404           }
405           else if (!strcmp(model, "GFX 50R"))
406           {
407             if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x1424))
408               wb_section_offset = 0x1424;
409           }
410           else if (!strcmp(model, "X30"))
411           {
412             if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x1444))
413               wb_section_offset = 0x1444;
414           }
415           else if (!strcmp(model, "X100T"))
416           {
417             if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x1444))
418               wb_section_offset = 0x1444;
419           }
420           else if (!strcmp(model, "X-M1"))
421           {
422             if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x1474))
423               wb_section_offset = 0x1474;
424           }
425           else if (!strcmp(model, "X-A1"))
426           {
427             if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x1474))
428               wb_section_offset = 0x1474;
429           }
430           else if (!strcmp(model, "X-A2"))
431           {
432             if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x1474))
433               wb_section_offset = 0x1474;
434           }
435           else if (!strcmp(model, "X-E2"))
436           {
437             if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x1480))
438               wb_section_offset = 0x1480;
439           }
440           else if (!strcmp(model, "X-H1"))
441           {
442             if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x1480))
443               wb_section_offset = 0x1480;
444           }
445           else if (!strcmp(model, "X-T1"))
446           {
447             if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x14b0))
448               wb_section_offset = 0x14b0;
449           }
450           else if (!strcmp(model, "X70"))
451           {
452             if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x17b4))
453               wb_section_offset = 0x17b4;
454           }
455           else if (!strcmp(model, "X-T10"))
456           {
457             if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x1824))
458               wb_section_offset = 0x1824;
459           }
460           else if (!strcmp(model, "X-E2S"))
461           {
462             if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x1840))
463               wb_section_offset = 0x1840;
464           }
465           else if (!strcmp(model, "X-T3"))
466           {
467             if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x2014))
468               wb_section_offset = 0x2014;
469           }
470           else if (!strcmp(model, "X100V"))
471           {
472             if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x20e8))
473               wb_section_offset = 0x2078;
474           }
475           else if (!strcmp(model, "X-T30"))
476           {
477             if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x20b8))
478               wb_section_offset = 0x20b8;
479           }
480           else if (!strcmp(model, "GFX 100"))
481           {
482             if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x20e4))
483               wb_section_offset = 0x20e4;
484           }
485           else if (!strcmp(model, "X-Pro3"))
486           {
487             if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x20e8))
488               wb_section_offset = 0x20e8;
489           }
490           else if (!strcmp(model, "X-T4"))
491           {
492             if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x21c8))
493               wb_section_offset = 0x21c8;
494           }
495 
496             /* no RAF Data version for the models below */
497           else if (!strcmp(model, "FinePix X100")) // X100 0 0x19f0 0x19e8
498           {
499             if (!strcmp(imfRAFVersion, "0069"))
500               wb_section_offset = 0x19e8;
501             else if (!strcmp(imfRAFVersion, "0100"))
502               wb_section_offset = 0x19f0;
503             else if (!strcmp(imfRAFVersion, "0110"))
504               wb_section_offset = 0x19f0;
505             else if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x19e8))
506               wb_section_offset = 0x19e8;
507             else if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x19f0))
508               wb_section_offset = 0x19f0;
509           }
510           else if (!strcmp(model, "X-E1")) // X-E1 0 0x13ac
511           {
512             if (!strcmp(imfRAFVersion, "0101"))
513               wb_section_offset = 0x13ac;
514             else if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x13ac))
515               wb_section_offset = 0x13ac;
516           }
517           else if (!strcmp(model, "X-Pro1")) // X-Pro1 0 0x13a4
518           {
519             if (!strcmp(imfRAFVersion, "0100"))
520               wb_section_offset = 0x13a4;
521             else if (!strcmp(imfRAFVersion, "0101"))
522               wb_section_offset = 0x13a4;
523             else if (!strcmp(imfRAFVersion, "0204"))
524               wb_section_offset = 0x13a4;
525             else if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x13a4))
526               wb_section_offset = 0x13a4;
527           }
528           else if (!strcmp(model, "XF1")) // XF1 0 0x138c
529           {
530             if (!strcmp(imfRAFVersion, "0100"))
531               wb_section_offset = 0x138c;
532             else if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x138c))
533               wb_section_offset = 0x138c;
534           }
535           else if (!strcmp(model, "X-S1")) // X-S1 0 0x1284
536           {
537             if (!strcmp(imfRAFVersion, "0100"))
538               wb_section_offset = 0x1284;
539             else if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x1284))
540               wb_section_offset = 0x1284;
541           }
542           else if (!strcmp(model, "X10")) // X10 0 0x1280 0x12d4
543           {
544             if (!strcmp(imfRAFVersion, "0100"))
545               wb_section_offset = 0x1280;
546             else if (!strcmp(imfRAFVersion, "0102"))
547               wb_section_offset = 0x1280;
548             else if (!strcmp(imfRAFVersion, "0103"))
549               wb_section_offset = 0x12d4;
550             else if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x1280))
551               wb_section_offset = 0x1280;
552             else if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x12d4))
553               wb_section_offset = 0x12d4;
554           }
555           else if (!strcmp(model, "XF1")) // XF1 0 0x138c
556           {
557             if (!strcmp(imfRAFVersion, "0100"))
558               wb_section_offset = 0x138c;
559             else if (isWB(PrivateMknBuf + posPrivateMknBuf + 0x138c))
560               wb_section_offset = 0x138c;
561           }
562           if (wb_section_offset &&
563               isWB(PrivateMknBuf + posPrivateMknBuf + wb_section_offset))
564           {
565 
566             if (!imfRAFDataVersion)
567             {
568               posWB = posPrivateMknBuf + wb_section_offset - 6;
569               icWBC[LIBRAW_WBI_Auto][1] =
570                   icWBC[LIBRAW_WBI_Auto][3] =
571                       sget2(PrivateMknBuf + posWB);
572               icWBC[LIBRAW_WBI_Auto][0] =
573                   sget2(PrivateMknBuf + posWB + 2);
574               icWBC[LIBRAW_WBI_Auto][2] =
575                   sget2(PrivateMknBuf + posWB + 4);
576             }
577 
578             posWB = posPrivateMknBuf + wb_section_offset;
579             for (int wb_ind = 0; wb_ind < Fuji_wb_list1.size(); posWB += 6, wb_ind++)
580             {
581               icWBC[Fuji_wb_list1[wb_ind]][1] =
582                   icWBC[Fuji_wb_list1[wb_ind]][3] =
583                       sget2(PrivateMknBuf + posWB);
584               icWBC[Fuji_wb_list1[wb_ind]][0] =
585                   sget2(PrivateMknBuf + posWB + 2);
586               icWBC[Fuji_wb_list1[wb_ind]][2] =
587                   sget2(PrivateMknBuf + posWB + 4);
588             }
589             int found = 0;
590             if ((imfRAFDataVersion == 0x0260) ||
591                 (imfRAFDataVersion == 0x0261) ||
592                 (imfRAFDataVersion == 0x0262))
593               posWB += 0x30;
594             posWB += 0xc0;
595             ushort Gval = sget2(PrivateMknBuf + posWB);
596             for (int posEndCCTsection = posWB; posEndCCTsection < (posWB + 30);
597                  posEndCCTsection += 6)
598             {
599               if (sget2(PrivateMknBuf + posEndCCTsection) != Gval)
600               {
601                 if ((imfRAFDataVersion == 0x0260) ||
602                     (imfRAFDataVersion == 0x0261) ||
603                     (imfRAFDataVersion == 0x0262))
604                   wb_section_offset = posEndCCTsection - 34*3*2; // 34 records, 3 2-byte values in a record
605                 else
606                   wb_section_offset = posEndCCTsection - 31*3*2; // 31 records, 3 2-byte values in a record
607                 found = 1;
608                 break;
609               }
610             }
611 
612             if (found)
613             {
614               for (int iCCT = 0; iCCT < 31; iCCT++)
615               {
616                 icWBCCTC[iCCT][0] = FujiCCT_K[iCCT];
617                 icWBCCTC[iCCT][1] = sget2(PrivateMknBuf + wb_section_offset + iCCT * 6 + 2);
618                 icWBCCTC[iCCT][2] = icWBCCTC[iCCT][4] = sget2(PrivateMknBuf + wb_section_offset + iCCT * 6);
619                 icWBCCTC[iCCT][3] = sget2(PrivateMknBuf + wb_section_offset + iCCT * 6 + 4);
620               }
621             }
622           }
623         }
624         else // process 4K raf data
625         {
626           int wb[4];
627           int nWB, tWB, pWB;
628           int iCCT = 0;
629           is_4K_RAFdata = 1; /* X-A3, X-A5, X-A7, X-A10, X-A20, X-T100, X-T200, XF10 */
630           posWB = posPrivateMknBuf + 0x200;
631           for (int wb_ind = 0; wb_ind < 42; wb_ind++)
632           {
633             nWB = sget4(PrivateMknBuf + posWB);
634             posWB += 4;
635             tWB = sget4(PrivateMknBuf + posWB);
636             posWB += 4;
637             wb[0] = sget4(PrivateMknBuf + posWB) << 1;
638             posWB += 4;
639             wb[1] = sget4(PrivateMknBuf + posWB);
640             posWB += 4;
641             wb[3] = sget4(PrivateMknBuf + posWB);
642             posWB += 4;
643             wb[2] = sget4(PrivateMknBuf + posWB) << 1;
644             posWB += 4;
645 
646             if (tWB && (iCCT < 255))
647             {
648               icWBCCTC[iCCT][0] = tWB;
649               FORC4 icWBCCTC[iCCT][c + 1] = wb[c];
650               iCCT++;
651             }
652             if (nWB != 0x46)
653             {
654               for (pWB = 1; pWB < Fuji_wb_list2.size(); pWB += 2)
655               {
656                 if (Fuji_wb_list2[pWB] == nWB)
657                 {
658                   FORC4 icWBC[Fuji_wb_list2[pWB - 1]][c] =
659                       wb[c];
660                   break;
661                 }
662               }
663             }
664           }
665         }
666       }
667       posPrivateMknBuf += PrivateTagBytes;
668     }
669     free(PrivateMknBuf);
670   }
671 #undef imfRAFVersion
672 #undef imfRAFDataVersion
673 #undef CHECKSPACE
674 }
parseFujiMakernotes(unsigned tag,unsigned type,unsigned len,unsigned dng_writer)675 void LibRaw::parseFujiMakernotes(unsigned tag, unsigned type, unsigned len,
676                                  unsigned dng_writer)
677 {
678   if ((dng_writer == nonDNG) && (tag == 0x0010))
679   {
680     char FujiSerial[sizeof(imgdata.shootinginfo.InternalBodySerial)];
681     char *words[4];
682     char yy[2], mm[3], dd[3], ystr[16], ynum[16];
683     int year, nwords, ynum_len;
684     unsigned c;
685     memset(FujiSerial, 0, sizeof(imgdata.shootinginfo.InternalBodySerial));
686     ifp->read(FujiSerial, MIN(len,sizeof(FujiSerial)), 1);
687     nwords = getwords(FujiSerial, words, 4,
688                       sizeof(imgdata.shootinginfo.InternalBodySerial));
689     for (int i = 0; i < nwords; i++)
690     {
691       mm[2] = dd[2] = 0;
692       if (strnlen(words[i],
693                   sizeof(imgdata.shootinginfo.InternalBodySerial) - 1) < 18)
694       {
695         if (i == 0)
696         {
697           strncpy(imgdata.shootinginfo.InternalBodySerial, words[0],
698                   sizeof(imgdata.shootinginfo.InternalBodySerial) - 1);
699         }
700         else
701         {
702           char tbuf[sizeof(imgdata.shootinginfo.InternalBodySerial)];
703           snprintf(tbuf, sizeof(tbuf)-1, "%s %s",
704                    imgdata.shootinginfo.InternalBodySerial, words[i]);
705           strncpy(imgdata.shootinginfo.InternalBodySerial, tbuf,
706                   sizeof(imgdata.shootinginfo.InternalBodySerial) - 1);
707         }
708       }
709       else
710       {
711         strncpy(
712             dd,
713             words[i] +
714                 strnlen(words[i],
715                         sizeof(imgdata.shootinginfo.InternalBodySerial) - 1) -
716                 14,
717             2);
718         strncpy(
719             mm,
720             words[i] +
721                 strnlen(words[i],
722                         sizeof(imgdata.shootinginfo.InternalBodySerial) - 1) -
723                 16,
724             2);
725         strncpy(
726             yy,
727             words[i] +
728                 strnlen(words[i],
729                         sizeof(imgdata.shootinginfo.InternalBodySerial) - 1) -
730                 18,
731             2);
732         year = (yy[0] - '0') * 10 + (yy[1] - '0');
733         if (year < 70)
734           year += 2000;
735         else
736           year += 1900;
737 
738         ynum_len = MIN(
739             int(sizeof(ynum) - 1),
740             (int)strnlen(words[i],
741                          sizeof(imgdata.shootinginfo.InternalBodySerial) - 1) -
742                 18);
743         strncpy(ynum, words[i], ynum_len);
744         ynum[ynum_len] = 0;
745         for (int j = 0; ynum[j] && ynum[j + 1] && sscanf(ynum + j, "%2x", &c);
746              j += 2)
747           ystr[j / 2] = c;
748         ystr[ynum_len / 2 + 1] = 0;
749         strcpy(model2, ystr);
750 
751         if (i == 0)
752         {
753           char tbuf[sizeof(imgdata.shootinginfo.InternalBodySerial)];
754 
755           if (nwords == 1)
756           {
757             snprintf(
758                 tbuf, sizeof(tbuf), "%s %s %d:%s:%s",
759                 words[0] +
760                     strnlen(words[0],
761                             sizeof(imgdata.shootinginfo.InternalBodySerial) -
762                                 1) -
763                     12,
764                 ystr, year, mm, dd);
765           }
766           else
767           {
768             snprintf(
769                 tbuf, sizeof(tbuf), "%s %d:%s:%s %s", ystr, year, mm, dd,
770                 words[0] +
771                     strnlen(words[0],
772                             sizeof(imgdata.shootinginfo.InternalBodySerial) -
773                                 1) -
774                     12);
775           }
776           strncpy(imgdata.shootinginfo.InternalBodySerial, tbuf,
777                   sizeof(imgdata.shootinginfo.InternalBodySerial) - 1);
778         }
779         else
780         {
781           char tbuf[sizeof(imgdata.shootinginfo.InternalBodySerial)];
782           snprintf(
783               tbuf, sizeof(tbuf), "%s %s %d:%s:%s %s",
784               imgdata.shootinginfo.InternalBodySerial, ystr, year, mm, dd,
785               words[i] +
786                   strnlen(words[i],
787                           sizeof(imgdata.shootinginfo.InternalBodySerial) - 1) -
788                   12);
789           strncpy(imgdata.shootinginfo.InternalBodySerial, tbuf,
790                   sizeof(imgdata.shootinginfo.InternalBodySerial) - 1);
791         }
792       }
793     }
794   }
795   else
796     switch (tag)
797     {
798     case 0x1002:
799       imFuji.WB_Preset = get2();
800       break;
801     case 0x1011:
802       imCommon.FlashEC = getreal(type);
803       break;
804     case 0x1020:
805       imFuji.Macro = get2();
806       break;
807     case 0x1021:
808       imFuji.FocusMode = imgdata.shootinginfo.FocusMode = get2();
809       break;
810     case 0x1022:
811       imFuji.AFMode = get2();
812       break;
813     case 0x1023:
814       imFuji.FocusPixel[0] = get2();
815       imFuji.FocusPixel[1] = get2();
816       break;
817     case 0x1034:
818       imFuji.ExrMode = get2();
819       break;
820     case 0x104d:
821       FujiCropMode = get2(); // odd: one of raw dimensions here can be lost
822       break;
823     case 0x1050:
824       imFuji.ShutterType = get2();
825       break;
826     case 0x1103:
827       imgdata.shootinginfo.DriveMode = get2();
828       imFuji.DriveMode = imgdata.shootinginfo.DriveMode & 0xff;
829       break;
830 
831     case 0x1400:
832       imFuji.DynamicRange = get2();
833       break;
834     case 0x1401:
835       imFuji.FilmMode = get2();
836       break;
837     case 0x1402:
838       imFuji.DynamicRangeSetting = get2();
839       break;
840     case 0x1403:
841       imFuji.DevelopmentDynamicRange = get2();
842       break;
843     case 0x140b:
844       imFuji.AutoDynamicRange = get2();
845       break;
846     case 0x1443:
847       imFuji.DRangePriority = get2();
848       break;
849     case 0x1444:
850       imFuji.DRangePriorityAuto = get2();
851       break;
852     case 0x1445:
853       imFuji.DRangePriorityFixed = get2();
854       break;
855 
856     case 0x1404:
857       ilm.MinFocal = getreal(type);
858       break;
859     case 0x1405:
860       ilm.MaxFocal = getreal(type);
861       break;
862     case 0x1406:
863       ilm.MaxAp4MinFocal = getreal(type);
864       break;
865     case 0x1407:
866       ilm.MaxAp4MaxFocal = getreal(type);
867       break;
868     case 0x1422:
869       imFuji.ImageStabilization[0] = get2();
870       imFuji.ImageStabilization[1] = get2();
871       imFuji.ImageStabilization[2] = get2();
872       imgdata.shootinginfo.ImageStabilization =
873           (imFuji.ImageStabilization[0] << 9) + imFuji.ImageStabilization[1];
874       break;
875     case 0x1431:
876       imFuji.Rating = get4();
877       break;
878     case 0x3820:
879       imFuji.FrameRate = get2();
880       break;
881     case 0x3821:
882       imFuji.FrameWidth = get2();
883       break;
884     case 0x3822:
885       imFuji.FrameHeight = get2();
886       break;
887     }
888   return;
889 }
890 
parse_fuji(int offset)891 void LibRaw::parse_fuji(int offset)
892 {
893   unsigned entries, tag, len, save, c;
894   ushort raw_inset_present = 0;
895   ushort use_WBcorr_coeffs = 0;
896   double wbR_corr = 1.0;
897   double wbB_corr = 1.0;
898 
899   fseek(ifp, offset, SEEK_SET);
900   entries = get4();
901   if (entries > 255)
902     return;
903   imgdata.process_warnings |= LIBRAW_WARN_PARSEFUJI_PROCESSED;
904 
905   if (strstr(model, "S7000") ||
906       strstr(model, "S5000") ||
907       strstr(model, "F700")  ||
908       strstr(model, "S2Pro") ||
909       strstr(model, "S20Pro")) {
910     use_WBcorr_coeffs = 1;
911     wbR_corr = 10.0 / 17.0 / 0.652941;
912     wbB_corr = 2.0 /3.0 / (3.0 / 4.0 + 1.0 / 300.0);
913   }
914 
915   while (entries--)
916   {
917     tag = get2();
918     len = get2();
919     save = ftell(ifp);
920 
921     if (tag == 0x0100) // RawImageFullSize
922     {
923       raw_height = get2();
924       raw_width = get2();
925       raw_inset_present = 1;
926     }
927     else if (tag == 0x0121) // RawImageSize
928     {
929       height = get2();
930       if ((width = get2()) == 4284)
931         width += 3;
932     }
933     else if (tag == 0x0130) // FujiLayout
934     {
935       fuji_layout = fgetc(ifp) >> 7;
936       fuji_width = !(fgetc(ifp) & 8);
937     }
938     else if (tag == 0x0131) // XTransLayout
939     {
940       filters = 9;
941       char *xtrans_abs_alias = &xtrans_abs[0][0];
942       FORC(36)
943       {
944         int q = fgetc(ifp);
945         xtrans_abs_alias[35 - c] = MAX(0, MIN(q, 2)); /* & 3;*/
946       }
947     }
948     else if (tag == 0x2ff0) // WB_GRGBLevels
949     {
950       FORC4 cam_mul[GRGB_2_RGBG(c)] = get2();
951       if (use_WBcorr_coeffs) {
952        cam_mul[0] *= wbR_corr;
953        cam_mul[2] *= wbB_corr;
954       }
955     }
956 
957     else if ((tag == 0x0110) && raw_inset_present) // RawImageCropTopLeft
958     {
959       imgdata.sizes.raw_inset_crop.ctop = get2();
960       imgdata.sizes.raw_inset_crop.cleft = get2();
961     }
962     else if ((tag == 0x0111) && raw_inset_present) // RawImageCroppedSize
963     {
964       imgdata.sizes.raw_inset_crop.cheight = get2();
965       imgdata.sizes.raw_inset_crop.cwidth = get2();
966     }
967     else if ((tag == 0x0115) && raw_inset_present) // RawImageAspectRatio
968     {
969       int a = get2();
970       int b = get2();
971       if (a * b == 6)
972         imgdata.sizes.raw_inset_crop.aspect = LIBRAW_IMAGE_ASPECT_3to2;
973       else if (a * b == 12)
974         imgdata.sizes.raw_inset_crop.aspect = LIBRAW_IMAGE_ASPECT_4to3;
975       else if (a * b == 144)
976         imgdata.sizes.raw_inset_crop.aspect = LIBRAW_IMAGE_ASPECT_16to9;
977       else if (a * b == 1)
978         imgdata.sizes.raw_inset_crop.aspect = LIBRAW_IMAGE_ASPECT_1to1;
979     }
980     else if (tag == 0x9200) // RelativeExposure
981     {
982       int a = get4();
983       if ((a == 0x01000100) || (a <= 0))
984         imFuji.BrightnessCompensation = 0.0f;
985       else if (a == 0x00100100)
986         imFuji.BrightnessCompensation = 4.0f;
987       else
988         imFuji.BrightnessCompensation =
989             24.0f - float(log((double)a) / log(2.0));
990     }
991     else if (tag == 0x9650) // RawExposureBias
992     {
993       short a = (short)get2();
994       float b = fMAX(1.0f, get2());
995       imFuji.ExpoMidPointShift = a / b;
996     }
997     else if (tag == 0x2f00) // WB_GRGBLevels
998     {
999       int nWBs = get4();
1000       nWBs = MIN(nWBs, 6);
1001       for (int wb_ind = 0; wb_ind < nWBs; wb_ind++)
1002       {
1003         FORC4 icWBC[LIBRAW_WBI_Custom1 + wb_ind][GRGB_2_RGBG(c)] = get2();
1004         if (use_WBcorr_coeffs) {
1005           icWBC[LIBRAW_WBI_Custom1 + wb_ind][0] *= wbR_corr;
1006           icWBC[LIBRAW_WBI_Custom1 + wb_ind][2] *= wbB_corr;
1007         }
1008         fseek(ifp, 8, SEEK_CUR);
1009       }
1010     }
1011     else if (tag == 0x2000) // WB_GRGBLevelsAuto
1012     {
1013       FORC4 icWBC[LIBRAW_WBI_Auto][GRGB_2_RGBG(c)] = get2();
1014       if (use_WBcorr_coeffs) {
1015         icWBC[LIBRAW_WBI_Auto][0] *= wbR_corr;
1016         icWBC[LIBRAW_WBI_Auto][2] *= wbB_corr;
1017       }
1018     }
1019     else if (tag == 0x2100) // WB_GRGBLevelsDaylight
1020     {
1021       FORC4 icWBC[LIBRAW_WBI_FineWeather][GRGB_2_RGBG(c)] = get2();
1022       if (use_WBcorr_coeffs) {
1023         icWBC[LIBRAW_WBI_FineWeather][0] *= wbR_corr;
1024         icWBC[LIBRAW_WBI_FineWeather][2] *= wbB_corr;
1025       }
1026     }
1027     else if (tag == 0x2200) // WB_GRGBLevelsCloudy
1028     {
1029       FORC4 icWBC[LIBRAW_WBI_Shade][GRGB_2_RGBG(c)] = get2();
1030       if (use_WBcorr_coeffs) {
1031         icWBC[LIBRAW_WBI_Shade][0] *= wbR_corr;
1032         icWBC[LIBRAW_WBI_Shade][2] *= wbB_corr;
1033       }
1034     }
1035     else if (tag == 0x2300) // WB_GRGBLevelsDaylightFluor
1036     {
1037       FORC4 icWBC[LIBRAW_WBI_FL_D][GRGB_2_RGBG(c)] = get2();
1038       if (use_WBcorr_coeffs) {
1039         icWBC[LIBRAW_WBI_FL_D][0] *= wbR_corr;
1040         icWBC[LIBRAW_WBI_FL_D][2] *= wbB_corr;
1041       }
1042     }
1043     else if (tag == 0x2301) // WB_GRGBLevelsDayWhiteFluor
1044     {
1045       FORC4 icWBC[LIBRAW_WBI_FL_N][GRGB_2_RGBG(c)] = get2();
1046       if (use_WBcorr_coeffs) {
1047         icWBC[LIBRAW_WBI_FL_N][0] *= wbR_corr;
1048         icWBC[LIBRAW_WBI_FL_N][2] *= wbB_corr;
1049       }
1050     }
1051     else if (tag == 0x2302) // WB_GRGBLevelsWhiteFluorescent
1052     {
1053       FORC4 icWBC[LIBRAW_WBI_FL_WW][GRGB_2_RGBG(c)] = get2();
1054       if (use_WBcorr_coeffs) {
1055         icWBC[LIBRAW_WBI_FL_WW][0] *= wbR_corr;
1056         icWBC[LIBRAW_WBI_FL_WW][2] *= wbB_corr;
1057       }
1058     }
1059     else if (tag == 0x2310) // WB_GRGBLevelsWarmWhiteFluor
1060     {
1061       FORC4 icWBC[LIBRAW_WBI_FL_L][GRGB_2_RGBG(c)] = get2();
1062       if (use_WBcorr_coeffs) {
1063         icWBC[LIBRAW_WBI_FL_L][0] *= wbR_corr;
1064         icWBC[LIBRAW_WBI_FL_L][2] *= wbB_corr;
1065       }
1066     }
1067     else if (tag == 0x2311) // WB_GRGBLevelsLivingRoomWarmWhiteFluor
1068     {
1069       FORC4 icWBC[LIBRAW_WBI_FL_W][GRGB_2_RGBG(c)] = get2();
1070       if (use_WBcorr_coeffs) {
1071         icWBC[LIBRAW_WBI_FL_W][0] *= wbR_corr;
1072         icWBC[LIBRAW_WBI_FL_W][2] *= wbB_corr;
1073       }
1074     }
1075     else if (tag == 0x2400) // WB_GRGBLevelsTungsten
1076     {
1077       FORC4 icWBC[LIBRAW_WBI_Tungsten][GRGB_2_RGBG(c)] = get2();
1078       if (use_WBcorr_coeffs) {
1079         icWBC[LIBRAW_WBI_Tungsten][0] *= wbR_corr;
1080         icWBC[LIBRAW_WBI_Tungsten][2] *= wbB_corr;
1081       }
1082     }
1083     else if (tag == 0x2410)
1084     {
1085       FORC4 icWBC[LIBRAW_WBI_Flash][GRGB_2_RGBG(c)] = get2();
1086       if (use_WBcorr_coeffs) {
1087         icWBC[LIBRAW_WBI_Flash][0] *= wbR_corr;
1088         icWBC[LIBRAW_WBI_Flash][2] *= wbB_corr;
1089       }
1090     }
1091 
1092     else if (tag == 0xc000) // RAFData
1093     {
1094       c = order;
1095       order = 0x4949;
1096       if (len > 20000)
1097       {
1098         tag = get4();
1099         if (tag > 10000)
1100         {
1101           imFuji.RAFDataVersion = tag >> 16;
1102           if (!imFuji.RAFDataVersion)
1103             imFuji.RAFDataVersion = tag;
1104           tag = get4();
1105         }
1106         if (tag > 10000)
1107         { // if it is >1000 it normally contains 0x53545257, "WRTS"
1108           tag = get4();
1109         }
1110         width = tag;
1111         height = get4();
1112         if (width > raw_width)
1113           width = raw_width;
1114         if (height > raw_height)
1115           height = raw_height;
1116       }
1117       if (len == 4096) // X-A3, X-A5, X-A7, X-A10, X-A20, X-T100, X-T200, XF10
1118       {                // Ill.A aligned to CCT 2850
1119         int wb[4];
1120         int nWB, tWB, pWB;
1121         int iCCT = 0;
1122         is_4K_RAFdata = 1;
1123         fseek(ifp, save + 0x200, SEEK_SET);
1124         for (int wb_ind = 0; wb_ind < 42; wb_ind++)
1125         {
1126           nWB = get4();
1127           tWB = get4();
1128           wb[0] = get4() << 1;
1129           wb[1] = get4();
1130           wb[3] = get4();
1131           wb[2] = get4() << 1;
1132           if (tWB && (iCCT < 255))
1133           {
1134             icWBCCTC[iCCT][0] = tWB;
1135             FORC4 icWBCCTC[iCCT][c + 1] = wb[c];
1136             iCCT++;
1137           }
1138           if (nWB != 70)
1139           {
1140             for (pWB = 1; pWB < Fuji_wb_list2.size(); pWB += 2)
1141             {
1142               if (Fuji_wb_list2[pWB] == nWB)
1143               {
1144                 FORC4 icWBC[Fuji_wb_list2[pWB - 1]][c] =
1145                     wb[c];
1146                 break;
1147               }
1148             }
1149           }
1150         }
1151       }
1152       else
1153       {
1154         libraw_internal_data.unpacker_data.posRAFData = save;
1155         libraw_internal_data.unpacker_data.lenRAFData = (len >> 1);
1156       }
1157       order = c;
1158     }
1159     fseek(ifp, save + len, SEEK_SET);
1160   }
1161   height <<= fuji_layout;
1162   width >>= fuji_layout;
1163 }
1164