From d4e87cebaffaf6256ac7af6d901eeab306e23829 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Milo=C5=A1=20Komar=C4=8Devi=C4=87?= Date: Fri, 1 Mar 2024 15:04:29 +0100 Subject: [PATCH] RafDecoder: support vendor crop from metadata --- src/librawspeed/decoders/RafDecoder.cpp | 36 ++++++++++++++++++++----- src/librawspeed/decoders/RafDecoder.h | 1 + src/librawspeed/parsers/FiffParser.cpp | 4 ++- src/librawspeed/tiff/TiffTag.h | 5 ++++ 4 files changed, 39 insertions(+), 7 deletions(-) diff --git a/src/librawspeed/decoders/RafDecoder.cpp b/src/librawspeed/decoders/RafDecoder.cpp index 772d2f13f..3659d0648 100644 --- a/src/librawspeed/decoders/RafDecoder.cpp +++ b/src/librawspeed/decoders/RafDecoder.cpp @@ -75,8 +75,8 @@ RawImage RafDecoder::decodeRawInternal() { if (raw->hasEntry(TiffTag::FUJI_RAWIMAGEFULLHEIGHT)) { height = raw->getEntry(TiffTag::FUJI_RAWIMAGEFULLHEIGHT)->getU32(); width = raw->getEntry(TiffTag::FUJI_RAWIMAGEFULLWIDTH)->getU32(); - } else if (raw->hasEntry(TiffTag::IMAGEWIDTH)) { - const TiffEntry* e = raw->getEntry(TiffTag::IMAGEWIDTH); + } else if (raw->hasEntry(TiffTag::FUJI_RAWIMAGEFULLSIZE)) { + const TiffEntry* e = raw->getEntry(TiffTag::FUJI_RAWIMAGEFULLSIZE); height = e->getU16(0); width = e->getU16(1); } else @@ -206,17 +206,23 @@ void RafDecoder::applyCorrections(const Camera* cam) { iPoint2D crop_offset(0, 0); if (applyCrop) { - new_size = cam->cropSize; - crop_offset = cam->cropPos; + if (cam->cropAvailable) { + new_size = cam->cropSize; + crop_offset = cam->cropPos; + } else { + const iRectangle2D vendor_crop = getDefaultCrop(); + new_size = vendor_crop.dim; + crop_offset = vendor_crop.pos; + } bool double_width = hints.contains("double_width_unpacked"); // If crop size is negative, use relative cropping if (new_size.x <= 0) { new_size.x = - mRaw->dim.x / (double_width ? 2 : 1) - cam->cropPos.x + new_size.x; + mRaw->dim.x / (double_width ? 2 : 1) - crop_offset.x + new_size.x; } else new_size.x /= (double_width ? 2 : 1); if (new_size.y <= 0) - new_size.y = mRaw->dim.y - cam->cropPos.y + new_size.y; + new_size.y = mRaw->dim.y - crop_offset.y + new_size.y; } bool rotate = hints.contains("fuji_rotate"); @@ -396,4 +402,22 @@ int RafDecoder::isCompressed() const { return count * 8 / (width * height) < bps; } +iRectangle2D RafDecoder::getDefaultCrop() { + if (const TiffIFD* raf = mRootIFD->getIFDWithTag(TiffTag::FUJI_RAFDATA); + raf->hasEntry(TiffTag::FUJI_RAWIMAGECROPTOPLEFT) && + raf->hasEntry(TiffTag::FUJI_RAWIMAGECROPPEDSIZE)) { + TiffEntry* e = raf->getEntry(TiffTag::FUJI_RAWIMAGECROPTOPLEFT); + const uint16_t topBorder = e->getU16(0); + const uint16_t leftBorder = e->getU16(1); + e = raf->getEntry(TiffTag::FUJI_RAWIMAGECROPPEDSIZE); + const uint16_t height = e->getU16(0); + const uint16_t width = e->getU16(1); + return {leftBorder, topBorder, width, height}; + } + ThrowRDE("Cannot figure out vendor crop. Required entries were not found: " + "%X, %X", + static_cast(TiffTag::FUJI_RAWIMAGECROPTOPLEFT), + static_cast(TiffTag::FUJI_RAWIMAGECROPPEDSIZE)); +} + } // namespace rawspeed diff --git a/src/librawspeed/decoders/RafDecoder.h b/src/librawspeed/decoders/RafDecoder.h index ee9bccded..8dc9e759c 100644 --- a/src/librawspeed/decoders/RafDecoder.h +++ b/src/librawspeed/decoders/RafDecoder.h @@ -45,6 +45,7 @@ class RafDecoder final : public AbstractTiffDecoder { void applyCorrections(const Camera* cam); void decodeMetaDataInternal(const CameraMetaData* meta) override; void checkSupportInternal(const CameraMetaData* meta) override; + iRectangle2D getDefaultCrop() override; static bool isRAF(Buffer input); protected: diff --git a/src/librawspeed/parsers/FiffParser.cpp b/src/librawspeed/parsers/FiffParser.cpp index d208733a5..fac0518e5 100644 --- a/src/librawspeed/parsers/FiffParser.cpp +++ b/src/librawspeed/parsers/FiffParser.cpp @@ -105,7 +105,9 @@ void FiffParser::parseData() { uint16_t length = bytes.getU16(); TiffDataType type = TiffDataType::UNDEFINED; - if (tag == TiffTag::IMAGEWIDTH || + if (tag == TiffTag::FUJI_RAWIMAGEFULLSIZE || + tag == TiffTag::FUJI_RAWIMAGECROPTOPLEFT || + tag == TiffTag::FUJI_RAWIMAGECROPPEDSIZE || tag == TiffTag::FUJIOLDWB) // also 0x121? type = TiffDataType::SHORT; diff --git a/src/librawspeed/tiff/TiffTag.h b/src/librawspeed/tiff/TiffTag.h index 04cfca2f0..8302f9f7f 100644 --- a/src/librawspeed/tiff/TiffTag.h +++ b/src/librawspeed/tiff/TiffTag.h @@ -41,6 +41,7 @@ enum class TiffTag { MAKERNOTE_ALT = 0x2e, IMAGEWIDTH = 0x0100, + FUJI_RAWIMAGEFULLSIZE = 0x0100, IMAGELENGTH = 0x0101, BITSPERSAMPLE = 0x0102, COMPRESSION = 0x0103, @@ -50,7 +51,9 @@ enum class TiffTag { IMAGEDESCRIPTION = 0x010E, MAKE = 0x010F, MODEL = 0x0110, + FUJI_RAWIMAGECROPTOPLEFT = 0x0110, STRIPOFFSETS = 0x0111, + FUJI_RAWIMAGECROPPEDSIZE = 0x0111, ORIENTATION = 0x0112, SAMPLESPERPIXEL = 0x0115, ROWSPERSTRIP = 0x0116, @@ -245,6 +248,8 @@ enum class TiffTag { // THE XMP SPEC DECLARES THAT XMP DATA SHOULD LIVE 0x2BC WHEN // EMBEDDED IN TIFF IMAGES. XMP = 0x02BC, + // Fujifilm tag for blob describing raw image size + FUJI_RAFDATA = 0xC000, // Canon tag for uncompressed RGB preview CANON_UNCOMPRESSED = 0xC5D9,