Coverage Report

Created: 2026-05-12 06:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libraw/src/utils/open.cpp
Line
Count
Source
1
/* -*- C++ -*-
2
 * Copyright 2019-2025 LibRaw LLC (info@libraw.org)
3
 *
4
5
 LibRaw is free software; you can redistribute it and/or modify
6
 it under the terms of the one of two licenses as you choose:
7
8
1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
9
   (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
10
11
2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
12
   (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
13
14
 */
15
16
#include "../../internal/libraw_cxx_defs.h"
17
#include "../../internal/libraw_cameraids.h"
18
19
#ifndef LIBRAW_NO_IOSTREAMS_DATASTREAM
20
int LibRaw::open_file(const char *fname, INT64 max_buf_size)
21
{
22
  int big = 0;
23
  if (max_buf_size == LIBRAW_OPEN_BIGFILE)
24
    big = 1;
25
  else if (max_buf_size == LIBRAW_OPEN_FILE)
26
    big = 0;
27
  else
28
  {
29
#ifndef LIBRAW_WIN32_CALLS
30
    struct stat st;
31
    if (stat(fname, &st))
32
      return LIBRAW_IO_ERROR;
33
    big = (st.st_size > max_buf_size) ? 1 : 0;
34
#else
35
    struct _stati64 st;
36
    if (_stati64(fname, &st))
37
      return LIBRAW_IO_ERROR;
38
    big = (st.st_size > max_buf_size) ? 1 : 0;
39
#endif
40
  }
41
42
  LibRaw_abstract_datastream *stream;
43
  try
44
  {
45
    if (big)
46
      stream = new LibRaw_bigfile_datastream(fname);
47
    else
48
      stream = new LibRaw_file_datastream(fname);
49
  }
50
51
  catch (const std::bad_alloc& )
52
  {
53
    recycle();
54
    return LIBRAW_UNSUFFICIENT_MEMORY;
55
  }
56
  if (!stream->valid())
57
  {
58
    delete stream;
59
    return LIBRAW_IO_ERROR;
60
  }
61
  ID.input_internal = 0; // preserve from deletion on error
62
  int ret = open_datastream(stream);
63
  if (ret == LIBRAW_SUCCESS)
64
  {
65
    ID.input_internal = 1; // flag to delete datastream on recycle
66
  }
67
  else
68
  {
69
    delete stream;
70
    ID.input_internal = 0;
71
  }
72
  return ret;
73
}
74
75
#if defined(WIN32) || defined(_WIN32)
76
#ifndef LIBRAW_WIN32_UNICODEPATHS
77
int LibRaw::open_file(const wchar_t *, INT64)
78
{
79
  return LIBRAW_NOT_IMPLEMENTED;
80
}
81
#else
82
int LibRaw::open_file(const wchar_t *fname, INT64 max_buf_size)
83
{
84
  int big = 0;
85
  if (max_buf_size == LIBRAW_OPEN_BIGFILE)
86
    big = 1;
87
  else if (max_buf_size == LIBRAW_OPEN_FILE)
88
    big = 0;
89
  else
90
  {
91
    struct _stati64 st;
92
    if (_wstati64(fname, &st))
93
      return LIBRAW_IO_ERROR;
94
    big = (st.st_size > max_buf_size) ? 1 : 0;
95
  }
96
97
  LibRaw_abstract_datastream *stream;
98
  try
99
  {
100
    if (big)
101
      stream = new LibRaw_bigfile_datastream(fname);
102
    else
103
      stream = new LibRaw_file_datastream(fname);
104
  }
105
106
  catch (const std::bad_alloc&)
107
  {
108
    recycle();
109
    return LIBRAW_UNSUFFICIENT_MEMORY;
110
  }
111
  if (!stream->valid())
112
  {
113
    delete stream;
114
    return LIBRAW_IO_ERROR;
115
  }
116
  ID.input_internal = 0; // preserve from deletion on error
117
  int ret = open_datastream(stream);
118
  if (ret == LIBRAW_SUCCESS)
119
  {
120
    ID.input_internal = 1; // flag to delete datastream on recycle
121
  }
122
  else
123
  {
124
    delete stream;
125
    ID.input_internal = 0;
126
  }
127
  return ret;
128
}
129
#endif
130
#endif
131
132
#else /* LIBRAW_NO_IOSTREAMS_DATASTREAM*/
133
134
int LibRaw::libraw_openfile_tail(LibRaw_abstract_datastream *stream)
135
0
{
136
0
    if (!stream->valid())
137
0
    {
138
0
        delete stream;
139
0
        return LIBRAW_IO_ERROR;
140
0
    }
141
0
    ID.input_internal = 0; // preserve from deletion on error
142
0
    int ret = open_datastream(stream);
143
0
    if (ret == LIBRAW_SUCCESS)
144
0
    {
145
0
        ID.input_internal = 1; // flag to delete datastream on recycle
146
0
    }
147
0
    else
148
0
    {
149
0
        delete stream;
150
0
        ID.input_internal = 0;
151
0
    }
152
0
    return ret;
153
0
}
154
155
int LibRaw::open_file(const char *fname)
156
0
{
157
0
    LibRaw_abstract_datastream *stream;
158
0
    try
159
0
    {
160
#ifdef LIBRAW_WIN32_CALLS
161
        stream = new LibRaw_bigfile_buffered_datastream(fname);
162
#else
163
0
        stream = new LibRaw_bigfile_datastream(fname);
164
0
#endif
165
0
    }
166
0
    catch (const std::bad_alloc&)
167
0
    {
168
0
        recycle();
169
0
        return LIBRAW_UNSUFFICIENT_MEMORY;
170
0
    }
171
0
    if ((stream->size() > (INT64)LIBRAW_MAX_NONDNG_RAW_FILE_SIZE) 
172
0
    && (stream->size() > (INT64)LIBRAW_MAX_DNG_RAW_FILE_SIZE)
173
0
    && (stream->size() > (INT64)LIBRAW_MAX_CR3_RAW_FILE_SIZE)
174
0
    )
175
0
    {
176
0
      delete stream;
177
0
      return LIBRAW_TOO_BIG;
178
0
    }
179
0
    return libraw_openfile_tail(stream);
180
0
}
181
182
#if defined(WIN32) || defined(_WIN32)
183
#ifndef LIBRAW_WIN32_UNICODEPATHS
184
int LibRaw::open_file(const wchar_t *)
185
{
186
    return LIBRAW_NOT_IMPLEMENTED;
187
}
188
#else
189
int LibRaw::open_file(const wchar_t *fname)
190
{
191
    LibRaw_abstract_datastream *stream;
192
    try
193
    {
194
#ifdef LIBRAW_WIN32_CALLS
195
        stream = new LibRaw_bigfile_buffered_datastream(fname);
196
#else
197
        stream = new LibRaw_bigfile_datastream(fname);
198
#endif
199
    }
200
    catch (const std::bad_alloc&)
201
    {
202
        recycle();
203
        return LIBRAW_UNSUFFICIENT_MEMORY;
204
    }
205
    if ((stream->size() > (INT64)LIBRAW_MAX_DNG_RAW_FILE_SIZE) 
206
    && (stream->size() > (INT64)LIBRAW_MAX_NONDNG_RAW_FILE_SIZE) &&
207
        (stream->size() > (INT64)LIBRAW_MAX_CR3_RAW_FILE_SIZE)
208
    )
209
    {
210
      delete stream;
211
      return LIBRAW_TOO_BIG;
212
    }
213
214
    return libraw_openfile_tail(stream);
215
}
216
#endif
217
#endif
218
219
#endif
220
221
int LibRaw::open_buffer(const void *buffer, size_t size)
222
93.9k
{
223
  // this stream will close on recycle()
224
93.9k
  if (!buffer || buffer == (const void *)-1)
225
300
    return LIBRAW_IO_ERROR;
226
227
93.6k
  if ((size > (INT64)LIBRAW_MAX_DNG_RAW_FILE_SIZE) 
228
0
    && (size > (INT64)LIBRAW_MAX_NONDNG_RAW_FILE_SIZE)
229
0
        && (size > (INT64)LIBRAW_MAX_CR3_RAW_FILE_SIZE)
230
93.6k
    )
231
0
      return LIBRAW_TOO_BIG;
232
233
93.6k
  LibRaw_buffer_datastream *stream;
234
93.6k
  try
235
93.6k
  {
236
93.6k
    stream = new LibRaw_buffer_datastream(buffer, size);
237
93.6k
  }
238
93.6k
  catch (const std::bad_alloc& )
239
93.6k
  {
240
0
    recycle();
241
0
    return LIBRAW_UNSUFFICIENT_MEMORY;
242
0
  }
243
93.6k
  if (!stream->valid())
244
0
  {
245
0
    delete stream;
246
0
    return LIBRAW_IO_ERROR;
247
0
  }
248
93.6k
  ID.input_internal = 0; // preserve from deletion on error
249
93.6k
  int ret = open_datastream(stream);
250
93.6k
  if (ret == LIBRAW_SUCCESS)
251
24.9k
  {
252
24.9k
    ID.input_internal = 1; // flag to delete datastream on recycle
253
24.9k
  }
254
68.7k
  else
255
68.7k
  {
256
68.7k
    delete stream;
257
68.7k
    ID.input_internal = 0;
258
68.7k
  }
259
93.6k
  return ret;
260
93.6k
}
261
262
int LibRaw::open_bayer(const unsigned char *buffer, unsigned datalen,
263
                       ushort _raw_width, ushort _raw_height,
264
                       ushort _left_margin, ushort _top_margin,
265
                       ushort _right_margin, ushort _bottom_margin,
266
                       unsigned char procflags, unsigned char bayer_pattern,
267
                       unsigned unused_bits, unsigned otherflags,
268
                       unsigned black_level)
269
0
{
270
  // this stream will close on recycle()
271
0
  if (!buffer || buffer == (const void *)-1)
272
0
    return LIBRAW_IO_ERROR;
273
274
0
  LibRaw_buffer_datastream *stream;
275
0
  try
276
0
  {
277
0
    stream = new LibRaw_buffer_datastream(buffer, datalen);
278
0
  }
279
0
  catch (const std::bad_alloc& )
280
0
  {
281
0
    recycle();
282
0
    return LIBRAW_UNSUFFICIENT_MEMORY;
283
0
  }
284
0
  if (!stream->valid())
285
0
  {
286
0
    delete stream;
287
0
    return LIBRAW_IO_ERROR;
288
0
  }
289
0
  ID.input = stream;
290
0
  SET_PROC_FLAG(LIBRAW_PROGRESS_OPEN);
291
  // From identify
292
0
  initdata();
293
0
  strcpy(imgdata.idata.make, "BayerDump");
294
0
  snprintf(imgdata.idata.model, sizeof(imgdata.idata.model) - 1,
295
0
           "%u x %u pixels", _raw_width, _raw_height);
296
0
  S.flip = procflags >> 2;
297
0
  libraw_internal_data.internal_output_params.zero_is_bad = procflags & 2;
298
0
  libraw_internal_data.unpacker_data.data_offset = 0;
299
0
  S.raw_width = _raw_width;
300
0
  S.raw_height = _raw_height;
301
0
  S.left_margin = _left_margin;
302
0
  S.top_margin = _top_margin;
303
0
  S.width = S.raw_width - S.left_margin - _right_margin;
304
0
  S.height = S.raw_height - S.top_margin - _bottom_margin;
305
306
0
  imgdata.idata.filters = 0x1010101 * bayer_pattern;
307
0
  imgdata.idata.colors =
308
0
      4 - !((imgdata.idata.filters & imgdata.idata.filters >> 1) & 0x5555);
309
0
  libraw_internal_data.unpacker_data.load_flags = otherflags;
310
0
  switch (libraw_internal_data.unpacker_data.tiff_bps =
311
0
              (datalen)*8 / (S.raw_width * S.raw_height))
312
0
  {
313
0
  case 8:
314
0
    load_raw = &LibRaw::eight_bit_load_raw;
315
0
    break;
316
0
  case 10:
317
0
    if ((datalen) / S.raw_height * 3u >= S.raw_width * 4u)
318
0
    {
319
0
      load_raw = &LibRaw::android_loose_load_raw;
320
0
      break;
321
0
    }
322
0
    else if (libraw_internal_data.unpacker_data.load_flags & 1)
323
0
    {
324
0
      load_raw = &LibRaw::android_tight_load_raw;
325
0
      break;
326
0
    }
327
0
  case 12:
328
0
    libraw_internal_data.unpacker_data.load_flags |= 128;
329
0
    load_raw = &LibRaw::packed_load_raw;
330
0
    break;
331
0
  case 16:
332
0
    libraw_internal_data.unpacker_data.order =
333
0
        0x4949 | 0x404 * (libraw_internal_data.unpacker_data.load_flags & 1);
334
0
    libraw_internal_data.unpacker_data.tiff_bps -=
335
0
        libraw_internal_data.unpacker_data.load_flags >> 4;
336
0
    libraw_internal_data.unpacker_data.tiff_bps -=
337
0
        libraw_internal_data.unpacker_data.load_flags =
338
0
            libraw_internal_data.unpacker_data.load_flags >> 1 & 7;
339
0
    load_raw = &LibRaw::unpacked_load_raw;
340
0
  }
341
0
  C.maximum =
342
0
      (1 << libraw_internal_data.unpacker_data.tiff_bps) - (1 << unused_bits);
343
0
  C.black = black_level;
344
0
  S.iwidth = S.width;
345
0
  S.iheight = S.height;
346
0
  imgdata.idata.colors = 3;
347
0
  imgdata.idata.filters |= ((imgdata.idata.filters >> 2 & 0x22222222) |
348
0
                            (imgdata.idata.filters << 2 & 0x88888888)) &
349
0
                           imgdata.idata.filters << 1;
350
351
0
  imgdata.idata.raw_count = 1;
352
0
  for (int i = 0; i < 4; i++)
353
0
    imgdata.color.pre_mul[i] = 1.0;
354
355
0
  strcpy(imgdata.idata.cdesc, "RGBG");
356
357
0
  ID.input_internal = 1;
358
0
  SET_PROC_FLAG(LIBRAW_PROGRESS_IDENTIFY);
359
0
  return LIBRAW_SUCCESS;
360
0
}
361
362
struct foveon_data_t
363
{
364
  const char *make;
365
  const char *model;
366
  const int raw_width, raw_height;
367
  const int white;
368
  const int left_margin, top_margin;
369
  const int width, height;
370
} foveon_data[] = {
371
    {"Sigma", "SD9", 2304, 1531, 12000, 20, 8, 2266, 1510},
372
    {"Sigma", "SD9", 1152, 763, 12000, 10, 2, 1132, 755},
373
    {"Sigma", "SD10", 2304, 1531, 12000, 20, 8, 2266, 1510},
374
    {"Sigma", "SD10", 1152, 763, 12000, 10, 2, 1132, 755},
375
    {"Sigma", "SD14", 2688, 1792, 14000, 18, 12, 2651, 1767},
376
    {"Sigma", "SD14", 2688, 896, 14000, 18, 6, 2651, 883}, // 2/3
377
    {"Sigma", "SD14", 1344, 896, 14000, 9, 6, 1326, 883},  // 1/2
378
    {"Sigma", "SD15", 2688, 1792, 2900, 18, 12, 2651, 1767},
379
    {"Sigma", "SD15", 2688, 896, 2900, 18, 6, 2651, 883}, // 2/3 ?
380
    {"Sigma", "SD15", 1344, 896, 2900, 9, 6, 1326, 883},  // 1/2 ?
381
    {"Sigma", "DP1", 2688, 1792, 2100, 18, 12, 2651, 1767},
382
    {"Sigma", "DP1", 2688, 896, 2100, 18, 6, 2651, 883}, // 2/3 ?
383
    {"Sigma", "DP1", 1344, 896, 2100, 9, 6, 1326, 883},  // 1/2 ?
384
    {"Sigma", "DP1S", 2688, 1792, 2200, 18, 12, 2651, 1767},
385
    {"Sigma", "DP1S", 2688, 896, 2200, 18, 6, 2651, 883}, // 2/3
386
    {"Sigma", "DP1S", 1344, 896, 2200, 9, 6, 1326, 883},  // 1/2
387
    {"Sigma", "DP1X", 2688, 1792, 3560, 18, 12, 2651, 1767},
388
    {"Sigma", "DP1X", 2688, 896, 3560, 18, 6, 2651, 883}, // 2/3
389
    {"Sigma", "DP1X", 1344, 896, 3560, 9, 6, 1326, 883},  // 1/2
390
    {"Sigma", "DP2", 2688, 1792, 2326, 13, 16, 2651, 1767},
391
    {"Sigma", "DP2", 2688, 896, 2326, 13, 8, 2651, 883}, // 2/3 ??
392
    {"Sigma", "DP2", 1344, 896, 2326, 7, 8, 1325, 883},  // 1/2 ??
393
    {"Sigma", "DP2S", 2688, 1792, 2300, 18, 12, 2651, 1767},
394
    {"Sigma", "DP2S", 2688, 896, 2300, 18, 6, 2651, 883}, // 2/3
395
    {"Sigma", "DP2S", 1344, 896, 2300, 9, 6, 1326, 883},  // 1/2
396
    {"Sigma", "DP2X", 2688, 1792, 2300, 18, 12, 2651, 1767},
397
    {"Sigma", "DP2X", 2688, 896, 2300, 18, 6, 2651, 883},           // 2/3
398
    {"Sigma", "DP2X", 1344, 896, 2300, 9, 6, 1325, 883},            // 1/2
399
    {"Sigma", "SD1", 4928, 3264, 3900, 12, 52, 4807, 3205},         // Full size
400
    {"Sigma", "SD1", 4928, 1632, 3900, 12, 26, 4807, 1603},         // 2/3 size
401
    {"Sigma", "SD1", 2464, 1632, 3900, 6, 26, 2403, 1603},          // 1/2 size
402
    {"Sigma", "SD1 Merrill", 4928, 3264, 3900, 12, 52, 4807, 3205}, // Full size
403
    {"Sigma", "SD1 Merrill", 4928, 1632, 3900, 12, 26, 4807, 1603}, // 2/3 size
404
    {"Sigma", "SD1 Merrill", 2464, 1632, 3900, 6, 26, 2403, 1603},  // 1/2 size
405
    {"Sigma", "DP1 Merrill", 4928, 3264, 3900, 12, 0, 4807, 3205},
406
    {"Sigma", "DP1 Merrill", 2464, 1632, 3900, 12, 0, 2403, 1603}, // 1/2 size
407
    {"Sigma", "DP1 Merrill", 4928, 1632, 3900, 12, 0, 4807, 1603}, // 2/3 size
408
    {"Sigma", "DP2 Merrill", 4928, 3264, 3900, 12, 0, 4807, 3205},
409
    {"Sigma", "DP2 Merrill", 2464, 1632, 3900, 12, 0, 2403, 1603}, // 1/2 size
410
    {"Sigma", "DP2 Merrill", 4928, 1632, 3900, 12, 0, 4807, 1603}, // 2/3 size
411
    {"Sigma", "DP3 Merrill", 4928, 3264, 3900, 12, 0, 4807, 3205},
412
    {"Sigma", "DP3 Merrill", 2464, 1632, 3900, 12, 0, 2403, 1603}, // 1/2 size
413
    {"Sigma", "DP3 Merrill", 4928, 1632, 3900, 12, 0, 4807, 1603}, // 2/3 size
414
    {"Polaroid", "x530", 1440, 1088, 2700, 10, 13, 1419, 1059},
415
    // dp2 Q
416
    {"Sigma", "dp3 Quattro", 5888, 3776, 16383, 204, 76, 5446,
417
     3624}, // full size, new fw ??
418
    {"Sigma", "dp3 Quattro", 5888, 3672, 16383, 204, 24, 5446,
419
     3624}, // full size
420
    {"Sigma", "dp3 Quattro", 2944, 1836, 16383, 102, 12, 2723,
421
     1812}, // half size
422
    {"Sigma", "dp3 Quattro", 2944, 1888, 16383, 102, 38, 2723,
423
     1812}, // half size, new fw??
424
425
    {"Sigma", "dp2 Quattro", 5888, 3776, 16383, 204, 76, 5446,
426
     3624}, // full size, new fw
427
    {"Sigma", "dp2 Quattro", 5888, 3672, 16383, 204, 24, 5446,
428
     3624}, // full size
429
    {"Sigma", "dp2 Quattro", 2944, 1836, 16383, 102, 12, 2723,
430
     1812}, // half size
431
    {"Sigma", "dp2 Quattro", 2944, 1888, 16383, 102, 38, 2723,
432
     1812}, // half size, new fw
433
434
    {"Sigma", "dp1 Quattro", 5888, 3776, 16383, 204, 76, 5446,
435
     3624}, // full size, new fw??
436
    {"Sigma", "dp1 Quattro", 5888, 3672, 16383, 204, 24, 5446,
437
     3624}, // full size
438
    {"Sigma", "dp1 Quattro", 2944, 1836, 16383, 102, 12, 2723,
439
     1812}, // half size
440
    {"Sigma", "dp1 Quattro", 2944, 1888, 16383, 102, 38, 2723,
441
     1812}, // half size, new fw
442
443
    {"Sigma", "dp0 Quattro", 5888, 3776, 16383, 204, 76, 5446,
444
     3624}, // full size, new fw??
445
    {"Sigma", "dp0 Quattro", 5888, 3672, 16383, 204, 24, 5446,
446
     3624}, // full size
447
    {"Sigma", "dp0 Quattro", 2944, 1836, 16383, 102, 12, 2723,
448
     1812}, // half size
449
    {"Sigma", "dp0 Quattro", 2944, 1888, 16383, 102, 38, 2723,
450
     1812}, // half size, new fw
451
    // Sigma sd Quattro
452
    {"Sigma", "sd Quattro", 5888, 3776, 16383, 204, 76, 5446,
453
     3624}, // full size
454
    {"Sigma", "sd Quattro", 2944, 1888, 16383, 102, 38, 2723,
455
     1812}, // half size
456
    // Sd Quattro H
457
    {"Sigma", "sd Quattro H", 6656, 4480, 4000, 224, 160, 6208,
458
     4160}, // full size
459
    {"Sigma", "sd Quattro H", 3328, 2240, 4000, 112, 80, 3104,
460
     2080},                                                        // half size
461
    {"Sigma", "sd Quattro H", 5504, 3680, 4000, 0, 4, 5496, 3668}, // full size
462
    {"Sigma", "sd Quattro H", 2752, 1840, 4000, 0, 2, 2748, 1834}, // half size
463
};
464
const int foveon_count = sizeof(foveon_data) / sizeof(foveon_data[0]);
465
466
int LibRaw::open_datastream(LibRaw_abstract_datastream *stream)
467
93.6k
{
468
469
93.6k
  if (!stream)
470
0
    return ENOENT;
471
93.6k
  if (!stream->valid())
472
0
    return LIBRAW_IO_ERROR;
473
93.6k
  if ((stream->size() > (INT64)LIBRAW_MAX_DNG_RAW_FILE_SIZE) 
474
0
    && (stream->size() > (INT64)LIBRAW_MAX_NONDNG_RAW_FILE_SIZE) &&
475
0
      (stream->size() > (INT64)LIBRAW_MAX_CR3_RAW_FILE_SIZE)
476
93.6k
    )
477
0
      return LIBRAW_TOO_BIG;
478
479
93.6k
  recycle();
480
93.6k
  if (callbacks.pre_identify_cb)
481
0
  {
482
0
    int r = (callbacks.pre_identify_cb)(this);
483
0
    if (r == 1)
484
0
      goto final;
485
0
  }
486
487
93.6k
  try
488
93.6k
  {
489
93.6k
    ID.input = stream;
490
93.6k
    SET_PROC_FLAG(LIBRAW_PROGRESS_OPEN);
491
492
93.6k
    identify();
493
494
    // Fuji layout files: either DNG or unpacked_load_raw should be used
495
93.6k
    if (libraw_internal_data.internal_output_params.fuji_width || libraw_internal_data.unpacker_data.fuji_layout)
496
1.24k
    {
497
1.24k
      if (!imgdata.idata.dng_version && load_raw != &LibRaw::unpacked_load_raw
498
24
        && load_raw != &LibRaw::unpacked_load_raw_FujiDBP
499
22
        && load_raw != &LibRaw::unpacked_load_raw_fuji_f700s20
500
1.24k
        )
501
22
        return LIBRAW_FILE_UNSUPPORTED;
502
1.24k
    }
503
    // Remove unsupported Nikon thumbnails
504
93.6k
    if (makeIs(LIBRAW_CAMERAMAKER_Nikon) &&
505
2.78k
      (!strncasecmp(imgdata.idata.model, "Z 8", 3) || !strcasecmp(imgdata.idata.model, "Z f")
506
2.72k
        || !strncasecmp(imgdata.idata.model, "Z6_3", 4))
507
84
      &&
508
84
      imgdata.thumbs_list.thumbcount > 1)
509
34
    {
510
34
      int tgtidx = 0;
511
117
      for (int idx = 0; idx < imgdata.thumbs_list.thumbcount && idx < LIBRAW_THUMBNAIL_MAXCOUNT; idx++)
512
83
      {
513
83
        int bps = imgdata.thumbs_list.thumblist[idx].tmisc & 0x1f;
514
83
        if (bps > 8) // remove high-bit thumbs
515
45
        {
516
          // nothing: just skip this item
517
45
        }
518
38
        else
519
38
        {
520
38
          if (tgtidx < idx)
521
10
          {
522
10
            memmove(&imgdata.thumbs_list.thumblist[tgtidx], &imgdata.thumbs_list.thumblist[idx],
523
10
              sizeof(imgdata.thumbs_list.thumblist[idx]));
524
10
            tgtidx++;
525
10
          }
526
28
          else // same index, just assign next tgtidx
527
28
            tgtidx = idx + 1;
528
38
        }
529
83
      }
530
34
      if (tgtidx > 0 && tgtidx < imgdata.thumbs_list.thumbcount)
531
15
      {
532
15
        int selidx = 0;
533
15
        INT64 maximgbits = INT64(imgdata.thumbs_list.thumblist[0].twidth) *
534
15
          INT64(imgdata.thumbs_list.thumblist[0].theight) * INT64(imgdata.thumbs_list.thumblist[0].tmisc & 0x1f);
535
22
        for (int i = 1; i < tgtidx; i++)
536
7
        {
537
7
          INT64 imgbits = INT64(imgdata.thumbs_list.thumblist[i].twidth) *
538
7
            INT64(imgdata.thumbs_list.thumblist[i].theight) *
539
7
            INT64(imgdata.thumbs_list.thumblist[i].tmisc & 0x1f);
540
7
          if (imgbits > maximgbits)
541
1
          {
542
1
            selidx = i;
543
1
            maximgbits = imgbits;
544
1
          }
545
7
        }
546
15
        libraw_internal_data.internal_data.toffset = imgdata.thumbs_list.thumblist[selidx].toffset;
547
15
        imgdata.thumbnail.tlength = imgdata.thumbs_list.thumblist[selidx].tlength;
548
15
        libraw_internal_data.unpacker_data.thumb_format = imgdata.thumbs_list.thumblist[selidx].tformat;
549
15
        imgdata.thumbnail.twidth = imgdata.thumbs_list.thumblist[selidx].twidth;
550
15
        imgdata.thumbnail.theight = imgdata.thumbs_list.thumblist[selidx].theight;
551
15
        libraw_internal_data.unpacker_data.thumb_misc = imgdata.thumbs_list.thumblist[selidx].tmisc;
552
        // find another largest thumb and copy it to single thumbnail data
553
15
      }
554
34
      imgdata.thumbs_list.thumbcount = tgtidx > 0 ? tgtidx : 1;
555
34
    }
556
557
    // promote the old single thumbnail to the thumbs_list if not present already
558
93.6k
    if (imgdata.thumbs_list.thumbcount < LIBRAW_THUMBNAIL_MAXCOUNT)
559
65.8k
    {
560
65.8k
      bool already = false;
561
65.8k
      if (imgdata.thumbnail.tlength || libraw_internal_data.internal_data.toffset)
562
15.6k
        for (int i = 0; i < imgdata.thumbs_list.thumbcount; i++)
563
3.71k
          if (imgdata.thumbs_list.thumblist[i].toffset == libraw_internal_data.internal_data.toffset
564
3.52k
            && imgdata.thumbs_list.thumblist[i].tlength == imgdata.thumbnail.tlength)
565
3.51k
          {
566
3.51k
            already = true;
567
3.51k
            break;
568
3.51k
          }
569
65.8k
      if (!already)
570
62.3k
      {
571
62.3k
        int idx = imgdata.thumbs_list.thumbcount;
572
62.3k
        imgdata.thumbs_list.thumblist[idx].toffset = libraw_internal_data.internal_data.toffset;
573
62.3k
        imgdata.thumbs_list.thumblist[idx].tlength = imgdata.thumbnail.tlength;
574
62.3k
        imgdata.thumbs_list.thumblist[idx].tflip = 0xffff;
575
62.3k
        imgdata.thumbs_list.thumblist[idx].tformat = libraw_internal_data.unpacker_data.thumb_format;
576
62.3k
        imgdata.thumbs_list.thumblist[idx].tmisc = libraw_internal_data.unpacker_data.thumb_misc;
577
        // promote if set
578
62.3k
        imgdata.thumbs_list.thumblist[idx].twidth = imgdata.thumbnail.twidth;
579
62.3k
        imgdata.thumbs_list.thumblist[idx].theight = imgdata.thumbnail.theight;
580
62.3k
        imgdata.thumbs_list.thumbcount++;
581
62.3k
      }
582
65.8k
    }
583
584
585
93.6k
    imgdata.lens.Lens[sizeof(imgdata.lens.Lens) - 1] = 0; // make sure lens is 0-terminated
586
587
93.6k
    if (callbacks.post_identify_cb)
588
0
      (callbacks.post_identify_cb)(this);
589
590
93.6k
#define isRIC imgdata.sizes.raw_inset_crops[0]
591
592
93.6k
    if (!imgdata.idata.dng_version && makeIs(LIBRAW_CAMERAMAKER_Fujifilm)
593
2.71k
      && (!strcmp(imgdata.idata.normalized_model, "S3Pro")
594
2.71k
        || !strcmp(imgdata.idata.normalized_model, "S5Pro")
595
2.71k
        || !strcmp(imgdata.idata.normalized_model, "S2Pro")))
596
21
    {
597
21
      isRIC.cleft = isRIC.ctop = 0xffff;
598
21
      isRIC.cwidth = isRIC.cheight = 0;
599
21
    }
600
    // Wipe out canon  incorrect in-camera crop
601
93.6k
    if (!imgdata.idata.dng_version && makeIs(LIBRAW_CAMERAMAKER_Canon)
602
5.20k
      && isRIC.cleft == 0 && isRIC.ctop == 0 // non symmetric!
603
53
      && isRIC.cwidth < (imgdata.sizes.raw_width * 4 / 5))  // less than 80% of sensor width
604
24
    {
605
24
      isRIC.cleft = isRIC.ctop = 0xffff;
606
24
      isRIC.cwidth = isRIC.cheight = 0;
607
24
    }
608
609
    // Wipe out non-standard WB
610
93.6k
    if (!imgdata.idata.dng_version &&
611
51.9k
      (makeIs(LIBRAW_CAMERAMAKER_Sony) && !strcmp(imgdata.idata.normalized_model, "DSC-F828"))
612
12
      && !(imgdata.rawparams.options & LIBRAW_RAWOPTIONS_PROVIDE_NONSTANDARD_WB))
613
12
    {
614
60
      for (int i = 0; i < 4; i++) imgdata.color.cam_mul[i] = (i == 1);
615
12
      memset(imgdata.color.WB_Coeffs, 0, sizeof(imgdata.color.WB_Coeffs));
616
12
      memset(imgdata.color.WBCT_Coeffs, 0, sizeof(imgdata.color.WBCT_Coeffs));
617
12
    }
618
619
93.6k
    if (load_raw == &LibRaw::nikon_load_raw)
620
486
      nikon_read_curve();
621
622
93.6k
    if (load_raw == &LibRaw::lossless_jpeg_load_raw &&
623
4.30k
      MN.canon.RecordMode && makeIs(LIBRAW_CAMERAMAKER_Kodak) &&
624
      /* Not normalized models here, it is intentional */
625
17
      (!strncasecmp(imgdata.idata.model, "EOS D2000", 9) || // if we want something different for B&W cameras,
626
10
        !strncasecmp(imgdata.idata.model, "EOS D6000", 9)))  // it's better to compare with CamIDs
627
10
    {
628
10
      imgdata.color.black = 0;
629
10
      imgdata.color.maximum = 4501;
630
10
      memset(imgdata.color.cblack, 0, sizeof(imgdata.color.cblack));
631
10
      memset(imgdata.sizes.mask, 0, sizeof(imgdata.sizes.mask));
632
10
      imgdata.sizes.mask[0][3] = 1; // to skip mask re-calc
633
10
      libraw_internal_data.unpacker_data.load_flags |= 512;
634
10
    }
635
636
93.6k
    if (load_raw == &LibRaw::panasonic_load_raw)
637
596
    {
638
596
      if (libraw_internal_data.unpacker_data.pana_encoding == 6 ||
639
457
        libraw_internal_data.unpacker_data.pana_encoding == 7 ||
640
432
        libraw_internal_data.unpacker_data.pana_encoding == 8)
641
184
      {
642
736
        for (int i = 0; i < 3; i++)
643
552
          imgdata.color.cblack[i] =
644
552
          libraw_internal_data.internal_data.pana_black[i];
645
184
        imgdata.color.cblack[3] = imgdata.color.cblack[1];
646
184
        imgdata.color.cblack[4] = imgdata.color.cblack[5] = 0;
647
184
        imgdata.color.black = 0;
648
184
        imgdata.color.maximum =
649
184
          MAX(imgdata.color.linear_max[0],
650
184
            MAX(imgdata.color.linear_max[1], imgdata.color.linear_max[2]));
651
184
      }
652
653
596
      if (libraw_internal_data.unpacker_data.pana_encoding == 6)
654
139
      {
655
139
        int rowbytes11 = imgdata.sizes.raw_width / 11 * 16;
656
139
        int rowbytes14 = imgdata.sizes.raw_width / 14 * 16;
657
139
        INT64 ds = INT64(libraw_internal_data.unpacker_data.data_size);
658
139
        if (!ds)
659
49
          ds = libraw_internal_data.internal_data.input->size() - libraw_internal_data.unpacker_data.data_offset;
660
139
        if ((imgdata.sizes.raw_width % 11) == 0 &&
661
80
          (INT64(imgdata.sizes.raw_height) * rowbytes11 == ds))
662
36
          load_raw = &LibRaw::panasonicC6_load_raw;
663
103
        else if ((imgdata.sizes.raw_width % 14) == 0 &&
664
98
          (INT64(imgdata.sizes.raw_height) * rowbytes14 == ds))
665
52
          load_raw = &LibRaw::panasonicC6_load_raw;
666
51
        else
667
51
          imgdata.idata.raw_count = 0; // incorrect size
668
139
      }
669
457
      else if (libraw_internal_data.unpacker_data.pana_encoding == 7)
670
25
      {
671
25
        int pixperblock =
672
25
          libraw_internal_data.unpacker_data.pana_bpp == 14 ? 9 : 10;
673
25
        int rowbytes = imgdata.sizes.raw_width / pixperblock * 16;
674
25
        if ((imgdata.sizes.raw_width % pixperblock) == 0 &&
675
21
          (INT64(imgdata.sizes.raw_height) * rowbytes ==
676
21
            INT64(libraw_internal_data.unpacker_data.data_size)))
677
16
          load_raw = &LibRaw::panasonicC7_load_raw;
678
9
        else
679
9
          imgdata.idata.raw_count = 0; // incorrect size
680
25
      }
681
432
      else if (libraw_internal_data.unpacker_data.pana_encoding == 8)
682
20
      {
683
20
        if (libraw_internal_data.unpacker_data.pana8.stripe_count > 0)
684
12
          load_raw = &LibRaw::panasonicC8_load_raw;
685
8
        else
686
8
          imgdata.idata.raw_count = 0; // incorrect stripes count
687
20
      }
688
596
    }
689
690
93.6k
#define NIKON_14BIT_SIZE(rw, rh)                                               \
691
93.6k
  (((unsigned)(ceilf((float)(rw * 7 / 4) / 16.f)) * 16) * rh)
692
693
93.6k
#define NIKON_14BIT_SIZE3COLOR(rw, rh) ( ceilf(float(rw * 21 / 4)/16.f) * 16 * rh)
694
695
    // Ugly hack, replace with proper data/line size for different
696
    // cameras/format when available
697
93.6k
    if (makeIs(LIBRAW_CAMERAMAKER_Nikon)
698
2.78k
      && (!strncasecmp(imgdata.idata.model, "Z", 1) || !strcasecmp(imgdata.idata.model, "D6"))
699
93.6k
      )
700
122
    {
701
122
      if (NIKON_14BIT_SIZE(imgdata.sizes.raw_width, imgdata.sizes.raw_height) ==
702
122
        libraw_internal_data.unpacker_data.data_size)
703
46
      {
704
46
        load_raw = &LibRaw::nikon_14bit_load_raw;
705
46
      }
706
122
          if (NIKON_14BIT_SIZE3COLOR(imgdata.sizes.raw_width, imgdata.sizes.raw_height) ==
707
122
              libraw_internal_data.unpacker_data.data_size)
708
32
          {
709
32
            load_raw = &LibRaw::nikon_14bit_load_raw;
710
32
      imgdata.idata.filters = 0; // 3-color nefx image
711
32
          }
712
122
    }
713
93.6k
#undef NIKON_14BIT_SIZE
714
93.6k
#undef NIKON_14BIT_SIZE3COLOR
715
716
    // Linear max from 14-bit camera, but on 12-bit data?
717
93.6k
    if (makeIs(LIBRAW_CAMERAMAKER_Sony) &&
718
5.54k
      imgdata.color.maximum > 0 &&
719
3.00k
      imgdata.color.linear_max[0] > imgdata.color.maximum &&
720
17
      imgdata.color.linear_max[0] <= imgdata.color.maximum * 4)
721
25
      for (int c = 0; c < 4; c++)
722
20
        imgdata.color.linear_max[c] /= 4;
723
724
93.6k
    if (makeIs(LIBRAW_CAMERAMAKER_Canon))
725
6.53k
    {
726
6.53k
      if (!imgdata.idata.dng_version && (MN.canon.DefaultCropAbsolute.l != -1))  // tag 0x00e0 SensorInfo was parsed
727
475
      {
728
475
        if (imgdata.sizes.raw_aspect != LIBRAW_IMAGE_ASPECT_UNKNOWN)
729
24
        { // tag 0x009a AspectInfo was parsed
730
24
          isRIC.cleft += MN.canon.DefaultCropAbsolute.l;
731
24
          isRIC.ctop  += MN.canon.DefaultCropAbsolute.t;
732
24
        }
733
451
        else
734
451
        {
735
451
          isRIC.cleft   = MN.canon.DefaultCropAbsolute.l;
736
451
          isRIC.ctop    = MN.canon.DefaultCropAbsolute.t;
737
451
          isRIC.cwidth  = MN.canon.DefaultCropAbsolute.r - MN.canon.DefaultCropAbsolute.l + 1;
738
451
          isRIC.cheight = MN.canon.DefaultCropAbsolute.b - MN.canon.DefaultCropAbsolute.t + 1;
739
451
        }
740
475
      }
741
6.05k
      else
742
6.05k
      {
743
6.05k
        if (imgdata.sizes.raw_aspect != LIBRAW_IMAGE_ASPECT_UNKNOWN)
744
307
        {
745
307
        }
746
5.74k
        else
747
5.74k
        { // Canon PowerShot S2 IS
748
5.74k
        }
749
6.05k
      }
750
6.53k
#undef isRIC
751
6.53k
          if (imgdata.color.raw_bps < 14 && !imgdata.idata.dng_version && load_raw != &LibRaw::canon_sraw_load_raw)
752
4.56k
          {
753
4.56k
              int xmax = (1 << imgdata.color.raw_bps) - 1;
754
4.56k
              if (MN.canon.SpecularWhiteLevel > xmax) // Adjust 14-bit metadata to real bps
755
265
              {
756
265
                int div = 1 << (14 - imgdata.color.raw_bps);
757
1.32k
                for (int c = 0; c < 4; c++) imgdata.color.linear_max[c] /= div;
758
1.32k
                for (int c = 0; c < 4; c++)  MN.canon.ChannelBlackLevel[c] /= div;
759
265
                MN.canon.AverageBlackLevel /= div;
760
265
                MN.canon.SpecularWhiteLevel /= div;
761
265
                MN.canon.NormalWhiteLevel /= div;
762
265
              }
763
4.56k
          }
764
6.53k
    }
765
766
93.6k
    if (makeIs(LIBRAW_CAMERAMAKER_Canon) &&
767
6.53k
      (load_raw == &LibRaw::canon_sraw_load_raw) &&
768
619
      imgdata.sizes.raw_width > 0)
769
607
    {
770
607
      float ratio =
771
607
        float(imgdata.sizes.raw_height) / float(imgdata.sizes.raw_width);
772
607
      if ((ratio < 0.57 || ratio > 0.75) &&
773
518
        MN.canon.SensorHeight > 1 &&
774
312
        MN.canon.SensorWidth > 1)
775
305
      {
776
305
        imgdata.sizes.raw_width = MN.canon.SensorWidth;
777
305
        imgdata.sizes.left_margin = MN.canon.DefaultCropAbsolute.l;
778
305
        imgdata.sizes.iwidth = imgdata.sizes.width =
779
305
          MN.canon.DefaultCropAbsolute.r - MN.canon.DefaultCropAbsolute.l + 1;
780
305
        imgdata.sizes.raw_height = MN.canon.SensorHeight;
781
305
        imgdata.sizes.top_margin = MN.canon.DefaultCropAbsolute.t;
782
305
        imgdata.sizes.iheight = imgdata.sizes.height =
783
305
          MN.canon.DefaultCropAbsolute.b - MN.canon.DefaultCropAbsolute.t + 1;
784
305
        libraw_internal_data.unpacker_data.load_flags |=
785
305
          256; // reset width/height in canon_sraw_load_raw()
786
305
        imgdata.sizes.raw_pitch = 8 * imgdata.sizes.raw_width;
787
305
      }
788
302
      else if (imgdata.sizes.raw_width == 4032 &&
789
4
        imgdata.sizes.raw_height == 3402 &&
790
0
        !strcasecmp(imgdata.idata.model, "EOS 80D")) // 80D hardcoded
791
0
      {
792
0
        imgdata.sizes.raw_width = 4536;
793
0
        imgdata.sizes.left_margin = 28;
794
0
        imgdata.sizes.iwidth = imgdata.sizes.width =
795
0
          imgdata.sizes.raw_width - imgdata.sizes.left_margin;
796
0
        imgdata.sizes.raw_height = 3024;
797
0
        imgdata.sizes.top_margin = 8;
798
0
        imgdata.sizes.iheight = imgdata.sizes.height =
799
0
          imgdata.sizes.raw_height - imgdata.sizes.top_margin;
800
0
        libraw_internal_data.unpacker_data.load_flags |= 256;
801
0
        imgdata.sizes.raw_pitch = 8 * imgdata.sizes.raw_width;
802
0
      }
803
607
    }
804
805
#ifdef USE_DNGSDK
806
    if (imgdata.idata.dng_version
807
      &&libraw_internal_data.unpacker_data.tiff_compress == 34892
808
      && libraw_internal_data.unpacker_data.tiff_bps == 8
809
      && libraw_internal_data.unpacker_data.tiff_samples == 3
810
      && load_raw == &LibRaw::lossy_dng_load_raw)
811
    {
812
      // Data should be linearized by DNG SDK
813
      C.black = 0;
814
      memset(C.cblack, 0, sizeof(C.cblack));
815
    }
816
#endif
817
818
    // XTrans Compressed?
819
93.6k
    if (!imgdata.idata.dng_version &&
820
51.7k
      makeIs(LIBRAW_CAMERAMAKER_Fujifilm) &&
821
2.71k
      (load_raw == &LibRaw::unpacked_load_raw))
822
2.52k
    {
823
2.52k
      if (imgdata.sizes.raw_width * (imgdata.sizes.raw_height * 2ul) !=
824
2.52k
        libraw_internal_data.unpacker_data.data_size)
825
2.39k
      {
826
2.39k
        if ((imgdata.sizes.raw_width * (imgdata.sizes.raw_height * 7ul)) / 4 ==
827
2.39k
          libraw_internal_data.unpacker_data.data_size)
828
86
          load_raw = &LibRaw::fuji_14bit_load_raw;
829
2.31k
        else
830
2.31k
          parse_fuji_compressed_header();
831
2.39k
      }
832
129
      else if (!strcmp(imgdata.idata.normalized_model, "X-H2S") 
833
15
        && libraw_internal_data.internal_data.input->size() 
834
15
        < (libraw_internal_data.unpacker_data.data_size + libraw_internal_data.unpacker_data.data_offset))
835
5
      {
836
5
            parse_fuji_compressed_header(); // try to use compressed header: X-H2S may record wrong data size
837
5
      }
838
2.52k
    }
839
      // set raw_inset_crops[1] via raw_aspect
840
93.6k
      if (imgdata.sizes.raw_aspect >= LIBRAW_IMAGE_ASPECT_MINIMAL_REAL_ASPECT_VALUE
841
910
          && imgdata.sizes.raw_aspect <= LIBRAW_IMAGE_ASPECT_MAXIMAL_REAL_ASPECT_VALUE
842
          /* crops[0] is valid*/
843
910
          && (imgdata.sizes.raw_inset_crops[0].cleft < 0xffff)
844
310
          && (imgdata.sizes.raw_inset_crops[0].cleft + imgdata.sizes.raw_inset_crops[0].cwidth <= imgdata.sizes.raw_width)
845
160
          && (imgdata.sizes.raw_inset_crops[0].ctop < 0xffff)
846
141
          && (imgdata.sizes.raw_inset_crops[0].ctop + imgdata.sizes.raw_inset_crops[0].cheight <= imgdata.sizes.raw_height)
847
107
          && imgdata.sizes.raw_inset_crops[0].cwidth > 0 && imgdata.sizes.raw_inset_crops[0].cheight >0
848
          /* crops[1] is not set*/
849
63
          && (imgdata.sizes.raw_inset_crops[1].cleft == 0xffff)
850
63
          && (imgdata.sizes.raw_inset_crops[1].ctop == 0xffff)
851
93.6k
          )
852
63
      {
853
63
          float c0_ratio = float(imgdata.sizes.raw_inset_crops[0].cwidth) / float(imgdata.sizes.raw_inset_crops[0].cheight);
854
63
          float c1_ratio = float(imgdata.sizes.raw_aspect) / 1000.f;
855
63
          if (c0_ratio / c1_ratio < 0.98 || c0_ratio / c1_ratio > 1.02) // set crops[1]
856
56
          {
857
56
              if (c1_ratio > c0_ratio) // requested image is wider, cut from top/bottom
858
40
              {
859
40
                  int newheight =  int(imgdata.sizes.raw_inset_crops[0].cwidth / c1_ratio);
860
40
                  int dtop = (imgdata.sizes.raw_inset_crops[0].cheight - newheight) / 2;
861
40
                  imgdata.sizes.raw_inset_crops[1].ctop = imgdata.sizes.raw_inset_crops[0].ctop + dtop;
862
40
                  imgdata.sizes.raw_inset_crops[1].cheight = newheight;
863
40
                  imgdata.sizes.raw_inset_crops[1].cleft = imgdata.sizes.raw_inset_crops[0].cleft;
864
40
                  imgdata.sizes.raw_inset_crops[1].cwidth = imgdata.sizes.raw_inset_crops[0].cwidth;
865
40
              }
866
16
              else
867
16
              {
868
16
                  int newwidth = int(imgdata.sizes.raw_inset_crops[0].cheight * c1_ratio);
869
16
                  int dleft = (imgdata.sizes.raw_inset_crops[0].cwidth - newwidth) / 2;
870
16
                  imgdata.sizes.raw_inset_crops[1].cleft = imgdata.sizes.raw_inset_crops[0].cleft + dleft;
871
16
                  imgdata.sizes.raw_inset_crops[1].cwidth = newwidth;
872
16
                  imgdata.sizes.raw_inset_crops[1].ctop = imgdata.sizes.raw_inset_crops[0].ctop;
873
16
                  imgdata.sizes.raw_inset_crops[1].cheight = imgdata.sizes.raw_inset_crops[0].cheight;
874
16
              }
875
56
          }
876
63
      }
877
878
93.6k
      int adjust_margins = 0;
879
93.6k
      if (makeIs(LIBRAW_CAMERAMAKER_Fujifilm) && (imgdata.idata.filters == 9))
880
81
      {
881
          // Adjust top/left margins for X-Trans
882
81
          int newtm = imgdata.sizes.top_margin % 6
883
81
              ? (imgdata.sizes.top_margin / 6 + 1) * 6
884
81
              : imgdata.sizes.top_margin;
885
81
          int newlm = imgdata.sizes.left_margin % 6
886
81
              ? (imgdata.sizes.left_margin / 6 + 1) * 6
887
81
              : imgdata.sizes.left_margin;
888
81
          if (newtm != imgdata.sizes.top_margin ||
889
68
              newlm != imgdata.sizes.left_margin)
890
15
          {
891
15
              imgdata.sizes.height -= (newtm - imgdata.sizes.top_margin);
892
15
              imgdata.sizes.top_margin = newtm;
893
15
              imgdata.sizes.width -= (newlm - imgdata.sizes.left_margin);
894
15
              imgdata.sizes.left_margin = newlm;
895
105
              for (int c1 = 0; c1 < 6; c1++)
896
630
                  for (int c2 = 0; c2 < 6; c2++)
897
540
                      imgdata.idata.xtrans[c1][c2] = imgdata.idata.xtrans_abs[c1][c2];
898
15
          }
899
81
          adjust_margins = 6;
900
81
      }
901
93.5k
      else if (!libraw_internal_data.internal_output_params.fuji_width
902
64.4k
          && imgdata.idata.filters >= 1000)
903
56.3k
    {
904
56.3k
          if ((imgdata.sizes.top_margin % 2) || (imgdata.sizes.left_margin % 2))
905
1.04k
          {
906
1.04k
              int crop[2] = { 0,0 };
907
1.04k
              unsigned filt;
908
1.04k
              int c;
909
1.04k
              if (imgdata.sizes.top_margin % 2)
910
665
              {
911
665
                  imgdata.sizes.top_margin += 1;
912
665
                  imgdata.sizes.height -= 1;
913
665
                  crop[1] = 1;
914
665
              }
915
1.04k
              if (imgdata.sizes.left_margin % 2)
916
745
              {
917
745
                  imgdata.sizes.left_margin += 1;
918
745
                  imgdata.sizes.width -= 1;
919
745
                  crop[0] = 1;
920
745
              }
921
17.7k
              for (filt = c = 0; c < 16; c++)
922
16.6k
                  filt |= FC((c >> 1) + (crop[1]), (c & 1) + (crop[0])) << c * 2;
923
1.04k
              imgdata.idata.filters = filt;
924
1.04k
          }
925
56.3k
          adjust_margins = 2;
926
56.3k
    }
927
928
93.6k
      if(adjust_margins) // adjust crop_inset margins
929
169k
          for (int i = 0; i < 2; i++)
930
112k
          {
931
112k
              if (imgdata.sizes.raw_inset_crops[i].cleft && imgdata.sizes.raw_inset_crops[i].cleft < 0xffff
932
965
                  && imgdata.sizes.raw_inset_crops[i].cwidth && imgdata.sizes.raw_inset_crops[i].cwidth < 0xffff
933
375
                  && (imgdata.sizes.raw_inset_crops[i].cleft%adjust_margins)
934
154
                  && (imgdata.sizes.raw_inset_crops[i].cwidth > adjust_margins))
935
115
              {
936
115
                  int newleft = ((imgdata.sizes.raw_inset_crops[i].cleft / adjust_margins) + 1) * adjust_margins;
937
115
                  int diff = newleft - imgdata.sizes.raw_inset_crops[i].cleft;
938
115
                  if (diff > 0)
939
115
                  {
940
115
                      imgdata.sizes.raw_inset_crops[i].cleft += diff;
941
115
                      imgdata.sizes.raw_inset_crops[i].cwidth -= diff;
942
115
                  }
943
115
              }
944
112k
              if (imgdata.sizes.raw_inset_crops[i].ctop && imgdata.sizes.raw_inset_crops[i].ctop < 0xffff
945
1.30k
                  && imgdata.sizes.raw_inset_crops[i].cheight && imgdata.sizes.raw_inset_crops[i].cheight < 0xffff
946
540
                  && (imgdata.sizes.raw_inset_crops[i].ctop%adjust_margins)
947
272
                  && (imgdata.sizes.raw_inset_crops[i].cheight > adjust_margins))
948
239
              {
949
239
                  int newtop = ((imgdata.sizes.raw_inset_crops[i].ctop / adjust_margins) + 1) * adjust_margins;
950
239
                  int diff = newtop - imgdata.sizes.raw_inset_crops[i].ctop;
951
239
                  if (diff > 0)
952
239
                  {
953
239
                      imgdata.sizes.raw_inset_crops[i].ctop += diff;
954
239
                      imgdata.sizes.raw_inset_crops[i].cheight -= diff;
955
239
                  }
956
239
              }
957
112k
          }
958
959
960
#ifdef USE_DNGSDK
961
    if (
962
      imgdata.rawparams.use_dngsdk &&
963
      !(imgdata.rawparams.options & (LIBRAW_RAWOPTIONS_DNG_STAGE2 | LIBRAW_RAWOPTIONS_DNG_STAGE3 | LIBRAW_RAWOPTIONS_DNG_DISABLEWBADJUST)))
964
#endif
965
93.6k
    {
966
      // Fix DNG white balance if needed: observed only for Kalpanika X3F tools produced DNGs
967
93.6k
      if (imgdata.idata.dng_version && (imgdata.idata.filters == 0) &&
968
2.62k
        imgdata.idata.colors > 1 && imgdata.idata.colors < 5)
969
1.02k
      {
970
1.02k
        float delta[4] = { 0.f, 0.f, 0.f, 0.f };
971
1.02k
        int black[4];
972
5.11k
        for (int c = 0; c < 4; c++)
973
4.09k
          black[c] = imgdata.color.dng_levels.dng_black +
974
4.09k
          imgdata.color.dng_levels.dng_cblack[c];
975
4.25k
        for (int c = 0; c < imgdata.idata.colors; c++)
976
3.22k
          delta[c] = float(imgdata.color.dng_levels.dng_whitelevel[c] - black[c]);
977
1.02k
        float mindelta = delta[0], maxdelta = delta[0];
978
3.22k
        for (int c = 1; c < imgdata.idata.colors; c++)
979
2.20k
        {
980
2.20k
          if (mindelta > delta[c])
981
65
            mindelta = delta[c];
982
2.20k
          if (maxdelta < delta[c])
983
59
            maxdelta = delta[c];
984
2.20k
        }
985
1.02k
        if (mindelta > 1 && maxdelta < (mindelta * 20)) // safety
986
352
        {
987
1.49k
          for (int c = 0; c < imgdata.idata.colors; c++)
988
1.14k
          {
989
1.14k
            imgdata.color.cam_mul[c] /= (delta[c] / maxdelta);
990
1.14k
            imgdata.color.pre_mul[c] /= (delta[c] / maxdelta);
991
1.14k
          }
992
352
          imgdata.color.maximum = unsigned(imgdata.color.cblack[0] + maxdelta);
993
352
        }
994
1.02k
      }
995
93.6k
    }
996
997
93.6k
    if (imgdata.idata.dng_version &&
998
13.9k
    makeIs(LIBRAW_CAMERAMAKER_Panasonic)
999
18
          && !strcasecmp(imgdata.idata.normalized_model, "DMC-LX100"))
1000
0
      imgdata.sizes.width = 4288;
1001
1002
93.6k
    if (imgdata.idata.dng_version && makeIs(LIBRAW_CAMERAMAKER_Leica))
1003
281
  {
1004
281
    if (!strcasecmp(imgdata.idata.normalized_model, "SL2"))
1005
0
      imgdata.sizes.height -= 16;
1006
281
    else if (!strcasecmp(imgdata.idata.normalized_model, "SL3"))
1007
0
    {
1008
0
      if (imgdata.sizes.raw_width == 9536)
1009
0
        imgdata.sizes.width -= 12;
1010
0
            else if (imgdata.sizes.raw_width == 7424)
1011
0
              imgdata.sizes.width -= 14;
1012
0
            else if (imgdata.sizes.raw_width == 5312)
1013
0
              imgdata.sizes.width -= 18;
1014
0
    }
1015
281
  }
1016
1017
93.6k
  if (makeIs(LIBRAW_CAMERAMAKER_Sony) &&
1018
5.54k
        imgdata.idata.dng_version)
1019
1.69k
    {
1020
1.69k
      if (S.raw_width == 3984)
1021
4
        S.width = 3925;
1022
1.69k
      else if (S.raw_width == 4288)
1023
5
        S.width = S.raw_width - 32;
1024
1.68k
      else if (S.raw_width == 4928 && S.height < 3280)
1025
4
        S.width = S.raw_width - 8;
1026
1.68k
      else if (S.raw_width == 5504)
1027
9
        S.width = S.raw_width - (S.height > 3664 ? 8 : 32);
1028
1.69k
    }
1029
1030
93.6k
  if (makeIs(LIBRAW_CAMERAMAKER_Sony) &&
1031
5.54k
        !imgdata.idata.dng_version)
1032
3.85k
    {
1033
3.85k
        if(load_raw ==&LibRaw::sony_arq_load_raw)
1034
22
        {
1035
22
            if(S.raw_width > 12000) // A7RM4 16x, both APS-C and APS
1036
1
                S.width = S.raw_width - 64;
1037
21
            else // A7RM3/M4 4x merge
1038
21
                S.width = S.raw_width - 32;
1039
22
        }
1040
1041
3.85k
      if (((!strncasecmp(imgdata.idata.model, "ILCE-7RM", 8) ||
1042
3.75k
            !strcasecmp(imgdata.idata.model, "ILCA-99M2")) &&
1043
131
           (S.raw_width == 5216 || S.raw_width == 6304)) // A7RM2/M3/A99M2 in APS mode; A7RM4 in APS-C
1044
3.84k
          ||
1045
3.84k
          (!strcasecmp(imgdata.idata.model, "ILCE-7R") && S.raw_width >= 4580 &&
1046
13
           S.raw_width < 5020) // A7R in crop mode, no samples, so size est.
1047
3.84k
          || (!strcasecmp(imgdata.idata.model, "ILCE-7") &&
1048
38
              S.raw_width == 3968) // A7 in crop mode
1049
3.83k
          ||
1050
3.83k
          ((!strncasecmp(imgdata.idata.model, "ILCE-7M", 7) ||
1051
3.78k
            !strcasecmp(imgdata.idata.model, "ILCE-9") ||
1052
#if 0
1053
            !strcasecmp(imgdata.idata.model,
1054
                        "SLT-A99V")) // Does SLT-A99 also have APS-C mode??
1055
#endif
1056
3.75k
           (mnCamID == SonyID_SLT_A99)) // 2 reasons: some cameras are SLT-A99, no 'V'; some are Hasselblad HV
1057
91
           && S.raw_width > 3750 &&
1058
32
           S.raw_width < 4120) // A7M2, A7M3, AA9, most likely APS-C raw_width
1059
                               // is 3968 (same w/ A7), but no samples, so guess
1060
3.83k
          || (!strncasecmp(imgdata.idata.model, "ILCE-7S", 7) &&
1061
47
              S.raw_width == 2816) // A7S2=> exact, hope it works for A7S-I too
1062
3.85k
      )
1063
23
        S.width = S.raw_width - 32;
1064
3.85k
    }
1065
1066
1067
    // FIXME: it is possible that DNG contains 4x main frames + some previews; in this case imgdata.idata.raw_count will be greater than 4
1068
93.6k
  if (makeIs(LIBRAW_CAMERAMAKER_Pentax) &&
1069
        /*!strcasecmp(imgdata.idata.model,"K-3 II")  &&*/
1070
1.27k
            imgdata.idata.raw_count == 4 &&
1071
8
        (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_PENTAX_PS_ALLFRAMES))
1072
0
    {
1073
0
      imgdata.idata.raw_count = 1;
1074
0
      imgdata.idata.filters = 0;
1075
0
      imgdata.idata.colors = 4;
1076
0
      imgdata.sizes.top_margin+=2;
1077
0
      imgdata.sizes.left_margin+=2;
1078
0
      imgdata.sizes.width-=4;
1079
0
      imgdata.sizes.height-=4;
1080
0
      IO.mix_green = 1;
1081
0
      pentax_component_load_raw = load_raw;
1082
0
      load_raw = &LibRaw::pentax_4shot_load_raw;
1083
0
    }
1084
1085
93.6k
  if (!imgdata.idata.dng_version && makeIs(LIBRAW_CAMERAMAKER_Leaf) &&
1086
1.75k
        !strcmp(imgdata.idata.model, "Credo 50"))
1087
3
    {
1088
3
      imgdata.color.pre_mul[0] = 1.f / 0.3984f;
1089
3
      imgdata.color.pre_mul[2] = 1.f / 0.7666f;
1090
3
      imgdata.color.pre_mul[1] = imgdata.color.pre_mul[3] = 1.0;
1091
3
    }
1092
1093
93.6k
  if (!imgdata.idata.dng_version && makeIs(LIBRAW_CAMERAMAKER_Fujifilm) &&
1094
2.71k
        (!strncmp(imgdata.idata.model, "S20Pro", 6) ||
1095
2.69k
         !strncmp(imgdata.idata.model, "F700", 4)))
1096
55
    {
1097
55
      imgdata.sizes.raw_width /= 2;
1098
55
      load_raw = &LibRaw::unpacked_load_raw_fuji_f700s20;
1099
55
    }
1100
1101
93.6k
    if (load_raw == &LibRaw::packed_load_raw &&
1102
1.80k
    makeIs(LIBRAW_CAMERAMAKER_Nikon) &&
1103
1.12k
        !libraw_internal_data.unpacker_data.load_flags &&
1104
940
        (!strncasecmp(imgdata.idata.model, "D810", 4) ||
1105
929
         !strcasecmp(imgdata.idata.model, "D4S")) &&
1106
17
        libraw_internal_data.unpacker_data.data_size * 2u ==
1107
17
            imgdata.sizes.raw_height * imgdata.sizes.raw_width * 3u)
1108
11
    {
1109
11
      libraw_internal_data.unpacker_data.load_flags = 80;
1110
11
    }
1111
    // Adjust BL for Sony A900/A850
1112
93.6k
    if (load_raw == &LibRaw::packed_load_raw &&
1113
1.80k
    makeIs(LIBRAW_CAMERAMAKER_Sony)) // 12 bit sony, but metadata may be for 14-bit range
1114
76
    {
1115
76
      if (C.maximum > 4095)
1116
33
        C.maximum = 4095;
1117
76
      if (C.black > 256 || C.cblack[0] > 256)
1118
38
      {
1119
38
        C.black /= 4;
1120
190
        for (int c = 0; c < 4; c++)
1121
152
          C.cblack[c] /= 4;
1122
6.99k
        for (unsigned c = 0; c < C.cblack[4] * C.cblack[5]; c++)
1123
6.95k
          C.cblack[6 + c] /= 4;
1124
38
      }
1125
76
    }
1126
1127
93.6k
  if (load_raw == &LibRaw::nikon_yuv_load_raw) // Is it Nikon sRAW?
1128
211
    {
1129
211
      load_raw = &LibRaw::nikon_load_sraw;
1130
211
      C.black = 0;
1131
211
      memset(C.cblack, 0, sizeof(C.cblack));
1132
211
      imgdata.idata.filters = 0;
1133
211
      libraw_internal_data.unpacker_data.tiff_samples = 3;
1134
211
      imgdata.idata.colors = 3;
1135
211
      double beta_1 = -5.79342238397656E-02;
1136
211
      double beta_2 = 3.28163551282665;
1137
211
      double beta_3 = -8.43136004842678;
1138
211
      double beta_4 = 1.03533181861023E+01;
1139
648k
      for (int i = 0; i <= 3072; i++)
1140
648k
      {
1141
648k
        double x = (double)i / 3072.;
1142
648k
        double y = (1. - exp(-beta_1 * x - beta_2 * x * x - beta_3 * x * x * x -
1143
648k
                             beta_4 * x * x * x * x));
1144
648k
        if (y < 0.)
1145
11.8k
          y = 0.;
1146
648k
        imgdata.color.curve[i] = ushort(y * 16383.f);
1147
648k
      }
1148
844
      for (int i = 0; i < 3; i++)
1149
3.16k
        for (int j = 0; j < 4; j++)
1150
2.53k
          imgdata.color.rgb_cam[i][j] = float(i == j);
1151
211
    }
1152
    // Adjust BL for Nikon 12bit
1153
93.6k
    if ((load_raw == &LibRaw::nikon_load_raw ||
1154
65.3k
         load_raw == &LibRaw::packed_load_raw ||
1155
63.5k
         load_raw == &LibRaw::nikon_load_padded_packed_raw) &&
1156
2.14k
     makeIs(LIBRAW_CAMERAMAKER_Nikon) &&
1157
1.13k
        strncmp(imgdata.idata.model, "COOLPIX", 7) &&
1158
1.11k
        libraw_internal_data.unpacker_data.tiff_bps == 12)
1159
170
    {
1160
170
      C.maximum = 4095;
1161
170
      C.black /= 4;
1162
850
      for (int c = 0; c < 4; c++)
1163
680
        C.cblack[c] /= 4;
1164
41.7k
      for (unsigned c = 0; c < C.cblack[4] * C.cblack[5]; c++)
1165
41.5k
        C.cblack[6 + c] /= 4;
1166
170
    }
1167
1168
    // Adjust wb_already_applied
1169
93.6k
    if (load_raw == &LibRaw::nikon_load_sraw)
1170
211
      imgdata.color.as_shot_wb_applied =
1171
211
          LIBRAW_ASWB_APPLIED | LIBRAW_ASWB_NIKON_SRAW;
1172
93.4k
    else if (makeIs(LIBRAW_CAMERAMAKER_Canon) &&
1173
6.53k
             MN.canon.multishot[0] >= 8 &&
1174
166
             MN.canon.multishot[1] > 0)
1175
136
      imgdata.color.as_shot_wb_applied =
1176
136
          LIBRAW_ASWB_APPLIED | LIBRAW_ASWB_CANON;
1177
93.2k
    else if (makeIs(LIBRAW_CAMERAMAKER_Nikon) &&
1178
2.75k
             MN.nikon.ExposureMode == 1)
1179
8
      imgdata.color.as_shot_wb_applied =
1180
8
          LIBRAW_ASWB_APPLIED | LIBRAW_ASWB_NIKON;
1181
93.2k
  else if (makeIs(LIBRAW_CAMERAMAKER_Pentax) &&
1182
1.27k
             ((MN.pentax.MultiExposure & 0x01) == 1))
1183
29
      imgdata.color.as_shot_wb_applied =
1184
29
          LIBRAW_ASWB_APPLIED | LIBRAW_ASWB_PENTAX;
1185
93.2k
  else if (makeIs(LIBRAW_CAMERAMAKER_Sony) && load_raw == &LibRaw::sony_ycbcr_load_raw)
1186
219
    imgdata.color.as_shot_wb_applied = LIBRAW_ASWB_APPLIED | LIBRAW_ASWB_SONY;
1187
93.0k
    else
1188
93.0k
      imgdata.color.as_shot_wb_applied = 0;
1189
1190
    // Adjust Highlight Linearity limit
1191
93.6k
    if (C.linear_max[0] < 0)
1192
0
    {
1193
0
      if (imgdata.idata.dng_version)
1194
0
      {
1195
0
        for (int c = 0; c < 4; c++)
1196
0
          C.linear_max[c] = -1 * C.linear_max[c] + imgdata.color.cblack[c + 6];
1197
0
      }
1198
0
      else
1199
0
      {
1200
0
        for (int c = 0; c < 4; c++)
1201
0
          C.linear_max[c] = -1 * C.linear_max[c] + imgdata.color.cblack[c];
1202
0
      }
1203
0
    }
1204
1205
93.6k
  if (makeIs(LIBRAW_CAMERAMAKER_Nikon) &&
1206
2.78k
    (!C.linear_max[0]) && (C.maximum > 1024) && (load_raw != &LibRaw::nikon_load_sraw))
1207
1.35k
    {
1208
1.35k
      C.linear_max[0] = C.linear_max[1] = C.linear_max[2] = C.linear_max[3] =
1209
1.35k
          (long)((float)(C.maximum) / 1.07f);
1210
1.35k
    }
1211
1212
    // Correct WB for Samsung GX20
1213
93.6k
  if (
1214
#if 0
1215
        /* GX20 should be corrected, but K20 is not */
1216
        makeIs(LIBRAW_CAMERAMAKER_Pentax) &&
1217
    !strcasecmp(imgdata.idata.normalized_model, "K20D")
1218
#endif
1219
#if 0
1220
    !strcasecmp(imgdata.idata.make, "Samsung") &&
1221
        !strcasecmp(imgdata.idata.model, "GX20")
1222
#endif
1223
93.6k
    makeIs(LIBRAW_CAMERAMAKER_Pentax) &&
1224
1.27k
    (mnCamID == PentaxID_GX20) // Samsung rebranding
1225
93.6k
    )
1226
65
    {
1227
1.69k
      for (int cnt = LIBRAW_WBI_Unknown; cnt <= LIBRAW_WBI_StudioTungsten; cnt++) {
1228
1.62k
        if (C.WB_Coeffs[cnt][1]) {
1229
95
          C.WB_Coeffs[cnt][0] = (int)((float)(C.WB_Coeffs[cnt][0]) * 1.0503f);
1230
95
          C.WB_Coeffs[cnt][2] = (int)((float)(C.WB_Coeffs[cnt][2]) * 2.2867f);
1231
95
        }
1232
1.62k
      }
1233
4.22k
      for (int cnt = 0; cnt < 64; cnt++) {
1234
4.16k
        if (C.WBCT_Coeffs[cnt][0] > 0.0f) {
1235
1.27k
          C.WBCT_Coeffs[cnt][1] *= 1.0503f;
1236
1.27k
          C.WBCT_Coeffs[cnt][3] *= 2.2867f;
1237
1.27k
        }
1238
4.16k
      }
1239
325
      for(int cnt = 0; cnt < 4; cnt++)
1240
260
        imgdata.color.pre_mul[cnt] =
1241
260
          float(C.WB_Coeffs[LIBRAW_WBI_Daylight][cnt]);
1242
65
    }
1243
1244
    // Adjust BL for Panasonic
1245
93.6k
    if (load_raw == &LibRaw::panasonic_load_raw &&
1246
480
    makeIs(LIBRAW_CAMERAMAKER_Panasonic) &&
1247
183
        ID.pana_black[0] && ID.pana_black[1] && ID.pana_black[2])
1248
10
    {
1249
10
      if (libraw_internal_data.unpacker_data.pana_encoding == 5)
1250
3
        libraw_internal_data.internal_output_params.zero_is_bad = 0;
1251
10
      C.black = 0;
1252
10
      int add = libraw_internal_data.unpacker_data.pana_encoding == 4 ? 15 : 0;
1253
10
      C.cblack[0] = ID.pana_black[0] + add;
1254
10
      C.cblack[1] = C.cblack[3] = ID.pana_black[1] + add;
1255
10
      C.cblack[2] = ID.pana_black[2] + add;
1256
10
      unsigned i = C.cblack[3];
1257
40
      for (int c = 0; c < 3; c++)
1258
30
        if (i > C.cblack[c])
1259
4
          i = C.cblack[c];
1260
50
      for (int c = 0; c < 4; c++)
1261
40
        C.cblack[c] -= i;
1262
10
      C.black = i;
1263
10
    }
1264
1265
    // Adjust sizes for X3F processing
1266
#ifdef USE_X3FTOOLS
1267
  if (load_raw == &LibRaw::x3f_load_raw)
1268
    {
1269
      for (int i = 0; i < foveon_count; i++)
1270
        if (!strcasecmp(imgdata.idata.make, foveon_data[i].make) &&
1271
            !strcasecmp(imgdata.idata.model, foveon_data[i].model) &&
1272
            imgdata.sizes.raw_width == foveon_data[i].raw_width &&
1273
            imgdata.sizes.raw_height == foveon_data[i].raw_height)
1274
        {
1275
          imgdata.sizes.top_margin = foveon_data[i].top_margin;
1276
          imgdata.sizes.left_margin = foveon_data[i].left_margin;
1277
          imgdata.sizes.width = imgdata.sizes.iwidth = foveon_data[i].width;
1278
          imgdata.sizes.height = imgdata.sizes.iheight = foveon_data[i].height;
1279
          C.maximum = foveon_data[i].white;
1280
          break;
1281
        }
1282
    }
1283
#endif
1284
#if 0
1285
    size_t bytes = ID.input->size()-libraw_internal_data.unpacker_data.data_offset;
1286
    float bpp = float(bytes)/float(S.raw_width)/float(S.raw_height);
1287
    float bpp2 = float(bytes)/float(S.width)/float(S.height);
1288
    if(!strcasecmp(imgdata.idata.make,"Hasselblad") && bpp == 6.0f)
1289
      {
1290
        load_raw = &LibRaw::hasselblad_full_load_raw;
1291
        S.width = S.raw_width;
1292
        S.height = S.raw_height;
1293
        P1.filters = 0;
1294
        P1.colors=3;
1295
        P1.raw_count=1;
1296
        C.maximum=0xffff;
1297
      }
1298
#endif
1299
93.6k
    if (C.profile_length)
1300
201
    {
1301
201
      if (C.profile)
1302
0
        free(C.profile);
1303
201
    INT64 profile_sz = MIN(INT64(C.profile_length), ID.input->size() - ID.profile_offset);
1304
201
    if (profile_sz > 0LL && profile_sz < LIBRAW_MAX_PROFILE_SIZE_MB * 1024LL * 1024LL)
1305
164
    {
1306
164
        C.profile = calloc(size_t(profile_sz),1);
1307
164
        C.profile_length = unsigned(profile_sz);
1308
164
        ID.input->seek(ID.profile_offset, SEEK_SET);
1309
164
        ID.input->read(C.profile, size_t(profile_sz), 1);
1310
164
    }
1311
37
    else
1312
37
      C.profile = NULL;
1313
201
    }
1314
1315
93.6k
    SET_PROC_FLAG(LIBRAW_PROGRESS_IDENTIFY);
1316
93.6k
  }
1317
93.6k
  catch (const std::bad_alloc&)
1318
93.6k
  {
1319
0
      EXCEPTION_HANDLER(LIBRAW_EXCEPTION_ALLOC);
1320
0
  }
1321
93.6k
  catch (const LibRaw_exceptions& err)
1322
93.6k
  {
1323
27.9k
    EXCEPTION_HANDLER(err);
1324
27.9k
  }
1325
93.6k
  catch (const std::exception& )
1326
93.6k
  {
1327
0
    EXCEPTION_HANDLER(LIBRAW_EXCEPTION_IO_CORRUPT);
1328
0
  }
1329
1330
65.6k
final:;
1331
1332
65.6k
  if (P1.raw_count < 1)
1333
40.7k
    return LIBRAW_FILE_UNSUPPORTED;
1334
1335
24.9k
  write_fun = &LibRaw::write_ppm_tiff;
1336
1337
24.9k
  if (load_raw == &LibRaw::kodak_ycbcr_load_raw)
1338
231
  {
1339
231
    S.height += S.height & 1;
1340
231
    S.width += S.width & 1;
1341
231
  }
1342
1343
24.9k
  IO.shrink =
1344
24.9k
      P1.filters &&
1345
20.2k
      (O.half_size || ((O.threshold || O.aber[0] != 1 || O.aber[2] != 1)));
1346
24.9k
  if (IO.shrink && P1.filters >= 1000)
1347
18.1k
  {
1348
18.1k
    S.width &= 65534;
1349
18.1k
    S.height &= 65534;
1350
18.1k
  }
1351
1352
24.9k
  S.iheight = (S.height + IO.shrink) >> IO.shrink;
1353
24.9k
  S.iwidth = (S.width + IO.shrink) >> IO.shrink;
1354
1355
  // Save color,sizes and internal data into raw_image fields
1356
24.9k
  memmove(&imgdata.rawdata.color, &imgdata.color, sizeof(imgdata.color));
1357
24.9k
  memmove(&imgdata.rawdata.sizes, &imgdata.sizes, sizeof(imgdata.sizes));
1358
24.9k
  memmove(&imgdata.rawdata.iparams, &imgdata.idata, sizeof(imgdata.idata));
1359
24.9k
  memmove(&imgdata.rawdata.ioparams,
1360
24.9k
          &libraw_internal_data.internal_output_params,
1361
24.9k
          sizeof(libraw_internal_data.internal_output_params));
1362
1363
24.9k
  SET_PROC_FLAG(LIBRAW_PROGRESS_SIZE_ADJUST);
1364
1365
24.9k
  return LIBRAW_SUCCESS;
1366
65.6k
}