Coverage Report

Created: 2026-06-30 07:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libraw/src/metadata/fuji.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
#include "../../internal/libraw_checked_buffer.h"
21
22
23
int LibRaw::guess_RAFDataGeneration (uchar *RAFData_start) // returns offset to first valid width/height pair
24
11.3k
{
25
26
/* RAFDataGeneration codes, values are 4 bytes, little endian
27
28
   RAFData gen. 0: no RAFData
29
     DBP for GX680 / DX-2000
30
     E550, E900, (F500 / F505?) F550, F600 / F605, F700, F770 / F775, F800, F810, F900
31
     HS10 HS11, HS20 / HS22, HS30 / HS33 / HS35, HS50
32
     S1, SL1000, S100, S200 / S205, S20Pro, S2Pro, S3Pro, S5Pro
33
     S5000, S5100 / S5500, S5200 / S5600, S6000 / S6500, S7000, S9000 / S9500, S9100 / S9600
34
35
   RAFData gen. 1, offset to WH pair (offsetWH_inRAFData) = 0:
36
   - number in bytes 0..1 is less than 10000
37
   - contains WH pair, recommended image size WH pair, 16 bytes unknown, 2*13 values (for crops, scales?)
38
     X100, X-Pro1, X-S1, X10, XF1
39
40
   RAFData gen. 2, offset to WH pair = 4:
41
   - bytes 0..1 contain a number greater than 10000; bytes 2..3 contain zero;
42
     version is in bytes 0..1, possibly big endian
43
     - contains WH pair, recommended image size WH pair, 16 bytes unknown, 2*13 values
44
     X-E1
45
46
   RAFData gen. 3, offset to WH pair = 4:
47
   - bytes 0..1 contain zero; bytes 2..3 contain version;
48
   - contains a table of 3+2*13 values; first 3 values look like WHW
49
     X-A1, X-A2, X-E2, X-M1
50
     X-T1, X-T10
51
     X100S, X100T
52
     X20, X30, X70, XQ1, XQ2
53
54
   RAFData gen. 4, offset to WH pair = 8:
55
   - same conditions as for RAFData gen. 3, but also adds WRTS in bytes 4..7
56
   - contains a table of 3+2*13 values; first 3 values look like WHW
57
   - H in WHW group has a different meaning if the shot is taken in crop 2 mode
58
     GFX 100, GFX 100S, GFX 100 II
59
     GFX 50R, GFX 50S, GFX 50S II
60
     X-E2S, X-E3, X-H1, X-S10, X-H2
61
     X-T2, X-T3, X-T4, X-T20, X-T30
62
     X-Pro2, X-Pro3
63
     X100F, X100V, X100VI
64
65
   RAFData gen. set to 4096:
66
   - RAFData length is exactly 4096
67
     X-A3, X-A5, X-A7, X-A10, X-A20
68
     X-T100, X-T200,
69
     XF10
70
*/
71
72
11.3k
  int offsetWH_inRAFData=0; /* clang warns about not initialized value */
73
11.3k
  ushort b01  = sget2(RAFData_start);   // bytes 0..1
74
11.3k
  ushort b23  = sget2(RAFData_start+2); // bytes 2..3
75
11.3k
  int is_WRTS = (sget4(RAFData_start + 4) == 0x53545257); // STRW
76
11.3k
  if (b01 && !b23 && (b01<10000))
77
474
  {
78
474
    imFuji.RAFDataGeneration = 1;
79
474
    offsetWH_inRAFData = 0;
80
474
  }
81
10.8k
  else if ((b01>10000) && !b23)
82
305
  {
83
305
    imFuji.RAFDataGeneration = 2;
84
305
    imFuji.RAFDataVersion = b01;
85
305
    offsetWH_inRAFData = 4;
86
305
  }
87
10.5k
  else if (!b01)
88
5.28k
  {
89
5.28k
    if (!is_WRTS)
90
5.28k
    {
91
5.28k
      imFuji.RAFDataGeneration = 3;
92
5.28k
      offsetWH_inRAFData = 4;
93
5.28k
    }
94
0
    else
95
0
    {
96
0
      imFuji.RAFDataGeneration = 4;
97
0
      offsetWH_inRAFData = 8;
98
0
    }
99
5.28k
    imFuji.RAFDataVersion = b23;
100
5.28k
  }
101
102
// printf (">> ID: 0x%llx, RAFDataVersion: 0x%04x, RAFDataGeneration: %d\n",
103
// ilm.CamID, imFuji.RAFDataVersion, imFuji.RAFDataGeneration);
104
105
11.3k
  return offsetWH_inRAFData;
106
11.3k
}
107
108
class fuji_wb_checked_buffer_t : public checked_buffer_t
109
{
110
public:
111
  bool isWB(unsigned offset)
112
12.8k
  {
113
12.8k
    return sget2(offset) != 0 && sget2(offset + 2) != 0 && sget2(offset + 4) != 0 && sget2(offset + 6) != 0 &&
114
3.81k
      sget2(offset + 8) != 0 && sget2(offset + 10) != 0 && sget2(offset) != 0xff && sget2(offset + 2) != 0xff &&
115
3.16k
      sget2(offset + 4) != 0xff && sget2(offset + 6) != 0xff && sget2(offset + 8) != 0xff &&
116
2.66k
      sget2(offset + 10) != 0xff && sget2(offset) == sget2(offset + 6) && sget2(offset) < sget2(offset + 2) &&
117
1.95k
      sget2(offset) < sget2(offset + 4) && sget2(offset) < sget2(offset + 8) && sget2(offset) < sget2(offset + 10)
118
12.8k
      ;
119
12.8k
  }
120
13.7k
  fuji_wb_checked_buffer_t(short ord, int size) : checked_buffer_t(ord, size) {}
121
3.21M
  void set_order(short o) { _order = o; }
122
};
123
124
struct tag2wb_t
125
{
126
  unsigned tag;
127
  int wb;
128
} tag2wbtable[] =
129
{
130
  {0x2000, LIBRAW_WBI_Auto },
131
  {0x2100, LIBRAW_WBI_FineWeather },
132
  {0x2200, LIBRAW_WBI_Shade},
133
  {0x2300, LIBRAW_WBI_FL_D },
134
  {0x2301, LIBRAW_WBI_FL_N},
135
  {0x2302, LIBRAW_WBI_FL_W },
136
  {0x2310, LIBRAW_WBI_FL_WW},
137
  {0x2311, LIBRAW_WBI_FL_L},
138
  {0x2400, LIBRAW_WBI_Tungsten},
139
  {0x2410, LIBRAW_WBI_Flash}
140
};
141
const int tag2wbtable_size = sizeof(tag2wbtable) / sizeof(tag2wbtable[0]);
142
143
144
void LibRaw::parseAdobeRAFMakernote()
145
13.8k
{
146
147
13.8k
  unsigned posPrivateMknBuf=0; /* clang warns about not inited value */
148
13.8k
  unsigned PrivateMknLength;
149
13.8k
  unsigned PrivateOrder;
150
13.8k
  unsigned ifd_start, ifd_len;
151
13.8k
  unsigned PrivateEntries, PrivateTagID;
152
13.8k
  unsigned PrivateTagBytes;
153
13.8k
  int FujiShotSelect;
154
13.8k
  unsigned wb_section_offset = 0;
155
13.8k
  int posWB;
156
13.8k
  int c;
157
158
#if 0
159
#define isWB(posWB)                                                            \
160
  sget2(posWB) != 0 && sget2(posWB + 2) != 0 && sget2(posWB + 4) != 0 &&       \
161
      sget2(posWB + 6) != 0 && sget2(posWB + 8) != 0 &&                        \
162
      sget2(posWB + 10) != 0 && sget2(posWB) != 0xff &&                        \
163
      sget2(posWB + 2) != 0xff && sget2(posWB + 4) != 0xff &&                  \
164
      sget2(posWB + 6) != 0xff && sget2(posWB + 8) != 0xff &&                  \
165
      sget2(posWB + 10) != 0xff && sget2(posWB) == sget2(posWB + 6) &&         \
166
      sget2(posWB) < sget2(posWB + 2) && sget2(posWB) < sget2(posWB + 4) &&    \
167
      sget2(posWB) < sget2(posWB + 8) && sget2(posWB) < sget2(posWB + 10)
168
#endif
169
170
13.8k
#define get_average_WB(wb_index)                                               \
171
13.8k
  do {                                                                         \
172
19.7k
    FORC4 icWBC[wb_index][GRGB_2_RGBG(c)] =                                      \
173
19.7k
      PrivateMknBuf.sget2(posPrivateMknBuf + (c << 1));                        \
174
4.94k
    if ((PrivateTagBytes == 16) && average_WBData) {                             \
175
4.00k
    FORC4 icWBC[wb_index][GRGB_2_RGBG(c)] =                                    \
176
4.00k
         (icWBC[wb_index][GRGB_2_RGBG(c)] +                                \
177
4.00k
          PrivateMknBuf.sget2(posPrivateMknBuf + (c << 1)+8)) /2;          \
178
1.00k
    }                                                                            \
179
4.94k
    if (use_WBcorr_coeffs) {                                                     \
180
1.13k
    icWBC[wb_index][0] = int(icWBC[wb_index][0]*wbR_corr);                     \
181
1.13k
    icWBC[wb_index][2] = int(icWBC[wb_index][2]*wbB_corr);                     \
182
1.13k
    }                                                                            \
183
4.94k
  } while(0)
184
185
13.8k
  ushort use_WBcorr_coeffs = 0;
186
13.8k
  double wbR_corr = 1.0;
187
13.8k
  double wbB_corr = 1.0;
188
189
13.8k
  if (strstr(model, "S2Pro")
190
13.7k
      || strstr(model, "S20Pro")
191
13.6k
      || strstr(model, "F700")
192
13.4k
      || strstr(model, "S5000")
193
13.3k
      || strstr(model, "S7000")
194
13.8k
      ) {
195
528
    use_WBcorr_coeffs = 1;
196
528
    wbR_corr = 10.0 / 17.0 / 0.652941;
197
528
    wbB_corr = 2.0 /3.0 / (3.0 / 4.0 + 1.0 / 300.0);
198
13.2k
  } else if (strstr(model, "DBP") || strstr(model, "DX-2000")) {
199
236
    use_WBcorr_coeffs = 1;
200
236
    wbR_corr = 0.7632653061;
201
236
    wbB_corr = 0.8591549296;
202
236
  }
203
204
13.8k
  FujiShotSelect = LIM(shot_select, 0, 1);
205
13.8k
  int average_WBData = 1;
206
207
13.8k
  order = 0x4d4d;
208
13.8k
  PrivateMknLength = get4();
209
210
  // At least 0x36 bytes because of memcpy(imFuji.RAFVersion, PrivateMknBuf + 0x32, 4);
211
13.8k
  if ((PrivateMknLength >= 0x36) && (PrivateMknLength < 10240000)) // 1024b for safety
212
13.7k
  {
213
13.7k
  fuji_wb_checked_buffer_t PrivateMknBuf(order, PrivateMknLength+1024);
214
13.7k
    fread(PrivateMknBuf.data(), PrivateMknLength, 1, ifp);
215
13.7k
    memcpy(imFuji.SerialSignature, PrivateMknBuf.data() + 6, 0x0c);
216
13.7k
    imFuji.SerialSignature[0x0c] = 0;
217
13.7k
    memcpy(imFuji.SensorID, imFuji.SerialSignature + 0x06, 0x04);
218
13.7k
    imFuji.SensorID[0x04] = 0;
219
13.7k
    c = 11;
220
14.4k
    while (isdigit(imFuji.SerialSignature[c]) && (c>0))
221
728
      c--;
222
13.7k
    ilm.CamID = unique_id = (unsigned long long)atoi(imFuji.SerialSignature+c+1);
223
13.7k
    memcpy(model, PrivateMknBuf.data() + 0x12, 0x20);
224
13.7k
    model[0x20] = 0;
225
13.7k
    memcpy(imFuji.RAFVersion, PrivateMknBuf.data() + 0x32, 4);
226
13.7k
    imFuji.RAFVersion[4] = 0;
227
228
13.7k
    PrivateOrder = PrivateMknBuf.sget2(0);
229
13.7k
    unsigned s, l;
230
13.7k
    s = ifd_start = PrivateMknBuf.sget4(2)+6;
231
13.7k
    l = ifd_len = PrivateMknBuf.sget4(ifd_start);
232
233
13.7k
  if (!PrivateMknBuf.sget4(ifd_start+ifd_len+4))
234
1.94k
      FujiShotSelect = 0;
235
236
13.7k
    if ((FujiShotSelect == 1) && (PrivateMknLength > ifd_len*2)) {
237
0
      ifd_start += (ifd_len+4);
238
0
      ifd_len = PrivateMknBuf.sget4(ifd_start);
239
0
      if ((ifd_start+ifd_len) > PrivateMknLength) {
240
0
        ifd_start = s;
241
0
        ifd_len = l;
242
0
        FujiShotSelect = 0;
243
0
      }
244
13.7k
    } else FujiShotSelect = 0;
245
246
13.7k
    PrivateEntries = PrivateMknBuf.sget4(ifd_start + 4);
247
13.7k
    if ((PrivateEntries > 1000) ||
248
12.1k
        ((PrivateOrder != 0x4d4d) && (PrivateOrder != 0x4949)))
249
703
    {
250
703
      return;
251
703
    }
252
13.0k
    posPrivateMknBuf = (ifd_start+8);
253
254
    /*
255
     * because Adobe DNG converter strips or misplaces 0xfnnn tags,
256
     * for now, Auto WB is missing for the following cameras:
257
     * - F550EXR / F600EXR / F770EXR / F800EXR / F900EXR
258
     * - HS10 / HS11 / HS20EXR / HS30EXR / HS33EXR / HS35EXR / HS50EXR
259
     * - S1 / SL1000
260
     **/
261
1.61M
    while (PrivateEntries--)
262
1.60M
    {
263
1.60M
    PrivateMknBuf.set_order(0x4d4d);
264
1.60M
    order = 0x4d4d;
265
1.60M
      PrivateTagID = PrivateMknBuf.sget2(posPrivateMknBuf);
266
1.60M
      PrivateTagBytes = PrivateMknBuf.sget2(posPrivateMknBuf + 2);
267
1.60M
      posPrivateMknBuf += 4;
268
1.60M
    PrivateMknBuf.set_order(PrivateOrder);
269
1.60M
    order = PrivateOrder;
270
271
1.60M
    if (PrivateTagID >= 0x2000 && PrivateTagID <= 0x2410)
272
4.16k
    {
273
32.8k
      for(int q = 0; q < tag2wbtable_size; q++)
274
31.3k
        if (tag2wbtable[q].tag == PrivateTagID)
275
2.69k
        {
276
2.69k
          get_average_WB(tag2wbtable[q].wb);
277
2.69k
          break;
278
2.69k
        }
279
4.16k
    }
280
1.59M
      else if (PrivateTagID == 0x2f00)
281
3.34k
      {
282
3.34k
        int nWBs = MIN(PrivateMknBuf.sget4(posPrivateMknBuf), 6);
283
3.34k
        posWB = posPrivateMknBuf + 4;
284
22.2k
        for (int wb_ind = LIBRAW_WBI_Custom1; wb_ind < LIBRAW_WBI_Custom1+nWBs; wb_ind++) {
285
75.7k
          FORC4 icWBC[wb_ind][GRGB_2_RGBG(c)] =
286
75.7k
        PrivateMknBuf.sget2(posWB + (c << 1));
287
18.9k
          if ((PrivateTagBytes >= unsigned(4+16*nWBs)) && average_WBData) {
288
162
            posWB += 8;
289
648
            FORC4 icWBC[wb_ind][GRGB_2_RGBG(c)] =
290
648
                    (icWBC[wb_ind][GRGB_2_RGBG(c)] +
291
648
            PrivateMknBuf.sget2(posWB + (c << 1))) /2;
292
162
          }
293
18.9k
          if (use_WBcorr_coeffs) {
294
3.76k
             icWBC[wb_ind][0] = int(icWBC[wb_ind][0]*wbR_corr);
295
3.76k
             icWBC[wb_ind][2] = int(icWBC[wb_ind][2]*wbB_corr);
296
3.76k
          }
297
18.9k
          posWB += 8;
298
18.9k
        }
299
3.34k
      }
300
1.59M
      else if (PrivateTagID == 0x2ff0)
301
2.24k
      {
302
2.24k
        get_average_WB(LIBRAW_WBI_AsShot);
303
8.99k
        FORC4 cam_mul[c] = float(icWBC[LIBRAW_WBI_AsShot][c]);
304
2.24k
      }
305
1.59M
      else if ((PrivateTagID == 0x4000) &&
306
780
               ((PrivateTagBytes == 8) || (PrivateTagBytes == 16)))
307
431
      {
308
431
        imFuji.BlackLevel[0] = PrivateTagBytes / 2;
309
1.72k
        FORC4 imFuji.BlackLevel[GRGB_2_RGBG(c)+1] =
310
1.72k
      PrivateMknBuf.sget2(posPrivateMknBuf + (c << 1));
311
431
        if (imFuji.BlackLevel[0] == 8) {
312
1.23k
          FORC4 imFuji.BlackLevel[GRGB_2_RGBG(c) + 5] =
313
1.23k
        PrivateMknBuf.sget2(posPrivateMknBuf + (c << 1) + 8);
314
308
        }
315
431
      }
316
1.59M
      else if (PrivateTagID == 0x9650)
317
97
      {
318
97
        short a = (short)PrivateMknBuf.sget2(posPrivateMknBuf);
319
97
        float b = fMAX(1.0f, PrivateMknBuf.sget2(posPrivateMknBuf + 2));
320
97
        imFuji.ExpoMidPointShift = a / b;
321
97
        imCommon.ExposureCalibrationShift += imFuji.ExpoMidPointShift;
322
97
      }
323
1.59M
      else if ((PrivateTagID == 0xc000) && (PrivateTagBytes > 3) &&
324
11.7k
               (PrivateTagBytes < 10240000))
325
11.7k
      {
326
11.7k
    PrivateMknBuf.set_order(0x4949);
327
11.7k
    order = 0x4949;
328
11.7k
        if (PrivateTagBytes != 4096) // not one of Fuji X-A3, X-A5, X-A7, X-A10, X-A20, X-T100, X-T200, XF10
329
11.1k
        {
330
11.1k
          int is34 = 0;
331
11.1k
      PrivateMknBuf.checkoffset(posPrivateMknBuf + 8); // will raise exception if no space
332
11.1k
          guess_RAFDataGeneration (PrivateMknBuf.data() + posPrivateMknBuf);
333
334
// printf (">> ID: 0x%llx, RAFDataVersion: 0x%04x, RAFDataGeneration: %d\n",
335
// ilm.CamID, imFuji.RAFDataVersion, imFuji.RAFDataGeneration);
336
337
21.4M
          for (posWB = 0; posWB < (int)PrivateTagBytes - 16; posWB++)
338
21.4M
          {
339
21.4M
            PrivateMknBuf.checkoffset(posWB + 12); // will raise exception if no space
340
21.4M
            if ((!memcmp(PrivateMknBuf.data() + posWB, "TSNERDTS", 8) &&
341
392
                 (PrivateMknBuf.sget2( posWB + 10) > 125)))
342
340
            {
343
340
              posWB += 10;
344
340
              icWBC[LIBRAW_WBI_Auto][1] =
345
340
                  icWBC[LIBRAW_WBI_Auto][3] =
346
340
          PrivateMknBuf.sget2(posWB);
347
340
              icWBC[LIBRAW_WBI_Auto][0] =
348
340
          PrivateMknBuf.sget2(posWB + 2);
349
340
              icWBC[LIBRAW_WBI_Auto][2] =
350
340
          PrivateMknBuf.sget2(posWB + 4);
351
340
              break;
352
340
            }
353
21.4M
          }
354
355
11.1k
          if ((imFuji.RAFDataVersion == 0x0260) || // X-Pro3, GFX 100S
356
10.8k
              (imFuji.RAFDataVersion == 0x0261) || // X100V, GFX 50S II
357
10.8k
              (imFuji.RAFDataVersion == 0x0262) || // X-T4
358
10.7k
              (imFuji.RAFDataVersion == 0x0263) || // X-H2s
359
10.7k
              (imFuji.RAFDataVersion == 0x0264) || // X-S10, X-H2
360
10.6k
              (imFuji.RAFDataVersion == 0x0265) || // X-E4, X-T5
361
10.5k
              (imFuji.RAFDataVersion == 0x0266) || // X-T30 II
362
10.2k
              (imFuji.RAFDataVersion == 0x0267) || // GFX 100 II
363
10.1k
              (imFuji.RAFDataVersion == 0x0368) || // GFX 100S II
364
10.1k
              (imFuji.RAFDataVersion == 0x0369) || // X100VI
365
9.65k
              (imFuji.RAFDataVersion == 0x036a) || // X-T50
366
9.65k
              (imFuji.RAFDataVersion == 0x036b) || // X-M5
367
9.62k
                !strcmp(model, "X-Pro3")      ||
368
9.53k
                !strcmp(model, "GFX 100S II") || !strcmp(model, "GFX100S II") ||
369
9.50k
                !strcmp(model, "GFX 100S")    || !strcmp(model, "GFX100S")    ||
370
9.43k
                !strcmp(model, "GFX 100 II")  || !strcmp(model, "GFX100 II")  ||
371
9.34k
                !strcmp(model, "GFX 50S II")  || !strcmp(model, "GFX50S II")  ||
372
9.33k
                !strcmp(model, "X100VI")      ||
373
9.24k
                !strcmp(model, "X100V")       ||
374
9.20k
                !strcmp(model, "X-H2")        ||
375
9.01k
                !strcmp(model, "X-H2S")       ||
376
8.88k
                !strcmp(model, "X-T4")        ||
377
8.79k
                !strcmp(model, "X-T50")       ||
378
8.69k
                !strcmp(model, "X-T5")        ||
379
8.57k
                !strcmp(model, "X-M5")        ||
380
8.52k
                !strcmp(model, "X-E4")        ||
381
8.50k
                !strcmp(model, "X-T30 II")    ||
382
8.41k
                !strcmp(model, "X-S10"))
383
2.56k
            is34 = 1;
384
385
11.1k
          if (imFuji.RAFDataVersion == 0x4500) // X-E1, RAFData gen. 3
386
66
          {
387
66
            wb_section_offset = 0x13ac;
388
66
          }
389
11.0k
          else if (imFuji.RAFDataVersion == 0x0146 || // X20
390
10.7k
                   imFuji.RAFDataVersion == 0x0149 || // X100S
391
10.6k
                   imFuji.RAFDataVersion == 0x0249)   // X100S
392
153
          {
393
153
            wb_section_offset = 0x1410;
394
153
          }
395
10.9k
          else if (imFuji.RAFDataVersion == 0x014d || // X-M1
396
10.6k
                   imFuji.RAFDataVersion == 0x014e)   // X-A1, X-A2
397
96
          {
398
96
            wb_section_offset = 0x1474;
399
96
          }
400
10.8k
          else if (imFuji.RAFDataVersion == 0x014f || // X-E2
401
10.4k
                   imFuji.RAFDataVersion == 0x024f || // X-E2
402
9.78k
                   imFuji.RAFDataVersion == 0x025d || // X-H1
403
9.75k
                   imFuji.RAFDataVersion == 0x035d)   // X-H1
404
866
          {
405
866
            wb_section_offset = 0x1480;
406
866
          }
407
9.95k
          else if (imFuji.RAFDataVersion == 0x0150) // XQ1, XQ2
408
79
          {
409
79
            wb_section_offset = 0x1414;
410
79
          }
411
9.87k
          else if (imFuji.RAFDataVersion == 0x0151 || // X-T1 w/diff. fws
412
9.60k
                   imFuji.RAFDataVersion == 0x0251 || imFuji.RAFDataVersion == 0x0351 ||
413
9.54k
                   imFuji.RAFDataVersion == 0x0451 || imFuji.RAFDataVersion == 0x0551)
414
121
          {
415
121
            wb_section_offset = 0x14b0;
416
121
          }
417
9.75k
          else if (imFuji.RAFDataVersion == 0x0152 || // X30
418
9.45k
                   imFuji.RAFDataVersion == 0x0153)   // X100T
419
89
          {
420
89
            wb_section_offset = 0x1444;
421
89
          }
422
9.66k
          else if (imFuji.RAFDataVersion == 0x0154) // X-T10
423
19
          {
424
19
            wb_section_offset = 0x1824;
425
19
          }
426
9.64k
          else if (imFuji.RAFDataVersion == 0x0155) // X70
427
18
          {
428
18
            wb_section_offset = 0x17b4;
429
18
          }
430
9.62k
          else if (imFuji.RAFDataVersion == 0x0255 || // X-Pro2
431
9.36k
                   imFuji.RAFDataVersion == 0x0455)
432
52
          {
433
52
            wb_section_offset = 0x135c;
434
52
          }
435
9.57k
          else if (imFuji.RAFDataVersion == 0x0258 || // X-T2
436
9.12k
                   imFuji.RAFDataVersion == 0x025b)   // X-T20
437
217
          {
438
217
            wb_section_offset = 0x13dc;
439
217
          }
440
9.35k
          else if (imFuji.RAFDataVersion == 0x0259) // X100F
441
77
          {
442
77
            wb_section_offset = 0x1370;
443
77
          }
444
9.28k
          else if (imFuji.RAFDataVersion == 0x025a || // GFX 50S
445
9.01k
                   imFuji.RAFDataVersion == 0x045a)
446
58
          {
447
58
            wb_section_offset = 0x1424;
448
58
         }
449
9.22k
          else if (imFuji.RAFDataVersion == 0x025c) // X-E3
450
48
          {
451
48
            wb_section_offset = 0x141c;
452
48
          }
453
9.17k
          else if (imFuji.RAFDataVersion == 0x025e) // X-T3
454
31
          {
455
31
            wb_section_offset = 0x2014;
456
31
          }
457
9.14k
          else if (imFuji.RAFDataVersion == 0x025f) // X-T30, GFX 50R, GFX 100 (? RAFDataVersion 0x045f)
458
364
          {
459
364
            if (!strcmp(model, "X-T30")) {
460
235
              if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x20b8))
461
0
                wb_section_offset = 0x20b8;
462
235
              else if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x20c8))
463
0
            wb_section_offset = 0x20c8;
464
235
            }
465
129
            else if (!strcmp(model, "GFX 50R"))
466
13
              wb_section_offset = 0x1424;
467
116
            else if (!strcmp(model, "GFX 100"))
468
25
              wb_section_offset = 0x20e4;
469
364
          }
470
8.78k
          else if (imFuji.RAFDataVersion == 0x0260) // X-Pro3, GFX 100S
471
40
          {
472
40
           if (!strcmp(model, "X-Pro3"))
473
0
              wb_section_offset = 0x20e8;
474
40
            else if (!strcmp(model, "GFX 100S") || !strcmp(model, "GFX100S"))
475
0
              wb_section_offset = 0x2108;
476
40
          }
477
8.74k
          else if (imFuji.RAFDataVersion == 0x0261) // X100V, GFX 50S II
478
41
          {
479
41
            if (!strcmp(model, "X100V"))
480
0
              wb_section_offset = 0x2078;
481
41
            else if (!strcmp(model, "GFX 50S II") || !strcmp(model, "GFX50S II"))
482
0
              wb_section_offset = 0x214c;
483
41
          }
484
8.70k
          else if (imFuji.RAFDataVersion == 0x0262) // X-T4
485
67
          {
486
67
            if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x21c8))
487
0
              wb_section_offset = 0x21c8;
488
67
            else if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x21cc))
489
0
              wb_section_offset = 0x21cc;
490
67
          }
491
8.63k
          else if (imFuji.RAFDataVersion == 0x0263) // X-H2S
492
11
          {
493
11
            wb_section_offset = 0x0b40;
494
11
          }
495
8.62k
          else if (imFuji.RAFDataVersion == 0x0264) // X-S10, X-H2
496
95
          {
497
95
            if (!strcmp(model, "X-S10"))
498
43
              wb_section_offset = 0x21de;
499
52
            else if (!strcmp(model, "X-H2"))
500
20
              wb_section_offset = 0x0b3e;
501
95
          }
502
8.52k
          else if ((imFuji.RAFDataVersion == 0x0265)  || // X-E4, X-T5
503
8.16k
                   (imFuji.RAFDataVersion == 0x0266))    // X-T30 II, X-S20
504
369
          {
505
369
            if (!strcmp(model, "X-T5") ||
506
330
                !strcmp(model, "X-S20"))
507
50
              wb_section_offset = 0x0c72;
508
319
            else
509
319
              wb_section_offset = 0x21cc;
510
369
          }
511
8.15k
          else if (imFuji.RAFDataVersion == 0x0267) // GFX 100 II
512
89
          {
513
89
            wb_section_offset = 0x0cae;
514
89
          }
515
8.06k
          else if (imFuji.RAFDataVersion == 0x0355) // X-E2S
516
69
          {
517
69
            wb_section_offset = 0x1840;
518
69
          }
519
8.00k
          else if (imFuji.RAFDataVersion == 0x0368) // GFX 100S II
520
62
          {
521
62
            wb_section_offset = 0x0cba;
522
62
          }
523
7.93k
          else if (imFuji.RAFDataVersion == 0x0369) // X100VI
524
463
          {
525
463
            wb_section_offset = 0x0c5a;
526
463
          }
527
7.47k
          else if (imFuji.RAFDataVersion == 0x036a) // X-T50
528
0
          {
529
0
            wb_section_offset = 0x0cca;
530
0
          }
531
7.47k
          else if (imFuji.RAFDataVersion == 0x036b) // X-M5
532
28
          {
533
28
            wb_section_offset = 0x0cea;
534
28
          }
535
536
/* try for unknown RAF Data versions */
537
7.44k
          else if (!strcmp(model, "X-Pro2"))
538
189
          {
539
189
            if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x135c))
540
84
              wb_section_offset = 0x135c;
541
189
          }
542
7.25k
          else if (!strcmp(model, "X100F"))
543
60
          {
544
60
            if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x1370))
545
9
              wb_section_offset = 0x1370;
546
60
          }
547
7.19k
          else if (!strcmp(model, "X-E1"))
548
106
          {
549
106
            if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x13ac))
550
22
              wb_section_offset = 0x13ac;
551
106
          }
552
7.09k
          else if (!strcmp(model, "X-T2") ||
553
6.72k
                   !strcmp(model, "X-T20"))
554
140
          {
555
140
            if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x13dc))
556
1
              wb_section_offset = 0x13dc;
557
140
          }
558
6.95k
          else if (!strcmp(model, "X20") ||
559
5.98k
                   !strcmp(model, "X100S"))
560
800
          {
561
800
            if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x1410))
562
90
              wb_section_offset = 0x1410;
563
800
          }
564
6.15k
          else if (!strcmp(model, "XQ1") ||
565
5.74k
                   !strcmp(model, "XQ2"))
566
254
          {
567
254
            if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x1414))
568
75
              wb_section_offset = 0x1414;
569
254
          }
570
5.89k
          else if (!strcmp(model, "X-E3"))
571
103
          {
572
103
            if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x141c))
573
11
              wb_section_offset = 0x141c;
574
103
          }
575
5.79k
          else if (!strcmp(model, "GFX 50S") ||
576
5.47k
                   !strcmp(model, "GFX 50R"))
577
222
          {
578
222
            if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x1424))
579
62
              wb_section_offset = 0x1424;
580
222
          }
581
5.57k
          else if (!strcmp(model, "GFX 50S II") ||
582
5.31k
                   !strcmp(model, "GFX50S II")) {
583
10
            if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x214c))
584
0
              wb_section_offset = 0x214c;
585
10
          }
586
5.56k
          else if (!strcmp(model, "X30") ||
587
5.26k
                   !strcmp(model, "X100T"))
588
147
          {
589
147
            if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x1444))
590
0
              wb_section_offset = 0x1444;
591
147
          }
592
5.41k
          else if (!strcmp(model, "X-M1") ||
593
5.03k
                   !strcmp(model, "X-A1") ||
594
4.79k
                   !strcmp(model, "X-A2"))
595
487
          {
596
487
            if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x1474))
597
35
              wb_section_offset = 0x1474;
598
487
          }
599
4.92k
          else if (!strcmp(model, "X-E2") ||
600
4.67k
                   !strcmp(model, "X-H1"))
601
84
          {
602
84
            if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x1480))
603
0
              wb_section_offset = 0x1480;
604
84
          }
605
4.84k
          else if (!strcmp(model, "X-T1"))
606
120
          {
607
120
            if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x14b0))
608
3
              wb_section_offset = 0x14b0;
609
120
          }
610
4.72k
          else if (!strcmp(model, "X70"))
611
161
          {
612
161
            if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x17b4))
613
60
              wb_section_offset = 0x17b4;
614
161
          }
615
4.56k
          else if (!strcmp(model, "X-T10"))
616
56
          {
617
56
            if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x1824))
618
17
              wb_section_offset = 0x1824;
619
56
          }
620
4.50k
          else if (!strcmp(model, "X-E2S"))
621
67
          {
622
67
            if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x1840))
623
11
              wb_section_offset = 0x1840;
624
67
          }
625
4.44k
          else if (!strcmp(model, "X-T3"))
626
38
          {
627
38
            if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x2014))
628
0
              wb_section_offset = 0x2014;
629
38
          }
630
4.40k
          else if (!strcmp(model, "X100VI"))
631
89
          {
632
89
            if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x0c5a))
633
45
              wb_section_offset = 0x0c5a;
634
89
          }
635
4.31k
          else if (!strcmp(model, "X100V"))
636
39
          {
637
39
            if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x2078))
638
0
              wb_section_offset = 0x2078;
639
39
          }
640
4.27k
          else if (!strcmp(model, "X-T30"))
641
195
          {
642
195
            if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x20b8))
643
0
              wb_section_offset = 0x20b8;
644
195
            else if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x20c8))
645
0
              wb_section_offset = 0x20c8;
646
195
          }
647
4.08k
          else if (!strcmp(model, "GFX 100"))
648
147
          {
649
147
            if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x20e4))
650
0
              wb_section_offset = 0x20e4;
651
147
          }
652
3.93k
          else if (!strcmp(model, "X-Pro3"))
653
87
          {
654
87
            if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x20e8))
655
0
              wb_section_offset = 0x20e8;
656
87
          }
657
3.84k
          else if (!strcmp(model, "GFX100S") ||
658
3.59k
                   !strcmp(model, "GFX 100S"))
659
67
          {
660
67
            if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x2108))
661
0
              wb_section_offset = 0x2108;
662
67
          }
663
3.77k
          else if (!strcmp(model, "X-T4"))
664
86
          {
665
86
            if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x21c8))
666
0
              wb_section_offset = 0x21c8;
667
86
            else if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x21cc))
668
0
              wb_section_offset = 0x21cc;
669
86
          }
670
3.69k
          else if ((!strcmp(model, "X-E4"))       ||
671
3.43k
                   (!strcmp(model, "X-T30 II")))
672
67
          {
673
67
            if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x21cc))
674
0
              wb_section_offset = 0x21cc;
675
67
          }
676
3.62k
          else if (!strcmp(model, "X-S10"))
677
62
          {
678
62
            if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x21de))
679
0
              wb_section_offset = 0x21de;
680
62
          }
681
3.56k
          else if (!strcmp(model, "X-H2"))
682
193
          {
683
193
            if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x0b3e))
684
18
              wb_section_offset = 0x0b3e;
685
193
          }
686
3.37k
          else if (!strcmp(model, "X-H2S"))
687
130
          {
688
130
            if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x0b40))
689
4
              wb_section_offset = 0x0b40;
690
130
          }
691
3.24k
          else if (!strcmp(model, "X-T5") ||
692
2.88k
                   !strcmp(model, "X-S20"))
693
162
          {
694
162
            if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x0c72))
695
72
              wb_section_offset = 0x0c72;
696
162
          }
697
3.07k
          else if (!strcmp(model, "GFX 100 II") ||
698
2.74k
                   !strcmp(model, "GFX100 II"))
699
94
          {
700
94
            if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x0cae))
701
4
              wb_section_offset = 0x0cae;
702
94
          }
703
2.98k
          else if (!strcmp(model, "GFX 100S II") ||
704
2.74k
                   !strcmp(model, "GFX100S II"))
705
34
          {
706
34
            if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x0cba))
707
0
              wb_section_offset = 0x0cba;
708
34
          }
709
2.95k
          else if (!strcmp(model, "X-T50"))
710
20
          {
711
20
            if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x0cca))
712
0
              wb_section_offset = 0x0cca;
713
20
          }
714
2.93k
          else if (!strcmp(model, "X-M5"))
715
56
          {
716
56
            if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x0cea))
717
6
              wb_section_offset = 0x0cea;
718
56
          }
719
720
/* no RAF Data version for the models below */
721
2.87k
          else if (!strcmp(model, "FinePix X100")) // X100 0 0x19f0 0x19e8
722
291
          {
723
291
            if (!strcmp(imFuji.RAFVersion, "0069"))
724
90
              wb_section_offset = 0x19e8;
725
201
            else if (!strcmp(imFuji.RAFVersion, "0100") ||
726
125
                     !strcmp(imFuji.RAFVersion, "0110"))
727
97
              wb_section_offset = 0x19f0;
728
104
      else
729
104
      {
730
104
        if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x19e8))
731
32
          wb_section_offset = 0x19e8;
732
72
                else if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x19f0))
733
0
                  wb_section_offset = 0x19f0;
734
104
      }
735
291
          }
736
2.58k
          else if (!strcmp(model, "X-Pro1")) // X-Pro1 0 0x13a4
737
393
          {
738
393
            if (!strcmp(imFuji.RAFVersion, "0100") ||
739
311
                !strcmp(imFuji.RAFVersion, "0101") ||
740
238
                !strcmp(imFuji.RAFVersion, "0204"))
741
174
              wb_section_offset = 0x13a4;
742
219
            else if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x13a4))
743
44
              wb_section_offset = 0x13a4;
744
393
          }
745
2.19k
          else if (!strcmp(model, "XF1")) // XF1 0 0x138c
746
265
          {
747
265
            if (!strcmp(imFuji.RAFVersion, "0100"))
748
82
              wb_section_offset = 0x138c;
749
183
            else if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x138c))
750
71
              wb_section_offset = 0x138c;
751
265
          }
752
1.92k
          else if (!strcmp(model, "X-S1")) // X-S1 0 0x1284
753
61
          {
754
61
            if (!strcmp(imFuji.RAFVersion, "0100"))
755
17
              wb_section_offset = 0x1284;
756
44
            else if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x1284))
757
11
              wb_section_offset = 0x1284;
758
61
          }
759
1.86k
          else if (!strcmp(model, "X10")) // X10 0 0x1280 0x12d4
760
1.19k
          {
761
1.19k
            if (!strcmp(imFuji.RAFVersion, "0100") ||
762
1.13k
                !strcmp(imFuji.RAFVersion, "0102"))
763
73
              wb_section_offset = 0x1280;
764
1.11k
            else if (!strcmp(imFuji.RAFVersion, "0103"))
765
79
              wb_section_offset = 0x12d4;
766
1.03k
            else if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x1280))
767
57
          wb_section_offset = 0x1280;
768
982
            else if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x12d4))
769
63
              wb_section_offset = 0x12d4;
770
1.19k
          }
771
674
          else if (!strcmp(model, "XF1")) // XF1 0 0x138c
772
0
          {
773
0
            if (!strcmp(imFuji.RAFVersion, "0100"))
774
0
              wb_section_offset = 0x138c;
775
0
            else if (PrivateMknBuf.isWB(posPrivateMknBuf + 0x138c))
776
0
              wb_section_offset = 0x138c;
777
0
          }
778
779
11.1k
          if (wb_section_offset && PrivateMknBuf.isWB(posPrivateMknBuf + wb_section_offset))
780
908
          {
781
782
908
            if (!imFuji.RAFDataVersion)
783
692
            {
784
692
              posWB = posPrivateMknBuf + wb_section_offset - 6;
785
692
              icWBC[LIBRAW_WBI_Auto][1] = icWBC[LIBRAW_WBI_Auto][3] = PrivateMknBuf.sget2(posWB);
786
692
              icWBC[LIBRAW_WBI_Auto][0] = PrivateMknBuf.sget2(posWB + 2);
787
692
              icWBC[LIBRAW_WBI_Auto][2] = PrivateMknBuf.sget2(posWB + 4);
788
692
            }
789
790
908
            posWB = posPrivateMknBuf + wb_section_offset;
791
6.35k
            for (int wb_ind = 0; wb_ind < (int)Fuji_wb_list1.size(); posWB += 6, wb_ind++)
792
5.44k
            {
793
5.44k
              icWBC[Fuji_wb_list1[wb_ind]][1] = icWBC[Fuji_wb_list1[wb_ind]][3] = PrivateMknBuf.sget2(posWB);
794
5.44k
              icWBC[Fuji_wb_list1[wb_ind]][0] = PrivateMknBuf.sget2(posWB + 2);
795
5.44k
              icWBC[Fuji_wb_list1[wb_ind]][2] = PrivateMknBuf.sget2(posWB + 4);
796
5.44k
            }
797
908
            int found = 0;
798
908
            if (is34)
799
143
              posWB += 0x30;
800
908
            posWB += 0xc0;
801
908
            ushort Gval = PrivateMknBuf.sget2(posWB);
802
3.73k
            for (int posEndCCTsection = posWB; posEndCCTsection < (posWB + 30);
803
2.82k
                 posEndCCTsection += 6)
804
3.26k
            {
805
3.26k
              if (PrivateMknBuf.sget2(posEndCCTsection) != Gval)
806
441
              {
807
441
                if (is34)
808
127
                  wb_section_offset = posEndCCTsection - 34*3*2; // 34 records, 3 2-byte values in a record
809
314
                else
810
314
                  wb_section_offset = posEndCCTsection - 31*3*2; // 31 records, 3 2-byte values in a record
811
441
                found = 1;
812
441
                break;
813
441
              }
814
3.26k
            }
815
816
908
            if (found)
817
441
            {
818
14.1k
              for (int iCCT = 0; iCCT < 31; iCCT++)
819
13.6k
              {
820
13.6k
                icWBCCTC[iCCT][0] = float(FujiCCT_K[iCCT]);
821
13.6k
                icWBCCTC[iCCT][1] = PrivateMknBuf.sget2(wb_section_offset + iCCT * 6 + 2);
822
13.6k
                icWBCCTC[iCCT][2] = icWBCCTC[iCCT][4] = PrivateMknBuf.sget2(wb_section_offset + iCCT * 6);
823
13.6k
                icWBCCTC[iCCT][3] = PrivateMknBuf.sget2(wb_section_offset + iCCT * 6 + 4);
824
13.6k
              }
825
441
            }
826
908
          }
827
11.1k
        }
828
568
        else // process 4K raf data
829
568
        {
830
568
          int wb[4];
831
568
          int nWB, tWB, pWB;
832
568
          int iCCT = 0;
833
568
          imFuji.RAFDataGeneration = 4096; // X-A3, X-A5, X-A7, X-A10, X-A20, X-T100, X-T200, XF10
834
568
          posWB = posPrivateMknBuf + 0x200;
835
23.4k
          for (int wb_ind = 0; wb_ind < 42; wb_ind++)
836
22.8k
          {
837
22.8k
            nWB = PrivateMknBuf.sget4(posWB);
838
22.8k
            posWB += 4;
839
22.8k
            tWB = PrivateMknBuf.sget4(posWB);
840
22.8k
            posWB += 4;
841
22.8k
            wb[0] = PrivateMknBuf.sget4(posWB) << 1;
842
22.8k
            posWB += 4;
843
22.8k
            wb[1] = PrivateMknBuf.sget4(posWB);
844
22.8k
            posWB += 4;
845
22.8k
            wb[3] = PrivateMknBuf.sget4(posWB);
846
22.8k
            posWB += 4;
847
22.8k
            wb[2] = PrivateMknBuf.sget4(posWB) << 1;
848
22.8k
            posWB += 4;
849
850
22.8k
            if (tWB && (iCCT < 64))
851
13.9k
            {
852
13.9k
              icWBCCTC[iCCT][0] = float(tWB);
853
55.6k
              FORC4 icWBCCTC[iCCT][c + 1] = float(wb[c]);
854
13.9k
              iCCT++;
855
13.9k
            }
856
22.8k
            if (nWB != 0x46)
857
22.6k
            {
858
165k
              for (pWB = 1; pWB < (int)Fuji_wb_list2.size(); pWB += 2)
859
152k
              {
860
152k
                if (Fuji_wb_list2[pWB] == nWB)
861
9.75k
                {
862
39.0k
                  FORC4 icWBC[Fuji_wb_list2[pWB - 1]][c] = wb[c];
863
9.75k
                  break;
864
9.75k
                }
865
152k
              }
866
22.6k
            }
867
22.8k
          }
868
568
        }
869
11.7k
      }
870
1.60M
      posPrivateMknBuf += PrivateTagBytes;
871
1.60M
    }
872
13.0k
  }
873
13.8k
#undef get_average_WB
874
13.8k
}
875
876
void LibRaw::parseFujiMakernotes(unsigned tag, unsigned type, unsigned len,
877
                                 unsigned /*dng_writer*/)
878
178k
{
879
178k
  if (tag == 0x0010)
880
6.67k
  {
881
6.67k
    char FujiSerial[sizeof(imgdata.shootinginfo.InternalBodySerial)];
882
6.67k
  char *words[4] = { 0,0,0,0 };
883
6.67k
    char yy[2], mm[3], dd[3], ystr[16], ynum[16];
884
6.67k
    int year, nwords, ynum_len;
885
6.67k
    unsigned c;
886
6.67k
    memset(FujiSerial, 0, sizeof(imgdata.shootinginfo.InternalBodySerial));
887
6.67k
    ifp->read(FujiSerial, MIN(len,sizeof(FujiSerial)), 1);
888
6.67k
    nwords = getwords(FujiSerial, words, 4,
889
6.67k
                      sizeof(imgdata.shootinginfo.InternalBodySerial));
890
12.4k
    for (int i = 0; i < nwords; i++)
891
5.75k
    {
892
5.75k
    if (!words[i]) break;  // probably damaged input
893
5.75k
      mm[2] = dd[2] = 0;
894
5.75k
      if (strnlen(words[i],
895
5.75k
                  sizeof(imgdata.shootinginfo.InternalBodySerial) - 1) < 18)
896
2.86k
      {
897
2.86k
        if (i == 0)
898
1.91k
        {
899
1.91k
          strncpy(imgdata.shootinginfo.InternalBodySerial, words[0],
900
1.91k
                  sizeof(imgdata.shootinginfo.InternalBodySerial) - 1);
901
1.91k
        }
902
956
        else
903
956
        {
904
956
          char tbuf[sizeof(imgdata.shootinginfo.InternalBodySerial)];
905
956
          snprintf(tbuf, sizeof(tbuf)-1, "%s %s",
906
956
                   imgdata.shootinginfo.InternalBodySerial, words[i]);
907
956
          strncpy(imgdata.shootinginfo.InternalBodySerial, tbuf,
908
956
                  sizeof(imgdata.shootinginfo.InternalBodySerial) - 1);
909
956
        }
910
2.86k
      }
911
2.88k
      else
912
2.88k
      {
913
2.88k
        strncpy(
914
2.88k
            dd,
915
2.88k
            words[i] +
916
2.88k
                strnlen(words[i],
917
2.88k
                        sizeof(imgdata.shootinginfo.InternalBodySerial) - 1) -
918
2.88k
                14,
919
2.88k
            2);
920
2.88k
        strncpy(
921
2.88k
            mm,
922
2.88k
            words[i] +
923
2.88k
                strnlen(words[i],
924
2.88k
                        sizeof(imgdata.shootinginfo.InternalBodySerial) - 1) -
925
2.88k
                16,
926
2.88k
            2);
927
2.88k
        strncpy(
928
2.88k
            yy,
929
2.88k
            words[i] +
930
2.88k
                strnlen(words[i],
931
2.88k
                        sizeof(imgdata.shootinginfo.InternalBodySerial) - 1) -
932
2.88k
                18,
933
2.88k
            2);
934
2.88k
        year = (yy[0] - '0') * 10 + (yy[1] - '0');
935
2.88k
        if (year < 70)
936
2.51k
          year += 2000;
937
376
        else
938
376
          year += 1900;
939
940
2.88k
        ynum_len = MIN(
941
2.88k
            int(sizeof(ynum) - 1),
942
2.88k
            (int)strnlen(words[i],
943
2.88k
                         sizeof(imgdata.shootinginfo.InternalBodySerial) - 1) -
944
2.88k
                18);
945
2.88k
        strncpy(ynum, words[i], ynum_len);
946
2.88k
        ynum[ynum_len] = 0;
947
4.29k
        for (int j = 0; ynum[j] && ynum[j + 1] && sscanf(ynum + j, "%2x", &c);
948
2.88k
             j += 2)
949
1.41k
          ystr[j / 2] = c;
950
2.88k
        ynum_len /= 2;
951
2.88k
        ystr[ynum_len + 1] = 0;
952
2.88k
        strcpy(model2, ystr);
953
954
2.88k
        if (i == 0)
955
1.87k
        {
956
1.87k
          char tbuf[sizeof(imgdata.shootinginfo.InternalBodySerial)];
957
958
1.87k
          if (nwords == 1)
959
1.21k
          {
960
1.21k
            snprintf(
961
1.21k
              tbuf, sizeof(tbuf), "%s %d:%s:%s %s",
962
1.21k
              ystr, year, mm, dd,
963
1.21k
              words[0] +
964
1.21k
                strnlen(words[0], sizeof(imgdata.shootinginfo.InternalBodySerial)-1)-12);
965
1.21k
          }
966
657
          else
967
657
          {
968
657
            snprintf(
969
657
                tbuf, sizeof(tbuf), "%s %d:%s:%s %s", ystr, year, mm, dd,
970
657
                words[0] +
971
657
                    strnlen(words[0],
972
657
                            sizeof(imgdata.shootinginfo.InternalBodySerial) -
973
657
                                1) -
974
657
                    12);
975
657
          }
976
1.87k
          strncpy(imgdata.shootinginfo.InternalBodySerial, tbuf,
977
1.87k
                  sizeof(imgdata.shootinginfo.InternalBodySerial) - 1);
978
1.87k
        }
979
1.01k
        else
980
1.01k
        {
981
1.01k
          char tbuf[sizeof(imgdata.shootinginfo.InternalBodySerial)];
982
1.01k
          snprintf(
983
1.01k
              tbuf, sizeof(tbuf), "%s %s %d:%s:%s %s",
984
1.01k
              imgdata.shootinginfo.InternalBodySerial, ystr, year, mm, dd,
985
1.01k
              words[i] +
986
1.01k
                  strnlen(words[i],
987
1.01k
                          sizeof(imgdata.shootinginfo.InternalBodySerial) - 1) -
988
1.01k
                  12);
989
1.01k
          strncpy(imgdata.shootinginfo.InternalBodySerial, tbuf,
990
1.01k
                  sizeof(imgdata.shootinginfo.InternalBodySerial) - 1);
991
1.01k
        }
992
2.88k
      }
993
5.75k
    }
994
6.67k
  }
995
171k
  else
996
171k
    switch (tag)
997
171k
    {
998
222
    case 0x1002:
999
222
      imFuji.WB_Preset = get2();
1000
222
      break;
1001
190
    case 0x1011:
1002
190
      imCommon.FlashEC = getrealf(type);
1003
190
      break;
1004
574
    case 0x1020:
1005
574
      imFuji.Macro = get2();
1006
574
      break;
1007
381
    case 0x1021:
1008
381
      imFuji.FocusMode = imgdata.shootinginfo.FocusMode = get2();
1009
381
      break;
1010
979
    case 0x1022:
1011
979
      imFuji.AFMode = get2();
1012
979
      break;
1013
614
    case 0x1023:
1014
614
      imFuji.FocusPixel[0] = get2();
1015
614
      imFuji.FocusPixel[1] = get2();
1016
614
      break;
1017
390
    case 0x102b:
1018
390
      imFuji.PrioritySettings = get2();
1019
390
      break;
1020
132
    case 0x102d:
1021
132
      imFuji.FocusSettings = get4();
1022
132
      break;
1023
50
    case 0x102e:
1024
50
      imFuji.AF_C_Settings = get4();
1025
50
      break;
1026
304
    case 0x1034:
1027
304
      imFuji.ExrMode = get2();
1028
304
      break;
1029
217
    case 0x104d:
1030
217
      FujiCropMode = get2(); // odd: one of raw dimensions here can be lost
1031
217
      break;
1032
396
    case 0x1050:
1033
396
      imFuji.ShutterType = get2();
1034
396
      break;
1035
118
    case 0x1100:
1036
118
      imFuji.AutoBracketing = get2(); // AutoBracketing = 6 for pixel shift mode
1037
118
      break;
1038
792
    case 0x1101:
1039
792
      imFuji.SequenceNumber = get2();
1040
792
      break;
1041
76
    case 0x1103:
1042
76
      imgdata.shootinginfo.DriveMode = get2();
1043
76
      imFuji.DriveMode = imgdata.shootinginfo.DriveMode & 0xff;
1044
76
      break;
1045
86
    case 0x1105:
1046
86
      imFuji.SeriesLength = get2();
1047
86
      break;
1048
251
    case 0x1106:
1049
251
      imFuji.PixelShiftOffset[0] = getrealf(type);
1050
251
      imFuji.PixelShiftOffset[1] = getrealf(type);
1051
251
      break;
1052
245
    case 0x1301:
1053
245
      imFuji.FocusWarning = get2();
1054
245
      break;
1055
340
    case 0x1400:
1056
340
      imFuji.DynamicRange = get2();
1057
340
      break;
1058
206
    case 0x1401:
1059
206
      imFuji.FilmMode = get2();
1060
206
      break;
1061
768
    case 0x1402:
1062
768
      imFuji.DynamicRangeSetting = get2();
1063
768
      break;
1064
90
    case 0x1403:
1065
90
      imFuji.DevelopmentDynamicRange = get2();
1066
90
      break;
1067
960
    case 0x1404:
1068
960
      ilm.MinFocal = getrealf(type);
1069
960
      break;
1070
200
    case 0x1405:
1071
200
      ilm.MaxFocal = getrealf(type);
1072
200
      break;
1073
169
    case 0x1406:
1074
169
      ilm.MaxAp4MinFocal = getrealf(type);
1075
169
      break;
1076
9
    case 0x1407:
1077
9
      ilm.MaxAp4MaxFocal = getrealf(type);
1078
9
      break;
1079
286
    case 0x140b:
1080
286
      imFuji.AutoDynamicRange = get2();
1081
286
      break;
1082
261
    case 0x1422:
1083
261
      imFuji.ImageStabilization[0] = get2();
1084
261
      imFuji.ImageStabilization[1] = get2();
1085
261
      imFuji.ImageStabilization[2] = get2();
1086
261
      imgdata.shootinginfo.ImageStabilization =
1087
261
          (imFuji.ImageStabilization[0] << 9) + imFuji.ImageStabilization[1];
1088
261
      break;
1089
100
    case 0x1438:
1090
100
      imFuji.ImageCount = get2();
1091
100
      break;
1092
169
    case 0x1431:
1093
169
      imFuji.Rating = get4();
1094
169
      break;
1095
135
    case 0x1443:
1096
135
      imFuji.DRangePriority = get2();
1097
135
      break;
1098
131
    case 0x1444:
1099
131
      imFuji.DRangePriorityAuto = get2();
1100
131
      break;
1101
462
    case 0x1445:
1102
462
      imFuji.DRangePriorityFixed = get2();
1103
462
      break;
1104
299
    case 0x1447:
1105
299
      stmread(imFuji.FujiModel, len, ifp);
1106
299
      break;
1107
708
    case 0x1448:
1108
708
      stmread(imFuji.FujiModel2, len, ifp);
1109
708
      break;
1110
171k
    }
1111
178k
  return;
1112
178k
}
1113
1114
void LibRaw::parse_fuji_thumbnail(INT64 offset)
1115
1.86k
{
1116
1.86k
    uchar xmpmarker[] = "http://ns.adobe.com/xap/1.0/";
1117
1.86k
    uchar buf[sizeof(xmpmarker)+1];
1118
1.86k
    int xmpsz = sizeof(xmpmarker); // we do not
1119
1120
1.86k
    INT64 pos = ftell(ifp);
1121
1.86k
    fseek(ifp, offset, SEEK_SET);
1122
1.86k
    ushort s_order = order;
1123
1.86k
    order = 0x4a4a; // JPEG is always in MM order
1124
1125
1.86k
    if (get2() == 0xFFD8)
1126
209
    {
1127
416
        while (1)
1128
416
        {
1129
416
          ushort tag = get2();
1130
416
          if (tag != 0xFFE1 && tag != 0xFFE2) // allow APP1/APP2 only
1131
208
            break;
1132
208
          INT64 tpos = ftell(ifp);
1133
208
          int len = get2();
1134
208
          if (len > xmpsz + 2)
1135
203
          {
1136
203
              if ((fread(buf, 1, xmpsz, ifp) == xmpsz) && !memcmp(buf, xmpmarker, xmpsz)) // got it
1137
1
              {
1138
1
                  xmplen = len - xmpsz - 2;
1139
1
                  xmpdata = (char*) calloc(xmplen+1,1);
1140
1
                  unsigned br = fread(xmpdata, 1, xmplen, ifp);
1141
1
                  xmpdata[br] = 0;
1142
1
                  break;
1143
1
              }
1144
203
          }
1145
207
          fseek(ifp, tpos + len, SEEK_SET);
1146
207
        }
1147
209
    }
1148
1149
1.86k
    order = s_order;
1150
1.86k
    fseek(ifp, pos, SEEK_SET);
1151
1.86k
}
1152
1153
void LibRaw::parse_fuji(INT64 offset)
1154
3.05k
{
1155
3.05k
  unsigned entries, tag, len, c;
1156
3.05k
  INT64 save;
1157
1158
3.05k
#define get_average_WB(wb_index)                                               \
1159
3.05k
  do {                                                                         \
1160
6.63k
    FORC4 icWBC[wb_index][GRGB_2_RGBG(c)] = get2();                              \
1161
1.65k
    if ((len == 16) && average_WBData) {                                         \
1162
908
    FORC4 icWBC[wb_index][GRGB_2_RGBG(c)] =                                    \
1163
908
         (icWBC[wb_index][GRGB_2_RGBG(c)] + get2())/2;                     \
1164
227
    }                                                                            \
1165
1.65k
    if (use_WBcorr_coeffs) {                                                     \
1166
333
    icWBC[wb_index][0] = int(icWBC[wb_index][0] * wbR_corr);                   \
1167
333
    icWBC[wb_index][2] = int( icWBC[wb_index][2] * wbB_corr);                  \
1168
333
    }                                                                            \
1169
1.65k
  } while(0)
1170
1171
3.05k
  ushort raw_inset_present = 0;
1172
3.05k
  ushort use_WBcorr_coeffs = 0;
1173
3.05k
  double wbR_corr = 1.0;
1174
3.05k
  double wbB_corr = 1.0;
1175
3.05k
  ilm.CamID = unique_id;
1176
3.05k
  int average_WBData = 1;
1177
1178
3.05k
  fseek(ifp, offset, SEEK_SET);
1179
3.05k
  entries = get4();
1180
3.05k
  if (entries > 255)
1181
1.70k
    return;
1182
1.35k
  imgdata.process_warnings |= LIBRAW_WARN_PARSEFUJI_PROCESSED;
1183
1184
1.35k
  if (strstr(model, "S2Pro")
1185
1.33k
      || strstr(model, "S20Pro")
1186
1.32k
      || strstr(model, "F700")
1187
1.31k
      || strstr(model, "S5000")
1188
1.30k
      || strstr(model, "S7000")
1189
1.35k
      ) {
1190
54
    use_WBcorr_coeffs = 1;
1191
54
    wbR_corr = 10.0 / 17.0 / 0.652941;
1192
54
    wbB_corr = 2.0 /3.0 / (3.0 / 4.0 + 1.0 / 300.0);
1193
1.29k
  } else if (strstr(model, "DBP") || strstr(model, "DX-2000")) {
1194
18
    use_WBcorr_coeffs = 1;
1195
18
    wbR_corr = 0.7632653061;
1196
18
    wbB_corr = 0.8591549296;
1197
18
  }
1198
1199
68.1k
  while (entries--)
1200
66.8k
  {
1201
66.8k
    tag = get2();
1202
66.8k
    len = get2();
1203
66.8k
    save = ftell(ifp);
1204
66.8k
    if (tag == 0x0100) // RawImageFullSize
1205
1.04k
    {
1206
1.04k
      raw_height = get2();
1207
1.04k
      raw_width = get2();
1208
1.04k
      raw_inset_present = 1;
1209
1.04k
    }
1210
65.7k
    else if ((tag == 0x0110) && raw_inset_present) // RawImageCropTopLeft
1211
135
    {
1212
135
      imgdata.sizes.raw_inset_crops[0].ctop = get2();
1213
135
      imgdata.sizes.raw_inset_crops[0].cleft = get2();
1214
135
    }
1215
65.6k
    else if ((tag == 0x0111) && raw_inset_present) // RawImageCroppedSize
1216
185
    {
1217
185
      imgdata.sizes.raw_inset_crops[0].cheight = get2();
1218
185
      imgdata.sizes.raw_inset_crops[0].cwidth = get2();
1219
185
    }
1220
65.4k
    else if ((tag == 0x0115) && raw_inset_present) // RawImageAspectRatio
1221
220
    {
1222
220
      int a = get2();
1223
220
      int b = get2();
1224
220
      if (a * b == 6)
1225
56
        imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_3to2;
1226
164
      else if (a * b == 12)
1227
61
        imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_4to3;
1228
103
      else if (a * b == 144)
1229
25
        imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_16to9;
1230
78
      else if (a * b == 1)
1231
17
        imgdata.sizes.raw_aspect = LIBRAW_IMAGE_ASPECT_1to1;
1232
220
    }
1233
65.2k
    else if (tag == 0x0121) // RawImageSize
1234
143
    {
1235
143
      height = get2();
1236
143
      if ((width = get2()) == 4284)
1237
1
        width += 3;
1238
143
    }
1239
65.1k
    else if (tag == 0x0130) // FujiLayout,
1240
162
    {
1241
162
      fuji_layout = fgetc(ifp) >> 7;
1242
162
      fuji_width  = !(fgetc(ifp) & 8);
1243
162
    }
1244
64.9k
    else if (tag == 0x0131) // XTransLayout
1245
50
    {
1246
50
      filters = 9;
1247
50
      char *xtrans_abs_alias = &xtrans_abs[0][0];
1248
50
      FORC(36)
1249
1.80k
      {
1250
1.80k
        int q = fgetc(ifp);
1251
1.80k
        xtrans_abs_alias[35 - c] = MAX(0, MIN(q, 2)); /* & 3;*/
1252
1.80k
      }
1253
50
    }
1254
64.8k
    else if (tag == 0x2ff0) // WB_GRGBLevels
1255
748
    {
1256
748
      get_average_WB(LIBRAW_WBI_AsShot);
1257
2.99k
      FORC4 cam_mul[c] = float(icWBC[LIBRAW_WBI_AsShot][c]);
1258
748
    }
1259
64.1k
    else if ((tag == 0x4000) &&
1260
171
             ((len == 8) || (len == 16)))
1261
118
    {
1262
118
      imFuji.BlackLevel[0] = len / 2;
1263
472
      FORC4 imFuji.BlackLevel[GRGB_2_RGBG(c)+1] = get2();
1264
118
      if (imFuji.BlackLevel[0] == 8)
1265
252
        FORC4 imFuji.BlackLevel[GRGB_2_RGBG(c)+5] = get2();
1266
118
      if (imFuji.BlackLevel[0] == 4)
1267
220
        FORC4 cblack[c] = imFuji.BlackLevel[c+1];
1268
63
      else if (imFuji.BlackLevel[0] == 8)
1269
252
        FORC4 cblack[c] = (imFuji.BlackLevel[c+1]+imFuji.BlackLevel[c+5]) /2;
1270
118
    }
1271
64.0k
    else if (tag == 0x9200) // RelativeExposure
1272
543
    {
1273
543
      int s1 = get2();
1274
543
      int s2 = get2();
1275
543
      if ((s1 == s2) || !s1)
1276
44
        imFuji.BrightnessCompensation = 0.0f;
1277
499
      else if ((s1*4) == s2)
1278
12
        imFuji.BrightnessCompensation = 2.0f;
1279
487
      else if ((s1*16) == s2)
1280
72
        imFuji.BrightnessCompensation = 4.0f;
1281
415
      else
1282
415
        imFuji.BrightnessCompensation = logf(float(s2)/float(s1))/logf(2.f);
1283
543
    }
1284
63.4k
    else if (tag == 0x9650) // RawExposureBias
1285
42
    {
1286
42
      short a = (short)get2();
1287
42
      float b = fMAX(1.0f, get2());
1288
42
      imFuji.ExpoMidPointShift = a / b;
1289
42
      imCommon.ExposureCalibrationShift += imFuji.ExpoMidPointShift;
1290
42
    }
1291
66.8k
    if (tag >= 0x2000 && tag <= 0x2410)
1292
1.25k
    {
1293
7.67k
      for (int q = 0; q < tag2wbtable_size; q++)
1294
7.33k
        if (tag2wbtable[q].tag == tag)
1295
911
        {
1296
911
          get_average_WB(tag2wbtable[q].wb);
1297
911
          break;
1298
911
        }
1299
1.25k
    }
1300
65.5k
    else if (tag == 0x2f00) // WB_GRGBLevels
1301
413
    {
1302
413
      int nWBs = get4();
1303
413
      nWBs = MIN(nWBs, 6);
1304
1.85k
      for (int wb_ind = LIBRAW_WBI_Custom1; wb_ind < LIBRAW_WBI_Custom1+nWBs; wb_ind++) {
1305
5.76k
        FORC4 icWBC[wb_ind][GRGB_2_RGBG(c)] = get2();
1306
1.44k
        if ((len >= unsigned(4+16*nWBs)) && average_WBData) {
1307
448
          FORC4 icWBC[wb_ind][GRGB_2_RGBG(c)] =
1308
448
                  (icWBC[wb_ind][GRGB_2_RGBG(c)] +get2()) /2;
1309
112
        }
1310
1.44k
        if (use_WBcorr_coeffs) {
1311
661
          icWBC[LIBRAW_WBI_Custom1 + wb_ind][0] = int(icWBC[LIBRAW_WBI_Custom1 + wb_ind][0] * wbR_corr);
1312
661
          icWBC[LIBRAW_WBI_Custom1 + wb_ind][2] = int(icWBC[LIBRAW_WBI_Custom1 + wb_ind][2] * wbB_corr);
1313
661
        }
1314
1.44k
      }
1315
413
    }
1316
1317
65.1k
    else if (tag == 0xc000) // RAFData
1318
284
    {
1319
284
      int offsetWH_inRAFData;
1320
284
      unsigned save_order = order;
1321
284
      order = 0x4949;
1322
284
      if (len > 20000)
1323
198
      {
1324
198
        uchar RAFDataHeader[16];
1325
198
        libraw_internal_data.unpacker_data.posRAFData = save;
1326
198
        libraw_internal_data.unpacker_data.lenRAFData = (len >> 1);
1327
198
    memset(RAFDataHeader, 0, sizeof(RAFDataHeader));
1328
198
        fread(RAFDataHeader, sizeof RAFDataHeader, 1, ifp);
1329
198
        offsetWH_inRAFData = guess_RAFDataGeneration(RAFDataHeader);
1330
198
        fseek(ifp, offsetWH_inRAFData-int(sizeof RAFDataHeader), SEEK_CUR);
1331
198
        for (int i=0;
1332
6.53k
             i< (int)((sizeof imFuji.RAFData_ImageSizeTable) / (sizeof imFuji.RAFData_ImageSizeTable[0]));
1333
6.33k
             i++) {
1334
6.33k
          imFuji.RAFData_ImageSizeTable[i] = get4();
1335
6.33k
        }
1336
1337
//         if ((width > raw_width)
1338
//             || (raw_inset_present && (width < imgdata.sizes.raw_inset_crops[0].cwidth))
1339
//         )
1340
//           width = raw_width;
1341
//         if ((height > raw_height)
1342
//             || (raw_inset_present && (height < imgdata.sizes.raw_inset_crops[0].cheight))
1343
//         )
1344
//           height = raw_height;
1345
//
1346
1347
198
      }
1348
86
      else if (len == 4096) // X-A3, X-A5, X-A7, X-A10, X-A20, X-T100, X-T200, XF10
1349
72
      {                     // Ill.A aligned to CCT 2850
1350
72
        int wb[4];
1351
72
        int nWB, tWB;
1352
72
        int iCCT = 0;
1353
72
        imFuji.RAFDataGeneration = 4096;
1354
72
        fseek(ifp, save + 0x200, SEEK_SET);
1355
3.09k
        for (int wb_ind = 0; wb_ind < 42; wb_ind++)
1356
3.02k
        {
1357
3.02k
          nWB = get4();
1358
3.02k
          tWB = get4();
1359
3.02k
          wb[0] = get4() << 1;
1360
3.02k
          wb[1] = get4();
1361
3.02k
          wb[3] = get4();
1362
3.02k
          wb[2] = get4() << 1;
1363
3.02k
          if (tWB && (iCCT < 64))
1364
2.06k
          {
1365
2.06k
            icWBCCTC[iCCT][0] = float(tWB);
1366
8.25k
            FORC4 icWBCCTC[iCCT][c + 1] = float(wb[c]);
1367
2.06k
            iCCT++;
1368
2.06k
          }
1369
3.02k
          if (nWB != 70)
1370
3.01k
          {
1371
25.4k
            for (int pWB = 1; pWB < (int)Fuji_wb_list2.size(); pWB += 2)
1372
23.4k
            {
1373
23.4k
              if (Fuji_wb_list2[pWB] == nWB)
1374
992
              {
1375
3.96k
                FORC4 icWBC[Fuji_wb_list2[pWB - 1]][c] = wb[c];
1376
992
                break;
1377
992
              }
1378
23.4k
            }
1379
3.01k
          }
1380
3.02k
        }
1381
72
      }
1382
284
      order = save_order;
1383
284
    }
1384
66.8k
    fseek(ifp, save + len, SEEK_SET);
1385
66.8k
  }
1386
1387
1.35k
  if (!imFuji.RAFDataGeneration) {
1388
1.21k
    height <<= fuji_layout;
1389
1.21k
    width >>= fuji_layout;
1390
1.21k
  }
1391
1.35k
#undef get_average_WB
1392
1.35k
}
1393