From fd474cedcccbdad0ff28e3f19aa72e8b6b43d4fa Mon Sep 17 00:00:00 2001 From: Roman Lebedev Date: Sun, 22 Oct 2023 03:49:53 +0300 Subject: [PATCH] Basic Sinarback eVolution decoder Seems to kind-of work, but `CFARepeatPatternDim` is `2,0` (??) Refs. https://github.com/darktable-org/darktable/issues/15466 --- data/cameras.xml | 18 ++++ data/cameras.xsd | 1 + fuzz/all-fuzzers.txt | 1 + .../decoders/TiffDecoders/CMakeLists.txt | 1 + .../decoders/TiffDecoders/main.cpp | 1 + src/librawspeed/decoders/CMakeLists.txt | 2 + src/librawspeed/decoders/StiDecoder.cpp | 97 +++++++++++++++++++ src/librawspeed/decoders/StiDecoder.h | 48 +++++++++ src/librawspeed/parsers/TiffParser.cpp | 4 +- src/librawspeed/parsers/TiffParser.h | 2 +- 10 files changed, 173 insertions(+), 2 deletions(-) create mode 100644 src/librawspeed/decoders/StiDecoder.cpp create mode 100644 src/librawspeed/decoders/StiDecoder.h diff --git a/data/cameras.xml b/data/cameras.xml index 6f81d178f..988ba89f6 100644 --- a/data/cameras.xml +++ b/data/cameras.xml @@ -14359,6 +14359,24 @@ + + Sinar eVolution 75 + + GREEN + RED + BLUE + GREEN + + + + + + 16442 -2956 -2422 + -2877 12128 750 + -1136 6066 4559 + + + Sinar Hy6 diff --git a/data/cameras.xsd b/data/cameras.xsd index 25b0d4187..837db6e78 100644 --- a/data/cameras.xsd +++ b/data/cameras.xsd @@ -473,6 +473,7 @@ + diff --git a/fuzz/all-fuzzers.txt b/fuzz/all-fuzzers.txt index 764a06036..8830122d6 100644 --- a/fuzz/all-fuzzers.txt +++ b/fuzz/all-fuzzers.txt @@ -66,6 +66,7 @@ TiffDecoderFuzzer-OrfDecoder TiffDecoderFuzzer-PefDecoder TiffDecoderFuzzer-Rw2Decoder TiffDecoderFuzzer-SrwDecoder +TiffDecoderFuzzer-StiDecoder TiffDecoderFuzzer-ThreefrDecoder TiffParserFuzzer-GetDecoder TiffParserFuzzer-GetDecoder-Decode diff --git a/fuzz/librawspeed/decoders/TiffDecoders/CMakeLists.txt b/fuzz/librawspeed/decoders/TiffDecoders/CMakeLists.txt index 54122ff0b..fc7cb002f 100644 --- a/fuzz/librawspeed/decoders/TiffDecoders/CMakeLists.txt +++ b/fuzz/librawspeed/decoders/TiffDecoders/CMakeLists.txt @@ -32,6 +32,7 @@ set(DECODERS "PefDecoder" "Rw2Decoder" "SrwDecoder" + "StiDecoder" "ThreefrDecoder" ) diff --git a/fuzz/librawspeed/decoders/TiffDecoders/main.cpp b/fuzz/librawspeed/decoders/TiffDecoders/main.cpp index 5e1cc5c9d..dd09f952b 100644 --- a/fuzz/librawspeed/decoders/TiffDecoders/main.cpp +++ b/fuzz/librawspeed/decoders/TiffDecoders/main.cpp @@ -39,6 +39,7 @@ #include "decoders/RafDecoder.h" // IWYU pragma: keep #include "decoders/Rw2Decoder.h" // IWYU pragma: keep #include "decoders/SrwDecoder.h" // IWYU pragma: keep +#include "decoders/StiDecoder.h" // IWYU pragma: keep #include "decoders/ThreefrDecoder.h" // IWYU pragma: keep #include "io/Buffer.h" // for Buffer #include "metadata/CameraMetaData.h" // for CameraMetaData diff --git a/src/librawspeed/decoders/CMakeLists.txt b/src/librawspeed/decoders/CMakeLists.txt index 654116331..beb2ed1fd 100644 --- a/src/librawspeed/decoders/CMakeLists.txt +++ b/src/librawspeed/decoders/CMakeLists.txt @@ -44,6 +44,8 @@ FILE(GLOB SOURCES "SimpleTiffDecoder.h" "SrwDecoder.cpp" "SrwDecoder.h" + "StiDecoder.cpp" + "StiDecoder.h" "ThreefrDecoder.cpp" "ThreefrDecoder.h" ) diff --git a/src/librawspeed/decoders/StiDecoder.cpp b/src/librawspeed/decoders/StiDecoder.cpp new file mode 100644 index 000000000..02df2949b --- /dev/null +++ b/src/librawspeed/decoders/StiDecoder.cpp @@ -0,0 +1,97 @@ +/* + RawSpeed - RAW file decoder. + + Copyright (C) 2023 Roman Lebedev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "decoders/StiDecoder.h" +#include "adt/Point.h" // for iPoint2D +#include "decoders/RawDecoderException.h" // for ThrowException +#include "decompressors/HasselbladLJpegDecoder.h" // for HasselbladLJpegDec... +#include "decompressors/UncompressedDecompressor.h" // for UncompressedDeco... +#include "io/Buffer.h" // for Buffer, DataBuffer +#include "io/ByteStream.h" // for ByteStream +#include "io/Endianness.h" // for Endianness, Endian... +#include "metadata/ColorFilterArray.h" // for CFAColor, CFAColor... +#include "tiff/TiffEntry.h" // for TiffEntry +#include "tiff/TiffIFD.h" // for TiffRootIFD, TiffIFD +#include "tiff/TiffTag.h" // for TiffTag, TiffTag::... +#include // for array +#include // for uint32_t +#include // for unique_ptr, allocator +#include // for operator==, string + +namespace rawspeed { + +class CameraMetaData; + +bool StiDecoder::isAppropriateDecoder(const TiffRootIFD* rootIFD, + [[maybe_unused]] Buffer file) { + const auto id = rootIFD->getID(); + const std::string& make = id.make; + + // FIXME: magic + + return make == "Sinar AG"; +} + +RawImage StiDecoder::decodeRawInternal() { + const auto* raw = mRootIFD->getIFDWithTag(TiffTag::TILEOFFSETS, 0); + uint32_t width = raw->getEntry(TiffTag::IMAGEWIDTH)->getU32(); + uint32_t height = raw->getEntry(TiffTag::IMAGELENGTH)->getU32(); + uint32_t compression = raw->getEntry(TiffTag::COMPRESSION)->getU32(); + + mRaw->dim = iPoint2D(width, height); + + if (1 != compression) + ThrowRDE("Unexpected compression type."); + + DecodeUncompressed(raw); + return mRaw; +} + +void StiDecoder::DecodeUncompressed(const TiffIFD* raw) const { + if (mRaw->getDataType() != RawImageType::UINT16) + ThrowRDE("Unexpected data type"); + + if (mRaw->getCpp() != 1 || mRaw->getBpp() != sizeof(uint16_t)) + ThrowRDE("Unexpected cpp: %u", mRaw->getCpp()); + + // FIXME: could be wrong. + if (!mRaw->dim.hasPositiveArea() || mRaw->dim.x % 2 != 0 || + mRaw->dim.y % 2 != 0 || mRaw->dim.x > 4992 || mRaw->dim.y > 6668) { + ThrowRDE("Unexpected image dimensions found: (%u; %u)", mRaw->dim.x, + mRaw->dim.y); + } + + uint32_t off = raw->getEntry(TiffTag::TILEOFFSETS)->getU32(); + uint32_t count = raw->getEntry(TiffTag::TILEBYTECOUNTS)->getU32(); + + const ByteStream bs( + DataBuffer(mFile.getSubView(off, count), Endianness::little)); + + UncompressedDecompressor u(bs, mRaw, iRectangle2D({0, 0}, mRaw->dim), + 2 * mRaw->dim.x, 16, BitOrder::MSB); + mRaw->createData(); + u.readUncompressedRaw(); +} + +void StiDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { + setMetaData(meta, "", 0); +} + +} // namespace rawspeed diff --git a/src/librawspeed/decoders/StiDecoder.h b/src/librawspeed/decoders/StiDecoder.h new file mode 100644 index 000000000..4ec101f76 --- /dev/null +++ b/src/librawspeed/decoders/StiDecoder.h @@ -0,0 +1,48 @@ +/* + RawSpeed - RAW file decoder. + + Copyright (C) 2023 Roman Lebedev + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#pragma once + +#include "common/RawImage.h" // for RawImage +#include "decoders/AbstractTiffDecoder.h" // for AbstractTiffDecoder +#include "io/Buffer.h" // for Buffer +#include "tiff/TiffIFD.h" // for TiffRootIFD (ptr only) +#include // for move + +namespace rawspeed { + +class Buffer; +class CameraMetaData; + +class StiDecoder final : public AbstractTiffDecoder { +public: + static bool isAppropriateDecoder(const TiffRootIFD* rootIFD, Buffer file); + StiDecoder(TiffRootIFDOwner&& root, Buffer file) + : AbstractTiffDecoder(std::move(root), file) {} + + RawImage decodeRawInternal() override; + void decodeMetaDataInternal(const CameraMetaData* meta) override; + +private: + [[nodiscard]] int getDecoderVersion() const override { return 0; } + void DecodeUncompressed(const TiffIFD* raw) const; +}; + +} // namespace rawspeed diff --git a/src/librawspeed/parsers/TiffParser.cpp b/src/librawspeed/parsers/TiffParser.cpp index 742892a62..17f1872ab 100644 --- a/src/librawspeed/parsers/TiffParser.cpp +++ b/src/librawspeed/parsers/TiffParser.cpp @@ -38,6 +38,7 @@ #include "decoders/PefDecoder.h" // for PefDecoder #include "decoders/Rw2Decoder.h" // for Rw2Decoder #include "decoders/SrwDecoder.h" // for SrwDecoder +#include "decoders/StiDecoder.h" // for StiDecoder #include "decoders/ThreefrDecoder.h" // for ThreefrDecoder #include "io/Buffer.h" // for Buffer, DataBuffer #include "io/ByteStream.h" // for ByteStream @@ -120,7 +121,7 @@ std::unique_ptr TiffParser::constructor(TiffRootIFDOwner&& root, } const std::array, - 16> + 17> TiffParser::Map = {{ DECODER(DngDecoder), DECODER(MosDecoder), @@ -137,6 +138,7 @@ const std::array, DECODER(DcsDecoder), DECODER(KdcDecoder), DECODER(ErfDecoder), + DECODER(StiDecoder), DECODER(ThreefrDecoder), }}; diff --git a/src/librawspeed/parsers/TiffParser.h b/src/librawspeed/parsers/TiffParser.h index dbca26c8f..ce4ab4f77 100644 --- a/src/librawspeed/parsers/TiffParser.h +++ b/src/librawspeed/parsers/TiffParser.h @@ -55,7 +55,7 @@ class TiffParser final : public RawParser { using checker_t = bool (*)(const TiffRootIFD* root, Buffer data); using constructor_t = std::unique_ptr (*)(TiffRootIFDOwner&& root, Buffer data); - static const std::array, 16> Map; + static const std::array, 17> Map; }; } // namespace rawspeed