File indexing completed on 2025-01-05 03:57:08

0001 /* -*- C++ -*-
0002  * Copyright 2019-2021 LibRaw LLC (info@libraw.org)
0003  *
0004 
0005  LibRaw is free software; you can redistribute it and/or modify
0006  it under the terms of the one of two licenses as you choose:
0007 
0008 1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
0009    (See file LICENSE.LGPL provided in LibRaw distribution archive for details).
0010 
0011 2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
0012    (See file LICENSE.CDDL provided in LibRaw distribution archive for details).
0013 
0014  */
0015 
0016 #include "../../internal/libraw_cxx_defs.h"
0017 #include "../../internal/libraw_cameraids.h"
0018 
0019 #ifndef LIBRAW_NO_IOSTREAMS_DATASTREAM
0020 int LibRaw::open_file(const char *fname, INT64 max_buf_size)
0021 {
0022     int big = 0;
0023     if (max_buf_size == LIBRAW_OPEN_BIGFILE)
0024         big = 1;
0025     else if (max_buf_size == LIBRAW_OPEN_FILE)
0026         big = 0;
0027     else
0028     {
0029 #ifndef LIBRAW_WIN32_CALLS
0030         struct stat st;
0031         if (stat(fname, &st))
0032             return LIBRAW_IO_ERROR;
0033         big = (st.st_size > max_buf_size) ? 1 : 0;
0034 #else
0035         struct _stati64 st;
0036         if (_stati64(fname, &st))
0037             return LIBRAW_IO_ERROR;
0038         big = (st.st_size > max_buf_size) ? 1 : 0;
0039 #endif
0040     }
0041 
0042   LibRaw_abstract_datastream *stream;
0043   try
0044   {
0045     if (big)
0046       stream = new LibRaw_bigfile_datastream(fname);
0047     else
0048       stream = new LibRaw_file_datastream(fname);
0049   }
0050 
0051   catch (const std::bad_alloc& )
0052   {
0053     recycle();
0054     return LIBRAW_UNSUFFICIENT_MEMORY;
0055   }
0056   if (!stream->valid())
0057   {
0058     delete stream;
0059     return LIBRAW_IO_ERROR;
0060   }
0061   ID.input_internal = 0; // preserve from deletion on error
0062   int ret = open_datastream(stream);
0063   if (ret == LIBRAW_SUCCESS)
0064   {
0065     ID.input_internal = 1; // flag to delete datastream on recycle
0066   }
0067   else
0068   {
0069     delete stream;
0070     ID.input_internal = 0;
0071   }
0072   return ret;
0073 }
0074 
0075 #if defined(WIN32) || defined(_WIN32)
0076 #ifndef LIBRAW_WIN32_UNICODEPATHS
0077 int LibRaw::open_file(const wchar_t *, INT64)
0078 {
0079   return LIBRAW_NOT_IMPLEMENTED;
0080 }
0081 #else
0082 int LibRaw::open_file(const wchar_t *fname, INT64 max_buf_size)
0083 {
0084     int big = 0;
0085     if (max_buf_size == LIBRAW_OPEN_BIGFILE)
0086         big = 1;
0087     else if (max_buf_size == LIBRAW_OPEN_FILE)
0088         big = 0;
0089     else
0090     {
0091         struct _stati64 st;
0092         if (_wstati64(fname, &st))
0093             return LIBRAW_IO_ERROR;
0094         big = (st.st_size > max_buf_size) ? 1 : 0;
0095     }
0096 
0097   LibRaw_abstract_datastream *stream;
0098   try
0099   {
0100     if (big)
0101       stream = new LibRaw_bigfile_datastream(fname);
0102     else
0103       stream = new LibRaw_file_datastream(fname);
0104   }
0105 
0106   catch (const std::bad_alloc&)
0107   {
0108     recycle();
0109     return LIBRAW_UNSUFFICIENT_MEMORY;
0110   }
0111   if (!stream->valid())
0112   {
0113     delete stream;
0114     return LIBRAW_IO_ERROR;
0115   }
0116   ID.input_internal = 0; // preserve from deletion on error
0117   int ret = open_datastream(stream);
0118   if (ret == LIBRAW_SUCCESS)
0119   {
0120     ID.input_internal = 1; // flag to delete datastream on recycle
0121   }
0122   else
0123   {
0124     delete stream;
0125     ID.input_internal = 0;
0126   }
0127   return ret;
0128 }
0129 #endif
0130 #endif
0131 
0132 #else /* LIBRAW_NO_IOSTREAMS_DATASTREAM*/
0133 
0134 int LibRaw::libraw_openfile_tail(LibRaw_abstract_datastream *stream)
0135 {
0136     if (!stream->valid())
0137     {
0138         delete stream;
0139         return LIBRAW_IO_ERROR;
0140     }
0141     ID.input_internal = 0; // preserve from deletion on error
0142     int ret = open_datastream(stream);
0143     if (ret == LIBRAW_SUCCESS)
0144     {
0145         ID.input_internal = 1; // flag to delete datastream on recycle
0146     }
0147     else
0148     {
0149         delete stream;
0150         ID.input_internal = 0;
0151     }
0152     return ret;
0153 }
0154 
0155 int LibRaw::open_file(const char *fname)
0156 {
0157     LibRaw_abstract_datastream *stream;
0158     try
0159     {
0160 #ifdef LIBRAW_WIN32_CALLS
0161         stream = new LibRaw_bigfile_buffered_datastream(fname);
0162 #else
0163         stream = new LibRaw_bigfile_datastream(fname);
0164 #endif
0165     }
0166     catch (const std::bad_alloc&)
0167     {
0168         recycle();
0169         return LIBRAW_UNSUFFICIENT_MEMORY;
0170     }
0171     if ((stream->size() > (INT64)LIBRAW_MAX_NONDNG_RAW_FILE_SIZE) && (stream->size() > (INT64)LIBRAW_MAX_DNG_RAW_FILE_SIZE))
0172     {
0173       delete stream;
0174       return LIBRAW_TOO_BIG;
0175     }
0176     return libraw_openfile_tail(stream);
0177 }
0178 
0179 #if defined(WIN32) || defined(_WIN32)
0180 #ifndef LIBRAW_WIN32_UNICODEPATHS
0181 int LibRaw::open_file(const wchar_t *)
0182 {
0183     return LIBRAW_NOT_IMPLEMENTED;
0184 }
0185 #else
0186 int LibRaw::open_file(const wchar_t *fname)
0187 {
0188     LibRaw_abstract_datastream *stream;
0189     try
0190     {
0191 #ifdef LIBRAW_WIN32_CALLS
0192         stream = new LibRaw_bigfile_buffered_datastream(fname);
0193 #else
0194         stream = new LibRaw_bigfile_datastream(fname);
0195 #endif
0196     }
0197     catch (const std::bad_alloc&)
0198     {
0199         recycle();
0200         return LIBRAW_UNSUFFICIENT_MEMORY;
0201     }
0202     if ((stream->size() > (INT64)LIBRAW_MAX_DNG_RAW_FILE_SIZE) && (stream->size() > (INT64)LIBRAW_MAX_NONDNG_RAW_FILE_SIZE))
0203     {
0204       delete stream;
0205       return LIBRAW_TOO_BIG;
0206     }
0207 
0208     return libraw_openfile_tail(stream);
0209 }
0210 #endif
0211 #endif
0212 
0213 #endif
0214 
0215 int LibRaw::open_buffer(const void *buffer, size_t size)
0216 {
0217   // this stream will close on recycle()
0218   if (!buffer || buffer == (const void *)-1)
0219     return LIBRAW_IO_ERROR;
0220 
0221   if ((size > (INT64)LIBRAW_MAX_DNG_RAW_FILE_SIZE) && (size > (INT64)LIBRAW_MAX_NONDNG_RAW_FILE_SIZE))   
0222       return LIBRAW_TOO_BIG;
0223 
0224   LibRaw_buffer_datastream *stream;
0225   try
0226   {
0227     stream = new LibRaw_buffer_datastream(buffer, size);
0228   }
0229   catch (const std::bad_alloc& )
0230   {
0231     recycle();
0232     return LIBRAW_UNSUFFICIENT_MEMORY;
0233   }
0234   if (!stream->valid())
0235   {
0236     delete stream;
0237     return LIBRAW_IO_ERROR;
0238   }
0239   ID.input_internal = 0; // preserve from deletion on error
0240   int ret = open_datastream(stream);
0241   if (ret == LIBRAW_SUCCESS)
0242   {
0243     ID.input_internal = 1; // flag to delete datastream on recycle
0244   }
0245   else
0246   {
0247     delete stream;
0248     ID.input_internal = 0;
0249   }
0250   return ret;
0251 }
0252 
0253 int LibRaw::open_bayer(const unsigned char *buffer, unsigned datalen,
0254                        ushort _raw_width, ushort _raw_height,
0255                        ushort _left_margin, ushort _top_margin,
0256                        ushort _right_margin, ushort _bottom_margin,
0257                        unsigned char procflags, unsigned char bayer_pattern,
0258                        unsigned unused_bits, unsigned otherflags,
0259                        unsigned black_level)
0260 {
0261   // this stream will close on recycle()
0262   if (!buffer || buffer == (const void *)-1)
0263     return LIBRAW_IO_ERROR;
0264 
0265   LibRaw_buffer_datastream *stream;
0266   try
0267   {
0268     stream = new LibRaw_buffer_datastream(buffer, datalen);
0269   }
0270   catch (const std::bad_alloc& )
0271   {
0272     recycle();
0273     return LIBRAW_UNSUFFICIENT_MEMORY;
0274   }
0275   if (!stream->valid())
0276   {
0277     delete stream;
0278     return LIBRAW_IO_ERROR;
0279   }
0280   ID.input = stream;
0281   SET_PROC_FLAG(LIBRAW_PROGRESS_OPEN);
0282   // From identify
0283   initdata();
0284   strcpy(imgdata.idata.make, "BayerDump");
0285   snprintf(imgdata.idata.model, sizeof(imgdata.idata.model) - 1,
0286            "%u x %u pixels", _raw_width, _raw_height);
0287   S.flip = procflags >> 2;
0288   libraw_internal_data.internal_output_params.zero_is_bad = procflags & 2;
0289   libraw_internal_data.unpacker_data.data_offset = 0;
0290   S.raw_width = _raw_width;
0291   S.raw_height = _raw_height;
0292   S.left_margin = _left_margin;
0293   S.top_margin = _top_margin;
0294   S.width = S.raw_width - S.left_margin - _right_margin;
0295   S.height = S.raw_height - S.top_margin - _bottom_margin;
0296 
0297   imgdata.idata.filters = 0x1010101 * bayer_pattern;
0298   imgdata.idata.colors =
0299       4 - !((imgdata.idata.filters & imgdata.idata.filters >> 1) & 0x5555);
0300   libraw_internal_data.unpacker_data.load_flags = otherflags;
0301   switch (libraw_internal_data.unpacker_data.tiff_bps =
0302               (datalen)*8 / (S.raw_width * S.raw_height))
0303   {
0304   case 8:
0305     load_raw = &LibRaw::eight_bit_load_raw;
0306     break;
0307   case 10:
0308     if ((datalen) / S.raw_height * 3u >= S.raw_width * 4u)
0309     {
0310       load_raw = &LibRaw::android_loose_load_raw;
0311       break;
0312     }
0313     else if (libraw_internal_data.unpacker_data.load_flags & 1)
0314     {
0315       load_raw = &LibRaw::android_tight_load_raw;
0316       break;
0317     }
0318   case 12:
0319     libraw_internal_data.unpacker_data.load_flags |= 128;
0320     load_raw = &LibRaw::packed_load_raw;
0321     break;
0322   case 16:
0323     libraw_internal_data.unpacker_data.order =
0324         0x4949 | 0x404 * (libraw_internal_data.unpacker_data.load_flags & 1);
0325     libraw_internal_data.unpacker_data.tiff_bps -=
0326         libraw_internal_data.unpacker_data.load_flags >> 4;
0327     libraw_internal_data.unpacker_data.tiff_bps -=
0328         libraw_internal_data.unpacker_data.load_flags =
0329             libraw_internal_data.unpacker_data.load_flags >> 1 & 7;
0330     load_raw = &LibRaw::unpacked_load_raw;
0331   }
0332   C.maximum =
0333       (1 << libraw_internal_data.unpacker_data.tiff_bps) - (1 << unused_bits);
0334   C.black = black_level;
0335   S.iwidth = S.width;
0336   S.iheight = S.height;
0337   imgdata.idata.colors = 3;
0338   imgdata.idata.filters |= ((imgdata.idata.filters >> 2 & 0x22222222) |
0339                             (imgdata.idata.filters << 2 & 0x88888888)) &
0340                            imgdata.idata.filters << 1;
0341 
0342   imgdata.idata.raw_count = 1;
0343   for (int i = 0; i < 4; i++)
0344     imgdata.color.pre_mul[i] = 1.0;
0345 
0346   strcpy(imgdata.idata.cdesc, "RGBG");
0347 
0348   ID.input_internal = 1;
0349   SET_PROC_FLAG(LIBRAW_PROGRESS_IDENTIFY);
0350   return LIBRAW_SUCCESS;
0351 }
0352 
0353 struct foveon_data_t
0354 {
0355   const char *make;
0356   const char *model;
0357   const int raw_width, raw_height;
0358   const int white;
0359   const int left_margin, top_margin;
0360   const int width, height;
0361 } foveon_data[] = {
0362     {"Sigma", "SD9", 2304, 1531, 12000, 20, 8, 2266, 1510},
0363     {"Sigma", "SD9", 1152, 763, 12000, 10, 2, 1132, 755},
0364     {"Sigma", "SD10", 2304, 1531, 12000, 20, 8, 2266, 1510},
0365     {"Sigma", "SD10", 1152, 763, 12000, 10, 2, 1132, 755},
0366     {"Sigma", "SD14", 2688, 1792, 14000, 18, 12, 2651, 1767},
0367     {"Sigma", "SD14", 2688, 896, 14000, 18, 6, 2651, 883}, // 2/3
0368     {"Sigma", "SD14", 1344, 896, 14000, 9, 6, 1326, 883},  // 1/2
0369     {"Sigma", "SD15", 2688, 1792, 2900, 18, 12, 2651, 1767},
0370     {"Sigma", "SD15", 2688, 896, 2900, 18, 6, 2651, 883}, // 2/3 ?
0371     {"Sigma", "SD15", 1344, 896, 2900, 9, 6, 1326, 883},  // 1/2 ?
0372     {"Sigma", "DP1", 2688, 1792, 2100, 18, 12, 2651, 1767},
0373     {"Sigma", "DP1", 2688, 896, 2100, 18, 6, 2651, 883}, // 2/3 ?
0374     {"Sigma", "DP1", 1344, 896, 2100, 9, 6, 1326, 883},  // 1/2 ?
0375     {"Sigma", "DP1S", 2688, 1792, 2200, 18, 12, 2651, 1767},
0376     {"Sigma", "DP1S", 2688, 896, 2200, 18, 6, 2651, 883}, // 2/3
0377     {"Sigma", "DP1S", 1344, 896, 2200, 9, 6, 1326, 883},  // 1/2
0378     {"Sigma", "DP1X", 2688, 1792, 3560, 18, 12, 2651, 1767},
0379     {"Sigma", "DP1X", 2688, 896, 3560, 18, 6, 2651, 883}, // 2/3
0380     {"Sigma", "DP1X", 1344, 896, 3560, 9, 6, 1326, 883},  // 1/2
0381     {"Sigma", "DP2", 2688, 1792, 2326, 13, 16, 2651, 1767},
0382     {"Sigma", "DP2", 2688, 896, 2326, 13, 8, 2651, 883}, // 2/3 ??
0383     {"Sigma", "DP2", 1344, 896, 2326, 7, 8, 1325, 883},  // 1/2 ??
0384     {"Sigma", "DP2S", 2688, 1792, 2300, 18, 12, 2651, 1767},
0385     {"Sigma", "DP2S", 2688, 896, 2300, 18, 6, 2651, 883}, // 2/3
0386     {"Sigma", "DP2S", 1344, 896, 2300, 9, 6, 1326, 883},  // 1/2
0387     {"Sigma", "DP2X", 2688, 1792, 2300, 18, 12, 2651, 1767},
0388     {"Sigma", "DP2X", 2688, 896, 2300, 18, 6, 2651, 883},           // 2/3
0389     {"Sigma", "DP2X", 1344, 896, 2300, 9, 6, 1325, 883},            // 1/2
0390     {"Sigma", "SD1", 4928, 3264, 3900, 12, 52, 4807, 3205},         // Full size
0391     {"Sigma", "SD1", 4928, 1632, 3900, 12, 26, 4807, 1603},         // 2/3 size
0392     {"Sigma", "SD1", 2464, 1632, 3900, 6, 26, 2403, 1603},          // 1/2 size
0393     {"Sigma", "SD1 Merrill", 4928, 3264, 3900, 12, 52, 4807, 3205}, // Full size
0394     {"Sigma", "SD1 Merrill", 4928, 1632, 3900, 12, 26, 4807, 1603}, // 2/3 size
0395     {"Sigma", "SD1 Merrill", 2464, 1632, 3900, 6, 26, 2403, 1603},  // 1/2 size
0396     {"Sigma", "DP1 Merrill", 4928, 3264, 3900, 12, 0, 4807, 3205},
0397     {"Sigma", "DP1 Merrill", 2464, 1632, 3900, 12, 0, 2403, 1603}, // 1/2 size
0398     {"Sigma", "DP1 Merrill", 4928, 1632, 3900, 12, 0, 4807, 1603}, // 2/3 size
0399     {"Sigma", "DP2 Merrill", 4928, 3264, 3900, 12, 0, 4807, 3205},
0400     {"Sigma", "DP2 Merrill", 2464, 1632, 3900, 12, 0, 2403, 1603}, // 1/2 size
0401     {"Sigma", "DP2 Merrill", 4928, 1632, 3900, 12, 0, 4807, 1603}, // 2/3 size
0402     {"Sigma", "DP3 Merrill", 4928, 3264, 3900, 12, 0, 4807, 3205},
0403     {"Sigma", "DP3 Merrill", 2464, 1632, 3900, 12, 0, 2403, 1603}, // 1/2 size
0404     {"Sigma", "DP3 Merrill", 4928, 1632, 3900, 12, 0, 4807, 1603}, // 2/3 size
0405     {"Polaroid", "x530", 1440, 1088, 2700, 10, 13, 1419, 1059},
0406     // dp2 Q
0407     {"Sigma", "dp3 Quattro", 5888, 3776, 16383, 204, 76, 5446,
0408      3624}, // full size, new fw ??
0409     {"Sigma", "dp3 Quattro", 5888, 3672, 16383, 204, 24, 5446,
0410      3624}, // full size
0411     {"Sigma", "dp3 Quattro", 2944, 1836, 16383, 102, 12, 2723,
0412      1812}, // half size
0413     {"Sigma", "dp3 Quattro", 2944, 1888, 16383, 102, 38, 2723,
0414      1812}, // half size, new fw??
0415 
0416     {"Sigma", "dp2 Quattro", 5888, 3776, 16383, 204, 76, 5446,
0417      3624}, // full size, new fw
0418     {"Sigma", "dp2 Quattro", 5888, 3672, 16383, 204, 24, 5446,
0419      3624}, // full size
0420     {"Sigma", "dp2 Quattro", 2944, 1836, 16383, 102, 12, 2723,
0421      1812}, // half size
0422     {"Sigma", "dp2 Quattro", 2944, 1888, 16383, 102, 38, 2723,
0423      1812}, // half size, new fw
0424 
0425     {"Sigma", "dp1 Quattro", 5888, 3776, 16383, 204, 76, 5446,
0426      3624}, // full size, new fw??
0427     {"Sigma", "dp1 Quattro", 5888, 3672, 16383, 204, 24, 5446,
0428      3624}, // full size
0429     {"Sigma", "dp1 Quattro", 2944, 1836, 16383, 102, 12, 2723,
0430      1812}, // half size
0431     {"Sigma", "dp1 Quattro", 2944, 1888, 16383, 102, 38, 2723,
0432      1812}, // half size, new fw
0433 
0434     {"Sigma", "dp0 Quattro", 5888, 3776, 16383, 204, 76, 5446,
0435      3624}, // full size, new fw??
0436     {"Sigma", "dp0 Quattro", 5888, 3672, 16383, 204, 24, 5446,
0437      3624}, // full size
0438     {"Sigma", "dp0 Quattro", 2944, 1836, 16383, 102, 12, 2723,
0439      1812}, // half size
0440     {"Sigma", "dp0 Quattro", 2944, 1888, 16383, 102, 38, 2723,
0441      1812}, // half size, new fw
0442     // Sigma sd Quattro
0443     {"Sigma", "sd Quattro", 5888, 3776, 16383, 204, 76, 5446,
0444      3624}, // full size
0445     {"Sigma", "sd Quattro", 2944, 1888, 16383, 102, 38, 2723,
0446      1812}, // half size
0447     // Sd Quattro H
0448     {"Sigma", "sd Quattro H", 6656, 4480, 4000, 224, 160, 6208,
0449      4160}, // full size
0450     {"Sigma", "sd Quattro H", 3328, 2240, 4000, 112, 80, 3104,
0451      2080},                                                        // half size
0452     {"Sigma", "sd Quattro H", 5504, 3680, 4000, 0, 4, 5496, 3668}, // full size
0453     {"Sigma", "sd Quattro H", 2752, 1840, 4000, 0, 2, 2748, 1834}, // half size
0454 };
0455 const int foveon_count = sizeof(foveon_data) / sizeof(foveon_data[0]);
0456 
0457 int LibRaw::open_datastream(LibRaw_abstract_datastream *stream)
0458 {
0459 
0460   if (!stream)
0461     return ENOENT;
0462   if (!stream->valid())
0463     return LIBRAW_IO_ERROR;
0464   if ((stream->size() > (INT64)LIBRAW_MAX_DNG_RAW_FILE_SIZE) && (stream->size() > (INT64)LIBRAW_MAX_NONDNG_RAW_FILE_SIZE))
0465       return LIBRAW_TOO_BIG;
0466 
0467   recycle();
0468   if (callbacks.pre_identify_cb)
0469   {
0470     int r = (callbacks.pre_identify_cb)(this);
0471     if (r == 1)
0472       goto final;
0473   }
0474 
0475   try
0476   {
0477       ID.input = stream;
0478       SET_PROC_FLAG(LIBRAW_PROGRESS_OPEN);
0479 
0480       identify();
0481 
0482       // Fuji layout files: either DNG or unpacked_load_raw should be used
0483       if (libraw_internal_data.internal_output_params.fuji_width || libraw_internal_data.unpacker_data.fuji_layout)
0484       {
0485         if (!imgdata.idata.dng_version && load_raw != &LibRaw::unpacked_load_raw
0486             && load_raw != &LibRaw::unpacked_load_raw_FujiDBP 
0487             && load_raw != &LibRaw::unpacked_load_raw_fuji_f700s20
0488             )
0489           return LIBRAW_FILE_UNSUPPORTED;
0490       }
0491 
0492       // promote the old single thumbnail to the thumbs_list if not present already
0493       if (imgdata.thumbs_list.thumbcount < LIBRAW_THUMBNAIL_MAXCOUNT)
0494       {
0495           bool already = false;
0496           if(imgdata.thumbnail.tlength || libraw_internal_data.internal_data.toffset)
0497               for(int i = 0; i < imgdata.thumbs_list.thumbcount; i++)
0498                   if (imgdata.thumbs_list.thumblist[i].toffset == libraw_internal_data.internal_data.toffset
0499                       && imgdata.thumbs_list.thumblist[i].tlength == imgdata.thumbnail.tlength)
0500                   {
0501                       already = true;
0502                       break;
0503                   }
0504           if (!already)
0505           {
0506               int idx = imgdata.thumbs_list.thumbcount;
0507               imgdata.thumbs_list.thumblist[idx].toffset = libraw_internal_data.internal_data.toffset;
0508               imgdata.thumbs_list.thumblist[idx].tlength = imgdata.thumbnail.tlength;
0509               imgdata.thumbs_list.thumblist[idx].tflip = 0xffff;
0510               imgdata.thumbs_list.thumblist[idx].tformat = libraw_internal_data.unpacker_data.thumb_format;
0511               imgdata.thumbs_list.thumblist[idx].tmisc = libraw_internal_data.unpacker_data.thumb_misc;
0512               // promote if set
0513               imgdata.thumbs_list.thumblist[idx].twidth = imgdata.thumbnail.twidth;
0514               imgdata.thumbs_list.thumblist[idx].theight = imgdata.thumbnail.theight;
0515               imgdata.thumbs_list.thumbcount++;
0516           }
0517       }
0518 
0519 
0520       imgdata.lens.Lens[sizeof(imgdata.lens.Lens) - 1] = 0; // make sure lens is 0-terminated
0521 
0522       if (callbacks.post_identify_cb)
0523           (callbacks.post_identify_cb)(this);
0524 
0525 #define isRIC imgdata.sizes.raw_inset_crops[0]
0526 
0527       if (!imgdata.idata.dng_version && makeIs(LIBRAW_CAMERAMAKER_Fujifilm)
0528           && (!strcmp(imgdata.idata.normalized_model, "S3Pro")
0529               || !strcmp(imgdata.idata.normalized_model, "S5Pro")
0530               || !strcmp(imgdata.idata.normalized_model, "S2Pro")))
0531       {
0532           isRIC.cleft = isRIC.ctop = 0xffff;
0533           isRIC.cwidth = isRIC.cheight = 0;
0534       }
0535       // Wipe out canon  incorrect in-camera crop
0536       if (!imgdata.idata.dng_version && makeIs(LIBRAW_CAMERAMAKER_Canon)
0537           && isRIC.cleft == 0 && isRIC.ctop == 0 // non symmetric!
0538           && isRIC.cwidth < (imgdata.sizes.raw_width * 4 / 5))  // less than 80% of sensor width
0539       {
0540         isRIC.cleft = isRIC.ctop = 0xffff;
0541         isRIC.cwidth = isRIC.cheight = 0;
0542       }
0543 
0544       // Wipe out non-standard WB
0545       if (!imgdata.idata.dng_version &&
0546           (makeIs(LIBRAW_CAMERAMAKER_Sony) && !strcmp(imgdata.idata.normalized_model, "DSC-F828"))
0547           && !(imgdata.rawparams.options & LIBRAW_RAWOPTIONS_PROVIDE_NONSTANDARD_WB))
0548       {
0549           for (int i = 0; i < 4; i++) imgdata.color.cam_mul[i] = (i == 1);
0550           memset(imgdata.color.WB_Coeffs, 0, sizeof(imgdata.color.WB_Coeffs));
0551           memset(imgdata.color.WBCT_Coeffs, 0, sizeof(imgdata.color.WBCT_Coeffs));
0552       }
0553 
0554       if (load_raw == &LibRaw::nikon_load_raw)
0555           nikon_read_curve();
0556 
0557       if (load_raw == &LibRaw::lossless_jpeg_load_raw &&
0558           MN.canon.RecordMode && makeIs(LIBRAW_CAMERAMAKER_Kodak) &&
0559           /* Not normalized models here, it is intentional */
0560           (!strncasecmp(imgdata.idata.model, "EOS D2000", 9) || // if we want something different for B&W cameras,
0561               !strncasecmp(imgdata.idata.model, "EOS D6000", 9)))  // it's better to compare with CamIDs
0562       {
0563           imgdata.color.black = 0;
0564           imgdata.color.maximum = 4501;
0565           memset(imgdata.color.cblack, 0, sizeof(imgdata.color.cblack));
0566           memset(imgdata.sizes.mask, 0, sizeof(imgdata.sizes.mask));
0567           imgdata.sizes.mask[0][3] = 1; // to skip mask re-calc
0568           libraw_internal_data.unpacker_data.load_flags |= 512;
0569       }
0570 
0571       if (load_raw == &LibRaw::panasonic_load_raw)
0572       {
0573           if (libraw_internal_data.unpacker_data.pana_encoding == 6 ||
0574               libraw_internal_data.unpacker_data.pana_encoding == 7)
0575           {
0576               for (int i = 0; i < 3; i++)
0577                   imgdata.color.cblack[i] =
0578                   libraw_internal_data.internal_data.pana_black[i];
0579               imgdata.color.cblack[3] = imgdata.color.cblack[1];
0580               imgdata.color.cblack[4] = imgdata.color.cblack[5] = 0;
0581               imgdata.color.black = 0;
0582               imgdata.color.maximum =
0583                   MAX(imgdata.color.linear_max[0],
0584                       MAX(imgdata.color.linear_max[1], imgdata.color.linear_max[2]));
0585           }
0586 
0587           if (libraw_internal_data.unpacker_data.pana_encoding == 6)
0588           {
0589               int rowbytes11 = imgdata.sizes.raw_width / 11 * 16;
0590               int rowbytes14 = imgdata.sizes.raw_width / 14 * 16;
0591               INT64 ds = INT64(libraw_internal_data.unpacker_data.data_size);
0592               if (!ds)
0593                   ds = libraw_internal_data.internal_data.input->size() - libraw_internal_data.unpacker_data.data_offset;
0594               if ((imgdata.sizes.raw_width % 11) == 0 &&
0595                   (INT64(imgdata.sizes.raw_height) * rowbytes11 == ds))
0596                   load_raw = &LibRaw::panasonicC6_load_raw;
0597               else if ((imgdata.sizes.raw_width % 14) == 0 &&
0598                 (INT64(imgdata.sizes.raw_height) * rowbytes14 == ds))
0599                   load_raw = &LibRaw::panasonicC6_load_raw;
0600               else
0601                   imgdata.idata.raw_count = 0; // incorrect size
0602           }
0603           else if (libraw_internal_data.unpacker_data.pana_encoding == 7)
0604           {
0605               int pixperblock =
0606                   libraw_internal_data.unpacker_data.pana_bpp == 14 ? 9 : 10;
0607               int rowbytes = imgdata.sizes.raw_width / pixperblock * 16;
0608               if ((imgdata.sizes.raw_width % pixperblock) == 0 &&
0609                   (INT64(imgdata.sizes.raw_height) * rowbytes ==
0610                       INT64(libraw_internal_data.unpacker_data.data_size)))
0611                   load_raw = &LibRaw::panasonicC7_load_raw;
0612               else
0613                   imgdata.idata.raw_count = 0; // incorrect size
0614           }
0615       }
0616 
0617 #define NIKON_14BIT_SIZE(rw, rh)                                               \
0618   (((unsigned)(ceilf((float)(rw * 7 / 4) / 16.0)) * 16) * rh)
0619 
0620       // Ugly hack, replace with proper data/line size for different
0621       // cameras/format when available
0622       if (makeIs(LIBRAW_CAMERAMAKER_Nikon)
0623           && (!strncasecmp(imgdata.idata.model, "Z", 1) || !strcasecmp(imgdata.idata.model,"D6"))
0624           &&  NIKON_14BIT_SIZE(imgdata.sizes.raw_width, imgdata.sizes.raw_height) ==
0625           libraw_internal_data.unpacker_data.data_size)
0626       {
0627           load_raw = &LibRaw::nikon_14bit_load_raw;
0628       }
0629 #undef NIKON_14BIT_SIZE
0630 
0631       // Linear max from 14-bit camera, but on 12-bit data?
0632       if (makeIs(LIBRAW_CAMERAMAKER_Sony) &&
0633           imgdata.color.maximum > 0 &&
0634           imgdata.color.linear_max[0] > (long)imgdata.color.maximum &&
0635           imgdata.color.linear_max[0] <= (long)imgdata.color.maximum * 4)
0636           for (int c = 0; c < 4; c++)
0637               imgdata.color.linear_max[c] /= 4;
0638 
0639       if (makeIs(LIBRAW_CAMERAMAKER_Canon))
0640       {
0641           if (MN.canon.DefaultCropAbsolute.l != -1)  // tag 0x00e0 SensorInfo was parsed
0642           {
0643               if (imgdata.sizes.raw_aspect != LIBRAW_IMAGE_ASPECT_UNKNOWN)
0644               { // tag 0x009a AspectInfo was parsed
0645                   isRIC.cleft += MN.canon.DefaultCropAbsolute.l;
0646                   isRIC.ctop  += MN.canon.DefaultCropAbsolute.t;
0647               }
0648               else
0649               {
0650                   isRIC.cleft   = MN.canon.DefaultCropAbsolute.l;
0651                   isRIC.ctop    = MN.canon.DefaultCropAbsolute.t;
0652                   isRIC.cwidth  = MN.canon.DefaultCropAbsolute.r - MN.canon.DefaultCropAbsolute.l + 1;
0653                   isRIC.cheight = MN.canon.DefaultCropAbsolute.b - MN.canon.DefaultCropAbsolute.t + 1;
0654               }
0655           }
0656           else
0657           {
0658               if (imgdata.sizes.raw_aspect != LIBRAW_IMAGE_ASPECT_UNKNOWN)
0659               {
0660               }
0661               else
0662               { // Canon PowerShot S2 IS
0663               }
0664           }
0665 #undef isRIC
0666           if (imgdata.color.raw_bps < 14 && !imgdata.idata.dng_version && load_raw != &LibRaw::canon_sraw_load_raw)
0667           {
0668               int xmax = (1 << imgdata.color.raw_bps) - 1;
0669               if (MN.canon.SpecularWhiteLevel > xmax) // Adjust 14-bit metadata to real bps
0670               {
0671                 int div = 1 << (14 - imgdata.color.raw_bps);
0672                 for (int c = 0; c < 4; c++) imgdata.color.linear_max[c] /= div;
0673                 for (int c = 0; c < 4; c++)  MN.canon.ChannelBlackLevel[c] /= div;
0674                 MN.canon.AverageBlackLevel /= div;
0675                 MN.canon.SpecularWhiteLevel /= div;
0676                 MN.canon.NormalWhiteLevel /= div;
0677               }
0678           }
0679       }
0680 
0681       if (makeIs(LIBRAW_CAMERAMAKER_Canon) &&
0682           (load_raw == &LibRaw::canon_sraw_load_raw) &&
0683           imgdata.sizes.raw_width > 0)
0684       {
0685           float ratio =
0686               float(imgdata.sizes.raw_height) / float(imgdata.sizes.raw_width);
0687           if ((ratio < 0.57 || ratio > 0.75) &&
0688               MN.canon.SensorHeight > 1 &&
0689               MN.canon.SensorWidth > 1)
0690           {
0691               imgdata.sizes.raw_width = MN.canon.SensorWidth;
0692               imgdata.sizes.left_margin = MN.canon.DefaultCropAbsolute.l;
0693               imgdata.sizes.iwidth = imgdata.sizes.width =
0694                   MN.canon.DefaultCropAbsolute.r - MN.canon.DefaultCropAbsolute.l + 1;
0695               imgdata.sizes.raw_height = MN.canon.SensorHeight;
0696               imgdata.sizes.top_margin = MN.canon.DefaultCropAbsolute.t;
0697               imgdata.sizes.iheight = imgdata.sizes.height =
0698                   MN.canon.DefaultCropAbsolute.b - MN.canon.DefaultCropAbsolute.t + 1;
0699               libraw_internal_data.unpacker_data.load_flags |=
0700                   256; // reset width/height in canon_sraw_load_raw()
0701               imgdata.sizes.raw_pitch = 8 * imgdata.sizes.raw_width;
0702           }
0703           else if (imgdata.sizes.raw_width == 4032 &&
0704               imgdata.sizes.raw_height == 3402 &&
0705               !strcasecmp(imgdata.idata.model, "EOS 80D")) // 80D hardcoded
0706           {
0707               imgdata.sizes.raw_width = 4536;
0708               imgdata.sizes.left_margin = 28;
0709               imgdata.sizes.iwidth = imgdata.sizes.width =
0710                   imgdata.sizes.raw_width - imgdata.sizes.left_margin;
0711               imgdata.sizes.raw_height = 3024;
0712               imgdata.sizes.top_margin = 8;
0713               imgdata.sizes.iheight = imgdata.sizes.height =
0714                   imgdata.sizes.raw_height - imgdata.sizes.top_margin;
0715               libraw_internal_data.unpacker_data.load_flags |= 256;
0716               imgdata.sizes.raw_pitch = 8 * imgdata.sizes.raw_width;
0717           }
0718       }
0719 
0720 #ifdef USE_DNGSDK
0721       if (imgdata.idata.dng_version
0722           &&libraw_internal_data.unpacker_data.tiff_compress == 34892
0723           && libraw_internal_data.unpacker_data.tiff_bps == 8
0724           && libraw_internal_data.unpacker_data.tiff_samples == 3
0725           && load_raw == &LibRaw::lossy_dng_load_raw)
0726       {
0727           // Data should be linearized by DNG SDK
0728           C.black = 0;
0729           memset(C.cblack, 0, sizeof(C.cblack));
0730       }
0731 #endif
0732 
0733       // XTrans Compressed?
0734       if (!imgdata.idata.dng_version &&
0735           makeIs(LIBRAW_CAMERAMAKER_Fujifilm) &&
0736           (load_raw == &LibRaw::unpacked_load_raw))
0737       {
0738           if (imgdata.sizes.raw_width * (imgdata.sizes.raw_height * 2ul) !=
0739               libraw_internal_data.unpacker_data.data_size)
0740           {
0741               if ((imgdata.sizes.raw_width * (imgdata.sizes.raw_height * 7ul)) / 4 ==
0742                   libraw_internal_data.unpacker_data.data_size)
0743                   load_raw = &LibRaw::fuji_14bit_load_raw;
0744               else
0745                   parse_fuji_compressed_header();
0746           }
0747           else if (!strcmp(imgdata.idata.normalized_model, "X-H2S") 
0748               && libraw_internal_data.internal_data.input->size() 
0749               < (libraw_internal_data.unpacker_data.data_size + libraw_internal_data.unpacker_data.data_offset))
0750           {
0751             parse_fuji_compressed_header(); // try to use compressed header: X-H2S may record wrong data size
0752           }
0753       }
0754       // set raw_inset_crops[1] via raw_aspect
0755       if (imgdata.sizes.raw_aspect >= LIBRAW_IMAGE_ASPECT_MINIMAL_REAL_ASPECT_VALUE
0756           && imgdata.sizes.raw_aspect <= LIBRAW_IMAGE_ASPECT_MAXIMAL_REAL_ASPECT_VALUE
0757           /* crops[0] is valid*/
0758           && (imgdata.sizes.raw_inset_crops[0].cleft < 0xffff)
0759           && (imgdata.sizes.raw_inset_crops[0].cleft + imgdata.sizes.raw_inset_crops[0].cwidth <= imgdata.sizes.raw_width)
0760           && (imgdata.sizes.raw_inset_crops[0].ctop < 0xffff)
0761           && (imgdata.sizes.raw_inset_crops[0].ctop + imgdata.sizes.raw_inset_crops[0].cheight <= imgdata.sizes.raw_height)
0762           && imgdata.sizes.raw_inset_crops[0].cwidth > 0 && imgdata.sizes.raw_inset_crops[0].cheight >0
0763           /* crops[1] is not set*/
0764           && (imgdata.sizes.raw_inset_crops[1].cleft == 0xffff)
0765           && (imgdata.sizes.raw_inset_crops[1].ctop == 0xffff)
0766           )
0767       {
0768           float c0_ratio = float(imgdata.sizes.raw_inset_crops[0].cwidth) / float(imgdata.sizes.raw_inset_crops[0].cheight);
0769           float c1_ratio = float(imgdata.sizes.raw_aspect) / 1000.f;
0770           if (c0_ratio / c1_ratio < 0.98 || c0_ratio / c1_ratio > 1.02) // set crops[1]
0771           {
0772               if (c1_ratio > c0_ratio) // requested image is wider, cut from top/bottom
0773               {
0774                   int newheight =  int(imgdata.sizes.raw_inset_crops[0].cwidth / c1_ratio);
0775                   int dtop = (imgdata.sizes.raw_inset_crops[0].cheight - newheight) / 2;
0776                   imgdata.sizes.raw_inset_crops[1].ctop = imgdata.sizes.raw_inset_crops[0].ctop + dtop;
0777                   imgdata.sizes.raw_inset_crops[1].cheight = newheight;
0778                   imgdata.sizes.raw_inset_crops[1].cleft = imgdata.sizes.raw_inset_crops[0].cleft;
0779                   imgdata.sizes.raw_inset_crops[1].cwidth = imgdata.sizes.raw_inset_crops[0].cwidth;
0780               }
0781               else
0782               {
0783                   int newwidth = int(imgdata.sizes.raw_inset_crops[0].cheight * c1_ratio);
0784                   int dleft = (imgdata.sizes.raw_inset_crops[0].cwidth - newwidth) / 2;
0785                   imgdata.sizes.raw_inset_crops[1].cleft = imgdata.sizes.raw_inset_crops[0].cleft + dleft;
0786                   imgdata.sizes.raw_inset_crops[1].cwidth = newwidth;
0787                   imgdata.sizes.raw_inset_crops[1].ctop = imgdata.sizes.raw_inset_crops[0].ctop;
0788                   imgdata.sizes.raw_inset_crops[1].cheight = imgdata.sizes.raw_inset_crops[0].cheight;
0789               }
0790           }
0791       }
0792 
0793       int adjust_margins = 0;
0794       if (makeIs(LIBRAW_CAMERAMAKER_Fujifilm) && (imgdata.idata.filters == 9))
0795       {
0796           // Adjust top/left margins for X-Trans
0797           int newtm = imgdata.sizes.top_margin % 6
0798               ? (imgdata.sizes.top_margin / 6 + 1) * 6
0799               : imgdata.sizes.top_margin;
0800           int newlm = imgdata.sizes.left_margin % 6
0801               ? (imgdata.sizes.left_margin / 6 + 1) * 6
0802               : imgdata.sizes.left_margin;
0803           if (newtm != imgdata.sizes.top_margin ||
0804               newlm != imgdata.sizes.left_margin)
0805           {
0806               imgdata.sizes.height -= (newtm - imgdata.sizes.top_margin);
0807               imgdata.sizes.top_margin = newtm;
0808               imgdata.sizes.width -= (newlm - imgdata.sizes.left_margin);
0809               imgdata.sizes.left_margin = newlm;
0810               for (int c1 = 0; c1 < 6; c1++)
0811                   for (int c2 = 0; c2 < 6; c2++)
0812                       imgdata.idata.xtrans[c1][c2] = imgdata.idata.xtrans_abs[c1][c2];
0813           }
0814           adjust_margins = 6;
0815       }
0816       else if (!libraw_internal_data.internal_output_params.fuji_width
0817           && imgdata.idata.filters >= 1000)
0818       {
0819           if ((imgdata.sizes.top_margin % 2) || (imgdata.sizes.left_margin % 2))
0820           {
0821               int crop[2] = { 0,0 };
0822               unsigned filt;
0823               int c;
0824               if (imgdata.sizes.top_margin % 2)
0825               {
0826                   imgdata.sizes.top_margin += 1;
0827                   imgdata.sizes.height -= 1;
0828                   crop[1] = 1;
0829               }
0830               if (imgdata.sizes.left_margin % 2)
0831               {
0832                   imgdata.sizes.left_margin += 1;
0833                   imgdata.sizes.width -= 1;
0834                   crop[0] = 1;
0835               }
0836               for (filt = c = 0; c < 16; c++)
0837                   filt |= FC((c >> 1) + (crop[1]), (c & 1) + (crop[0])) << c * 2;
0838               imgdata.idata.filters = filt;
0839           }
0840           adjust_margins = 2;
0841       }
0842 
0843       if(adjust_margins) // adjust crop_inset margins
0844           for (int i = 0; i < 2; i++)
0845           {
0846               if (imgdata.sizes.raw_inset_crops[i].cleft && imgdata.sizes.raw_inset_crops[i].cleft < 0xffff
0847                   && imgdata.sizes.raw_inset_crops[i].cwidth && imgdata.sizes.raw_inset_crops[i].cwidth < 0xffff
0848                   && (imgdata.sizes.raw_inset_crops[i].cleft%adjust_margins)
0849                   && (imgdata.sizes.raw_inset_crops[i].cwidth > adjust_margins))
0850               {
0851                   int newleft = ((imgdata.sizes.raw_inset_crops[i].cleft / adjust_margins) + 1) * adjust_margins;
0852                   int diff = newleft - imgdata.sizes.raw_inset_crops[i].cleft;
0853                   if (diff > 0)
0854                   {
0855                       imgdata.sizes.raw_inset_crops[i].cleft += diff;
0856                       imgdata.sizes.raw_inset_crops[i].cwidth -= diff;
0857                   }
0858               }
0859               if (imgdata.sizes.raw_inset_crops[i].ctop && imgdata.sizes.raw_inset_crops[i].ctop < 0xffff
0860                   && imgdata.sizes.raw_inset_crops[i].cheight && imgdata.sizes.raw_inset_crops[i].cheight < 0xffff
0861                   && (imgdata.sizes.raw_inset_crops[i].ctop%adjust_margins)
0862                   && (imgdata.sizes.raw_inset_crops[i].cheight > adjust_margins))
0863               {
0864                   int newtop = ((imgdata.sizes.raw_inset_crops[i].ctop / adjust_margins) + 1) * adjust_margins;
0865                   int diff = newtop - imgdata.sizes.raw_inset_crops[i].ctop;
0866                   if (diff > 0)
0867                   {
0868                       imgdata.sizes.raw_inset_crops[i].ctop += diff;
0869                       imgdata.sizes.raw_inset_crops[i].cheight -= diff;
0870                   }
0871               }
0872           }
0873 
0874 
0875 #ifdef USE_DNGSDK
0876       if (
0877           imgdata.rawparams.use_dngsdk &&
0878           !(imgdata.rawparams.options & (LIBRAW_RAWOPTIONS_DNG_STAGE2 | LIBRAW_RAWOPTIONS_DNG_STAGE3 | LIBRAW_RAWOPTIONS_DNG_DISABLEWBADJUST)))
0879 #endif
0880       {
0881           // Fix DNG white balance if needed: observed only for Kalpanika X3F tools produced DNGs
0882           if (imgdata.idata.dng_version && (imgdata.idata.filters == 0) &&
0883               imgdata.idata.colors > 1 && imgdata.idata.colors < 5)
0884           {
0885               float delta[4] = { 0.f, 0.f, 0.f, 0.f };
0886               int black[4];
0887               for (int c = 0; c < 4; c++)
0888                   black[c] = imgdata.color.dng_levels.dng_black +
0889                   imgdata.color.dng_levels.dng_cblack[c];
0890               for (int c = 0; c < imgdata.idata.colors; c++)
0891                   delta[c] = imgdata.color.dng_levels.dng_whitelevel[c] - black[c];
0892               float mindelta = delta[0], maxdelta = delta[0];
0893               for (int c = 1; c < imgdata.idata.colors; c++)
0894               {
0895                   if (mindelta > delta[c])
0896                       mindelta = delta[c];
0897                   if (maxdelta < delta[c])
0898                       maxdelta = delta[c];
0899               }
0900               if (mindelta > 1 && maxdelta < (mindelta * 20)) // safety
0901               {
0902                   for (int c = 0; c < imgdata.idata.colors; c++)
0903                   {
0904                       imgdata.color.cam_mul[c] /= (delta[c] / maxdelta);
0905                       imgdata.color.pre_mul[c] /= (delta[c] / maxdelta);
0906                   }
0907                   imgdata.color.maximum = imgdata.color.cblack[0] + maxdelta;
0908               }
0909           }
0910       }
0911 
0912     if (imgdata.idata.dng_version &&
0913         makeIs(LIBRAW_CAMERAMAKER_Panasonic)
0914           && !strcasecmp(imgdata.idata.normalized_model, "DMC-LX100"))
0915       imgdata.sizes.width = 4288;
0916 
0917     if (imgdata.idata.dng_version
0918         && makeIs(LIBRAW_CAMERAMAKER_Leica)
0919         && !strcasecmp(imgdata.idata.normalized_model, "SL2"))
0920             imgdata.sizes.height -= 16;
0921 
0922     if (makeIs(LIBRAW_CAMERAMAKER_Sony) &&
0923         imgdata.idata.dng_version)
0924     {
0925       if (S.raw_width == 3984)
0926         S.width = 3925;
0927       else if (S.raw_width == 4288)
0928         S.width = S.raw_width - 32;
0929       else if (S.raw_width == 4928 && S.height < 3280)
0930         S.width = S.raw_width - 8;
0931       else if (S.raw_width == 5504)
0932         S.width = S.raw_width - (S.height > 3664 ? 8 : 32);
0933     }
0934 
0935     if (makeIs(LIBRAW_CAMERAMAKER_Sony) &&
0936         !imgdata.idata.dng_version)
0937     {
0938         if(load_raw ==&LibRaw::sony_arq_load_raw)
0939         {
0940             if(S.raw_width > 12000) // A7RM4 16x, both APS-C and APS
0941                 S.width = S.raw_width - 64;
0942             else // A7RM3/M4 4x merge
0943                 S.width = S.raw_width - 32;
0944         }
0945 
0946       if (((!strncasecmp(imgdata.idata.model, "ILCE-7RM", 8) ||
0947             !strcasecmp(imgdata.idata.model, "ILCA-99M2")) &&
0948            (S.raw_width == 5216 || S.raw_width == 6304)) // A7RM2/M3/A99M2 in APS mode; A7RM4 in APS-C
0949           ||
0950           (!strcasecmp(imgdata.idata.model, "ILCE-7R") && S.raw_width >= 4580 &&
0951            S.raw_width < 5020) // A7R in crop mode, no samples, so size est.
0952           || (!strcasecmp(imgdata.idata.model, "ILCE-7") &&
0953               S.raw_width == 3968) // A7 in crop mode
0954           ||
0955           ((!strncasecmp(imgdata.idata.model, "ILCE-7M", 7) ||
0956             !strcasecmp(imgdata.idata.model, "ILCE-9") ||
0957 #if 0
0958             !strcasecmp(imgdata.idata.model,
0959                         "SLT-A99V")) // Does SLT-A99 also have APS-C mode??
0960 #endif
0961            (mnCamID == SonyID_SLT_A99)) // 2 reasons: some cameras are SLT-A99, no 'V'; some are Hasselblad HV
0962            && S.raw_width > 3750 &&
0963            S.raw_width < 4120) // A7M2, A7M3, AA9, most likely APS-C raw_width
0964                                // is 3968 (same w/ A7), but no samples, so guess
0965           || (!strncasecmp(imgdata.idata.model, "ILCE-7S", 7) &&
0966               S.raw_width == 2816) // A7S2=> exact, hope it works for A7S-I too
0967       )
0968         S.width = S.raw_width - 32;
0969     }
0970 
0971 
0972     // FIXME: it is possible that DNG contains 4x main frames + some previews; in this case imgdata.idata.raw_count will be greater than 4
0973     if (makeIs(LIBRAW_CAMERAMAKER_Pentax) &&
0974         /*!strcasecmp(imgdata.idata.model,"K-3 II")  &&*/
0975             imgdata.idata.raw_count == 4 &&
0976         (imgdata.rawparams.options & LIBRAW_RAWOPTIONS_PENTAX_PS_ALLFRAMES))
0977     {
0978       imgdata.idata.raw_count = 1;
0979       imgdata.idata.filters = 0;
0980       imgdata.idata.colors = 4;
0981       imgdata.sizes.top_margin+=2;
0982       imgdata.sizes.left_margin+=2;
0983       imgdata.sizes.width-=4;
0984       imgdata.sizes.height-=4;
0985       IO.mix_green = 1;
0986       pentax_component_load_raw = load_raw;
0987       load_raw = &LibRaw::pentax_4shot_load_raw;
0988     }
0989 
0990     if (!imgdata.idata.dng_version && makeIs(LIBRAW_CAMERAMAKER_Leaf) &&
0991         !strcmp(imgdata.idata.model, "Credo 50"))
0992     {
0993       imgdata.color.pre_mul[0] = 1.f / 0.3984f;
0994       imgdata.color.pre_mul[2] = 1.f / 0.7666f;
0995       imgdata.color.pre_mul[1] = imgdata.color.pre_mul[3] = 1.0;
0996     }
0997 
0998     if (!imgdata.idata.dng_version && makeIs(LIBRAW_CAMERAMAKER_Fujifilm) &&
0999         (!strncmp(imgdata.idata.model, "S20Pro", 6) ||
1000          !strncmp(imgdata.idata.model, "F700", 4)))
1001     {
1002       imgdata.sizes.raw_width /= 2;
1003       load_raw = &LibRaw::unpacked_load_raw_fuji_f700s20;
1004     }
1005 
1006     if (load_raw == &LibRaw::packed_load_raw &&
1007         makeIs(LIBRAW_CAMERAMAKER_Nikon) &&
1008         !libraw_internal_data.unpacker_data.load_flags &&
1009         (!strncasecmp(imgdata.idata.model, "D810", 4) ||
1010          !strcasecmp(imgdata.idata.model, "D4S")) &&
1011         libraw_internal_data.unpacker_data.data_size * 2u ==
1012             imgdata.sizes.raw_height * imgdata.sizes.raw_width * 3u)
1013     {
1014       libraw_internal_data.unpacker_data.load_flags = 80;
1015     }
1016     // Adjust BL for Sony A900/A850
1017     if (load_raw == &LibRaw::packed_load_raw &&
1018         makeIs(LIBRAW_CAMERAMAKER_Sony)) // 12 bit sony, but metadata may be for 14-bit range
1019     {
1020       if (C.maximum > 4095)
1021         C.maximum = 4095;
1022       if (C.black > 256 || C.cblack[0] > 256)
1023       {
1024         C.black /= 4;
1025         for (int c = 0; c < 4; c++)
1026           C.cblack[c] /= 4;
1027         for (unsigned c = 0; c < C.cblack[4] * C.cblack[5]; c++)
1028           C.cblack[6 + c] /= 4;
1029       }
1030     }
1031 
1032     if (load_raw == &LibRaw::nikon_yuv_load_raw) // Is it Nikon sRAW?
1033     {
1034       load_raw = &LibRaw::nikon_load_sraw;
1035       C.black = 0;
1036       memset(C.cblack, 0, sizeof(C.cblack));
1037       imgdata.idata.filters = 0;
1038       libraw_internal_data.unpacker_data.tiff_samples = 3;
1039       imgdata.idata.colors = 3;
1040       double beta_1 = -5.79342238397656E-02;
1041       double beta_2 = 3.28163551282665;
1042       double beta_3 = -8.43136004842678;
1043       double beta_4 = 1.03533181861023E+01;
1044       for (int i = 0; i <= 3072; i++)
1045       {
1046         double x = (double)i / 3072.;
1047         double y = (1. - exp(-beta_1 * x - beta_2 * x * x - beta_3 * x * x * x -
1048                              beta_4 * x * x * x * x));
1049         if (y < 0.)
1050           y = 0.;
1051         imgdata.color.curve[i] = (y * 16383.);
1052       }
1053       for (int i = 0; i < 3; i++)
1054         for (int j = 0; j < 4; j++)
1055           imgdata.color.rgb_cam[i][j] = float(i == j);
1056     }
1057     // Adjust BL for Nikon 12bit
1058     if ((load_raw == &LibRaw::nikon_load_raw ||
1059          load_raw == &LibRaw::packed_load_raw ||
1060          load_raw == &LibRaw::nikon_load_padded_packed_raw) &&
1061          makeIs(LIBRAW_CAMERAMAKER_Nikon) &&
1062         strncmp(imgdata.idata.model, "COOLPIX", 7) &&
1063         libraw_internal_data.unpacker_data.tiff_bps == 12)
1064     {
1065       C.maximum = 4095;
1066       C.black /= 4;
1067       for (int c = 0; c < 4; c++)
1068         C.cblack[c] /= 4;
1069       for (unsigned c = 0; c < C.cblack[4] * C.cblack[5]; c++)
1070         C.cblack[6 + c] /= 4;
1071     }
1072 
1073     // Adjust wb_already_applied
1074     if (load_raw == &LibRaw::nikon_load_sraw)
1075       imgdata.color.as_shot_wb_applied =
1076           LIBRAW_ASWB_APPLIED | LIBRAW_ASWB_NIKON_SRAW;
1077     else if (makeIs(LIBRAW_CAMERAMAKER_Canon) &&
1078              MN.canon.multishot[0] >= 8 &&
1079              MN.canon.multishot[1] > 0)
1080       imgdata.color.as_shot_wb_applied =
1081           LIBRAW_ASWB_APPLIED | LIBRAW_ASWB_CANON;
1082     else if (makeIs(LIBRAW_CAMERAMAKER_Nikon) &&
1083              MN.nikon.ExposureMode == 1)
1084       imgdata.color.as_shot_wb_applied =
1085           LIBRAW_ASWB_APPLIED | LIBRAW_ASWB_NIKON;
1086     else if (makeIs(LIBRAW_CAMERAMAKER_Pentax) &&
1087              ((MN.pentax.MultiExposure & 0x01) == 1))
1088       imgdata.color.as_shot_wb_applied =
1089           LIBRAW_ASWB_APPLIED | LIBRAW_ASWB_PENTAX;
1090     else
1091       imgdata.color.as_shot_wb_applied = 0;
1092 
1093     // Adjust Highlight Linearity limit
1094     if (C.linear_max[0] < 0)
1095     {
1096       if (imgdata.idata.dng_version)
1097       {
1098         for (int c = 0; c < 4; c++)
1099           C.linear_max[c] = -1 * C.linear_max[c] + imgdata.color.cblack[c + 6];
1100       }
1101       else
1102       {
1103         for (int c = 0; c < 4; c++)
1104           C.linear_max[c] = -1 * C.linear_max[c] + imgdata.color.cblack[c];
1105       }
1106     }
1107 
1108     if (makeIs(LIBRAW_CAMERAMAKER_Nikon) &&
1109         (!C.linear_max[0]) && (C.maximum > 1024) && (load_raw != &LibRaw::nikon_load_sraw))
1110     {
1111       C.linear_max[0] = C.linear_max[1] = C.linear_max[2] = C.linear_max[3] =
1112           (long)((float)(C.maximum) / 1.07f);
1113     }
1114 
1115     // Correct WB for Samsung GX20
1116     if (
1117 #if 0
1118         /* GX20 should be corrected, but K20 is not */
1119         makeIs(LIBRAW_CAMERAMAKER_Pentax) &&
1120         !strcasecmp(imgdata.idata.normalized_model, "K20D")
1121 #endif
1122 #if 0
1123         !strcasecmp(imgdata.idata.make, "Samsung") &&
1124         !strcasecmp(imgdata.idata.model, "GX20")
1125 #endif
1126     makeIs(LIBRAW_CAMERAMAKER_Pentax) &&
1127     (mnCamID == PentaxID_GX20) // Samsung rebranding
1128         )
1129     {
1130       for (int cnt = LIBRAW_WBI_Unknown; cnt <= LIBRAW_WBI_StudioTungsten; cnt++) {
1131         if (C.WB_Coeffs[cnt][1]) {
1132           C.WB_Coeffs[cnt][0] = (int)((float)(C.WB_Coeffs[cnt][0]) * 1.0503f);
1133           C.WB_Coeffs[cnt][2] = (int)((float)(C.WB_Coeffs[cnt][2]) * 2.2867f);
1134         }
1135       }
1136       for (int cnt = 0; cnt < 64; cnt++) {
1137         if (C.WBCT_Coeffs[cnt][0] > 0.0f) {
1138           C.WBCT_Coeffs[cnt][1] *= 1.0503f;
1139           C.WBCT_Coeffs[cnt][3] *= 2.2867f;
1140         }
1141       }
1142       for(int cnt = 0; cnt < 4; cnt++)
1143         imgdata.color.pre_mul[cnt] =
1144           C.WB_Coeffs[LIBRAW_WBI_Daylight][cnt];
1145     }
1146 
1147     // Adjust BL for Panasonic
1148     if (load_raw == &LibRaw::panasonic_load_raw &&
1149         makeIs(LIBRAW_CAMERAMAKER_Panasonic) &&
1150         ID.pana_black[0] && ID.pana_black[1] && ID.pana_black[2])
1151     {
1152       if (libraw_internal_data.unpacker_data.pana_encoding == 5)
1153         libraw_internal_data.internal_output_params.zero_is_bad = 0;
1154       C.black = 0;
1155       int add = libraw_internal_data.unpacker_data.pana_encoding == 4 ? 15 : 0;
1156       C.cblack[0] = ID.pana_black[0] + add;
1157       C.cblack[1] = C.cblack[3] = ID.pana_black[1] + add;
1158       C.cblack[2] = ID.pana_black[2] + add;
1159       unsigned i = C.cblack[3];
1160       for (int c = 0; c < 3; c++)
1161         if (i > C.cblack[c])
1162           i = C.cblack[c];
1163       for (int c = 0; c < 4; c++)
1164         C.cblack[c] -= i;
1165       C.black = i;
1166     }
1167 
1168     // Adjust sizes for X3F processing
1169 #ifdef USE_X3FTOOLS
1170     if (load_raw == &LibRaw::x3f_load_raw)
1171     {
1172       for (int i = 0; i < foveon_count; i++)
1173         if (!strcasecmp(imgdata.idata.make, foveon_data[i].make) &&
1174             !strcasecmp(imgdata.idata.model, foveon_data[i].model) &&
1175             imgdata.sizes.raw_width == foveon_data[i].raw_width &&
1176             imgdata.sizes.raw_height == foveon_data[i].raw_height)
1177         {
1178           imgdata.sizes.top_margin = foveon_data[i].top_margin;
1179           imgdata.sizes.left_margin = foveon_data[i].left_margin;
1180           imgdata.sizes.width = imgdata.sizes.iwidth = foveon_data[i].width;
1181           imgdata.sizes.height = imgdata.sizes.iheight = foveon_data[i].height;
1182           C.maximum = foveon_data[i].white;
1183           break;
1184         }
1185     }
1186 #endif
1187 #if 0
1188     size_t bytes = ID.input->size()-libraw_internal_data.unpacker_data.data_offset;
1189     float bpp = float(bytes)/float(S.raw_width)/float(S.raw_height);
1190     float bpp2 = float(bytes)/float(S.width)/float(S.height);
1191     if(!strcasecmp(imgdata.idata.make,"Hasselblad") && bpp == 6.0f)
1192       {
1193         load_raw = &LibRaw::hasselblad_full_load_raw;
1194         S.width = S.raw_width;
1195         S.height = S.raw_height;
1196         P1.filters = 0;
1197         P1.colors=3;
1198         P1.raw_count=1;
1199         C.maximum=0xffff;
1200       }
1201 #endif
1202     if (C.profile_length)
1203     {
1204       if (C.profile)
1205         free(C.profile);
1206       INT64 profile_sz = MIN(INT64(C.profile_length), ID.input->size() - ID.profile_offset);
1207       if (profile_sz > 0LL && profile_sz < LIBRAW_MAX_PROFILE_SIZE_MB * 1024LL * 1024LL)
1208       {
1209         C.profile = malloc(size_t(profile_sz));
1210         ID.input->seek(ID.profile_offset, SEEK_SET);
1211         ID.input->read(C.profile, size_t(profile_sz), 1);
1212       }
1213       else
1214           C.profile = NULL;
1215     }
1216 
1217     SET_PROC_FLAG(LIBRAW_PROGRESS_IDENTIFY);
1218   }
1219   catch (const std::bad_alloc&)
1220   {
1221       EXCEPTION_HANDLER(LIBRAW_EXCEPTION_ALLOC);
1222   }
1223   catch (const LibRaw_exceptions& err)
1224   {
1225     EXCEPTION_HANDLER(err);
1226   }
1227   catch (const std::exception& )
1228   {
1229     EXCEPTION_HANDLER(LIBRAW_EXCEPTION_IO_CORRUPT);
1230   }
1231 
1232 final:;
1233 
1234   if (P1.raw_count < 1)
1235     return LIBRAW_FILE_UNSUPPORTED;
1236 
1237   write_fun = &LibRaw::write_ppm_tiff;
1238 
1239   if (load_raw == &LibRaw::kodak_ycbcr_load_raw)
1240   {
1241     S.height += S.height & 1;
1242     S.width += S.width & 1;
1243   }
1244 
1245   IO.shrink =
1246       P1.filters &&
1247       (O.half_size || ((O.threshold || O.aber[0] != 1 || O.aber[2] != 1)));
1248   if (IO.shrink && P1.filters >= 1000)
1249   {
1250     S.width &= 65534;
1251     S.height &= 65534;
1252   }
1253 
1254   S.iheight = (S.height + IO.shrink) >> IO.shrink;
1255   S.iwidth = (S.width + IO.shrink) >> IO.shrink;
1256 
1257   // Save color,sizes and internal data into raw_image fields
1258   memmove(&imgdata.rawdata.color, &imgdata.color, sizeof(imgdata.color));
1259   memmove(&imgdata.rawdata.sizes, &imgdata.sizes, sizeof(imgdata.sizes));
1260   memmove(&imgdata.rawdata.iparams, &imgdata.idata, sizeof(imgdata.idata));
1261   memmove(&imgdata.rawdata.ioparams,
1262           &libraw_internal_data.internal_output_params,
1263           sizeof(libraw_internal_data.internal_output_params));
1264 
1265   SET_PROC_FLAG(LIBRAW_PROGRESS_SIZE_ADJUST);
1266 
1267   return LIBRAW_SUCCESS;
1268 }