58 [[maybe_unused]]
Buffer file) {
59 const auto id = rootIFD->
getID();
60 const std::string& make =
id.
make;
61 const std::string& model =
id.model;
65 return make ==
"Canon" ||
66 (make ==
"Kodak" && (model ==
"DCS520C" || model ==
"DCS560C"));
90 if (width > 2 * height) {
96 mRaw->dim = {width, height};
112 auto table = curve->getU16Array(curve->count);
117 mRaw->sixteenBitLookup();
129 ThrowTPE(
"failed to get SensorInfo from MakerNote");
131 assert(sensorInfoE !=
nullptr);
134 ThrowTPE(
"Subsampling sanity check failed");
143 if (subSampling.
x <= 1 && subSampling.
y <= 1)
144 ThrowRDE(
"RAW is expected to be subsampled, but it's not");
146 if (
mRaw->dim.x % subSampling.
x != 0)
147 ThrowRDE(
"Raw width is not a multiple of horizontal subsampling factor");
148 mRaw->dim.x /= subSampling.
x;
150 if (
mRaw->dim.y % subSampling.
y != 0)
151 ThrowRDE(
"Raw height is not a multiple of vertical subsampling factor");
152 mRaw->dim.y /= subSampling.
y;
154 mRaw->dim.x *= 2 + subSampling.
x * subSampling.
y;
172 if (cr2SliceEntry->count != 3) {
173 ThrowRDE(
"Found RawImageSegmentation tag with %u elements, should be 3.",
174 cr2SliceEntry->count);
177 if (cr2SliceEntry->getU16(1) != 0 && cr2SliceEntry->getU16(2) != 0) {
180 cr2SliceEntry->getU16(1),
181 cr2SliceEntry->getU16(2));
182 }
else if (cr2SliceEntry->getU16(0) == 0 && cr2SliceEntry->getU16(1) == 0 &&
183 cr2SliceEntry->getU16(2) != 0) {
186 ThrowRDE(
"Strange RawImageSegmentation tag: (%d, %d, %d), image corrupt.",
187 cr2SliceEntry->getU16(0), cr2SliceEntry->getU16(1),
188 cr2SliceEntry->getU16(2));
205 if (
mRaw->metadata.subsampling.x > 1 ||
mRaw->metadata.subsampling.y > 1)
212 if (
mRootIFD->getSubIFDs().size() < 4)
245 if (ccd->
count == 582)
248 if (ccd->
count == 653)
251 switch (
int colorDataVersion =
static_cast<int16_t>(ccd->
getU16(0));
276 return {{f, colorDataVersion}};
307 __builtin_unreachable();
321 switch (*colorDataVersion) {
334 __builtin_unreachable();
337 switch (*colorDataVersion) {
339 return {{333, 1386}};
343 __builtin_unreachable();
346 switch (*colorDataVersion) {
350 __builtin_unreachable();
353 switch (*colorDataVersion) {
359 __builtin_unreachable();
362 switch (*colorDataVersion) {
370 __builtin_unreachable();
373 __builtin_unreachable();
388 auto dsc = deduceColorDataFormat(wb);
392 auto [f, ver] = *dsc;
394 int offset = getWhiteBalanceOffsetInColorData(f);
398 std::array<float, 4> wbCoeffs = {};
399 wbCoeffs[0] =
static_cast<float>(wb->
getU16(offset + 0));
400 wbCoeffs[1] =
static_cast<float>(wb->
getU16(offset + 1));
401 wbCoeffs[2] =
static_cast<float>(wb->
getU16(offset + 3));
402 mRaw->metadata.wbCoeffs = wbCoeffs;
404 auto levelOffsets = getBlackAndWhiteLevelOffsetsInColorData(f, ver);
408 mRaw->whitePoint = wb->
getU16(levelOffsets->second);
410 mRaw->blackLevelSeparate =
412 auto blackLevelSeparate1D = *
mRaw->blackLevelSeparate->getAsArray1DRef();
413 for (
int c = 0; c != 4; ++c)
414 blackLevelSeparate1D(c) = wb->
getU16(c + levelOffsets->first);
418 constexpr int makernotesPrecision = 14;
421 assert(bitDepthDiff >= 1 && bitDepthDiff <= 12);
422 if (shouldRescaleBlackLevels(f, ver)) {
423 for (
int c = 0; c != 4; ++c)
424 blackLevelSeparate1D(c) >>= bitDepthDiff;
426 mRaw->whitePoint = *
mRaw->whitePoint >> bitDepthDiff;
447 int wb_offset = (wb_index < 18)
448 ? std::string_view(
"012347800000005896")[wb_index] -
'0'
450 wb_offset = wb_offset * 8 + 2;
452 std::array<float, 4> wbCoeffs = {};
453 wbCoeffs[0] =
static_cast<float>(g9_wb->
getU32(wb_offset + 1));
454 wbCoeffs[1] = (
static_cast<float>(g9_wb->
getU32(wb_offset + 0)) +
455 static_cast<float>(g9_wb->
getU32(wb_offset + 3))) /
457 wbCoeffs[2] =
static_cast<float>(g9_wb->
getU32(wb_offset + 2));
458 mRaw->metadata.wbCoeffs = wbCoeffs;
463 if (wb->
count >= 3) {
464 std::array<float, 4> wbCoeffs = {};
468 mRaw->metadata.wbCoeffs = wbCoeffs;
480 if (
mRaw->metadata.subsampling.y == 2 &&
mRaw->metadata.subsampling.x == 2)
483 if (
mRaw->metadata.subsampling.y == 1 &&
mRaw->metadata.subsampling.x == 2)
500 mRaw->setError(e.what());
506 mRaw->blackLevel = 0;
507 mRaw->blackLevelSeparate = std::nullopt;
516 if (
mRootIFD->getSubIFDs().size() != 4)
520 return typeE && typeE->
getU32() == 4;
527 ThrowRDE(
"CanonCameraSettings entry not found.");
530 ThrowRDE(
"Unexpected CanonCameraSettings entry type encountered ");
543 ThrowRDE(
"Unexpected SRAWQuality value found: %u", qual);
548 if (
hints.contains(
"old_sraw_hue"))
549 return (
mRaw->metadata.subsampling.y *
mRaw->metadata.subsampling.x);
556 model_id >= 0x80000281 || model_id == 0x80000218 ||
557 (
hints.contains(
"force_new_sraw_hue"))) {
558 return ((
mRaw->metadata.subsampling.y *
mRaw->metadata.subsampling.x) -
563 return (
mRaw->metadata.subsampling.y *
mRaw->metadata.subsampling.x);
570 ThrowRDE(
"Unable to locate WB info.");
575 std::array<int, 3> sraw_coeffs;
578 sraw_coeffs[0] = wb->
getU16(offset + 0);
579 sraw_coeffs[1] = (wb->
getU16(offset + 1) + wb->
getU16(offset + 2) + 1) >> 1;
580 sraw_coeffs[2] = wb->
getU16(offset + 3);
582 if (
hints.contains(
"invert_sraw_wb")) {
583 sraw_coeffs[0] =
static_cast<int>(
584 1024.0F / (
static_cast<float>(sraw_coeffs[0]) / 1024.0F));
585 sraw_coeffs[2] =
static_cast<int>(
586 1024.0F / (
static_cast<float>(sraw_coeffs[2]) / 1024.0F));
595 (subsampledRaw->
dim.
x /
608 bool isOldSraw =
hints.contains(
"sraw_40d");
609 bool isNewSraw =
hints.contains(
"sraw_new");
assert(dim.area() >=area)
int getSamplePrecision() const
bool checkCameraSupported(const CameraMetaData *meta, const TiffID &id, const std::string &mode)
void setMetaData(const CameraMetaData *meta, const TiffID &id, const std::string &mode, int iso_speed)
TiffRootIFDOwner mRootIFD
void skipBytes(size_type nbytes)
bool isSubSampled() const
RawImage decodeRawInternal() override
void checkSupportInternal(const CameraMetaData *meta) override
void parseWhiteBalance() const
RawImage decodeOldFormat()
static bool isAppropriateDecoder(const TiffRootIFD *rootIFD, Buffer file)
RawImage decodeNewFormat()
bool decodeCanonColorData() const
void decodeMetaDataInternal(const CameraMetaData *meta) override
iPoint2D getSubSampling() const
void decode(const Cr2SliceWidths &slicing)
void interpolate(int version)
bool uncorrectedRawValues
Array2DRef< uint16_t > getU16DataAsUncroppedArray2DRef() noexcept
static RawImage create(RawImageType type=RawImageType::UINT16)
float getFloat(uint32_t index=0) const
uint32_t getU32(uint32_t index=0) const
uint16_t getU16(uint32_t index=0) const
TiffEntry *RAWSPEED_READONLY getEntryRecursive(TiffTag tag) const
TiffEntry * getEntry(TiffTag tag) const
Optional< std::pair< int, int > > getBlackAndWhiteLevelOffsetsInColorData(ColorDataFormat f, Optional< int > colorDataVersion)
bool shouldRescaleBlackLevels(ColorDataFormat f, Optional< int > colorDataVersion)
int getWhiteBalanceOffsetInColorData(ColorDataFormat f)
Optional< std::pair< ColorDataFormat, Optional< int > > > deduceColorDataFormat(const TiffEntry *ccd)
constexpr RAWSPEED_READNONE Ttgt implicit_cast(Tsrc value)
constexpr bool RAWSPEED_READNONE isPowerOfTwo(T val)
Array2DRef(Array1DRef< T > data, int width, int height, int pitch) -> Array2DRef< T >
@ RECOMMENDEDEXPOSUREINDEX
static void CheckMemIsInitialized(const void *addr, size_t size)