diff --git a/.gitignore b/.gitignore index 41886df7c..48f69a1e1 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ cscope.out *.vcproj *.vcxproj .vscode/ +CMakeLists.txt.user # Compiled Object files *.slo diff --git a/fuzz/librawspeed/decompressors/Cr2Decompressor.cpp b/fuzz/librawspeed/decompressors/Cr2Decompressor.cpp index e0a702256..dcc6ed47f 100644 --- a/fuzz/librawspeed/decompressors/Cr2Decompressor.cpp +++ b/fuzz/librawspeed/decompressors/Cr2Decompressor.cpp @@ -39,7 +39,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { const rawspeed::DataBuffer db(b, rawspeed::Endianness::little); rawspeed::ByteStream bs(db); - rawspeed::RawImage mRaw(CreateRawImage(bs)); + auto mRaw(CreateRawImage(bs)); using slice_type = uint16_t; const auto numSlices = bs.get(); @@ -48,7 +48,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { const rawspeed::Cr2Slicing slicing(numSlices, sliceWidth, lastSliceWidth); - rawspeed::Cr2Decompressor c(bs, mRaw); + rawspeed::Cr2Decompressor c(bs, mRaw.get()); mRaw->createData(); c.decode(slicing); diff --git a/fuzz/librawspeed/decompressors/CrwDecompressor.cpp b/fuzz/librawspeed/decompressors/CrwDecompressor.cpp index 518f0820a..029432959 100644 --- a/fuzz/librawspeed/decompressors/CrwDecompressor.cpp +++ b/fuzz/librawspeed/decompressors/CrwDecompressor.cpp @@ -39,12 +39,12 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { const rawspeed::DataBuffer db(b, rawspeed::Endianness::little); rawspeed::ByteStream bs(db); - rawspeed::RawImage mRaw(CreateRawImage(bs)); + auto mRaw(CreateRawImage(bs)); const uint32_t dec_table = bs.getU32(); const uint32_t lowbits = bs.getU32(); - rawspeed::CrwDecompressor c(mRaw, dec_table, lowbits, + rawspeed::CrwDecompressor c(mRaw.get(), dec_table, lowbits, bs.getStream(bs.getRemainSize())); mRaw->createData(); c.decompress(); diff --git a/fuzz/librawspeed/decompressors/DummyLJpegDecompressor.cpp b/fuzz/librawspeed/decompressors/DummyLJpegDecompressor.cpp index 4b654ae9a..f07c073b1 100644 --- a/fuzz/librawspeed/decompressors/DummyLJpegDecompressor.cpp +++ b/fuzz/librawspeed/decompressors/DummyLJpegDecompressor.cpp @@ -39,7 +39,7 @@ class DummyLJpegDecompressor final public: DummyLJpegDecompressor(const rawspeed::ByteStream& bs, - const rawspeed::RawImage& img) + rawspeed::RawImageData* img) : AbstractLJpegDecompressor(bs, img) {} void decode() { AbstractLJpegDecompressor::decode(); } @@ -55,9 +55,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { const rawspeed::DataBuffer db(b, rawspeed::Endianness::little); rawspeed::ByteStream bs(db); - rawspeed::RawImage mRaw(CreateRawImage(bs)); + auto mRaw(CreateRawImage(bs)); - DummyLJpegDecompressor d(bs, mRaw); + DummyLJpegDecompressor d(bs, mRaw.get()); d.decode(); mRaw->createData(); diff --git a/fuzz/librawspeed/decompressors/FujiDecompressor.cpp b/fuzz/librawspeed/decompressors/FujiDecompressor.cpp index c5a7407bc..0d9dc6a88 100644 --- a/fuzz/librawspeed/decompressors/FujiDecompressor.cpp +++ b/fuzz/librawspeed/decompressors/FujiDecompressor.cpp @@ -39,10 +39,10 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { const rawspeed::DataBuffer db(b, rawspeed::Endianness::little); rawspeed::ByteStream bs(db); - rawspeed::RawImage mRaw(CreateRawImage(bs)); + auto mRaw(CreateRawImage(bs)); mRaw->cfa = CreateCFA(bs); - rawspeed::FujiDecompressor f(mRaw, bs.getStream(bs.getRemainSize())); + rawspeed::FujiDecompressor f(mRaw.get(), bs.getStream(bs.getRemainSize())); mRaw->createData(); f.decompress(); diff --git a/fuzz/librawspeed/decompressors/HasselbladDecompressor.cpp b/fuzz/librawspeed/decompressors/HasselbladDecompressor.cpp index 987502576..33b59e469 100644 --- a/fuzz/librawspeed/decompressors/HasselbladDecompressor.cpp +++ b/fuzz/librawspeed/decompressors/HasselbladDecompressor.cpp @@ -39,11 +39,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { const rawspeed::DataBuffer db(b, rawspeed::Endianness::little); rawspeed::ByteStream bs(db); - rawspeed::RawImage mRaw(CreateRawImage(bs)); + auto mRaw(CreateRawImage(bs)); const auto pixelBaseOffset = bs.get(); - rawspeed::HasselbladDecompressor h(bs, mRaw); + rawspeed::HasselbladDecompressor h(bs, mRaw.get()); mRaw->createData(); h.decode(pixelBaseOffset); diff --git a/fuzz/librawspeed/decompressors/KodakDecompressor.cpp b/fuzz/librawspeed/decompressors/KodakDecompressor.cpp index 9a3d58803..e1ef317c9 100644 --- a/fuzz/librawspeed/decompressors/KodakDecompressor.cpp +++ b/fuzz/librawspeed/decompressors/KodakDecompressor.cpp @@ -39,13 +39,13 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { const rawspeed::DataBuffer db(b, rawspeed::Endianness::little); rawspeed::ByteStream bs(db); - rawspeed::RawImage mRaw(CreateRawImage(bs)); + auto mRaw(CreateRawImage(bs)); const bool bps = bs.getU32(); const bool uncorrectedRawValues = bs.getU32(); - rawspeed::KodakDecompressor k(mRaw, bs.getStream(bs.getRemainSize()), bps, - uncorrectedRawValues); + rawspeed::KodakDecompressor k(mRaw.get(), bs.getStream(bs.getRemainSize()), + bps, uncorrectedRawValues); mRaw->createData(); diff --git a/fuzz/librawspeed/decompressors/LJpegDecompressor.cpp b/fuzz/librawspeed/decompressors/LJpegDecompressor.cpp index 36a1216b4..7f6618b26 100644 --- a/fuzz/librawspeed/decompressors/LJpegDecompressor.cpp +++ b/fuzz/librawspeed/decompressors/LJpegDecompressor.cpp @@ -39,7 +39,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { const rawspeed::DataBuffer db(b, rawspeed::Endianness::little); rawspeed::ByteStream bs(db); - rawspeed::RawImage mRaw(CreateRawImage(bs)); + auto mRaw(CreateRawImage(bs)); const auto offsetX = bs.getU32(); const auto offsetY = bs.getU32(); @@ -47,7 +47,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { const auto height = bs.getU32(); const auto fixDng16Bug = bs.getU32(); - rawspeed::LJpegDecompressor j(bs, mRaw); + rawspeed::LJpegDecompressor j(bs, mRaw.get()); mRaw->createData(); j.decode(offsetX, offsetY, width, height, fixDng16Bug); diff --git a/fuzz/librawspeed/decompressors/NikonDecompressor.cpp b/fuzz/librawspeed/decompressors/NikonDecompressor.cpp index d4bf173b1..7ab5d903b 100644 --- a/fuzz/librawspeed/decompressors/NikonDecompressor.cpp +++ b/fuzz/librawspeed/decompressors/NikonDecompressor.cpp @@ -39,7 +39,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { const rawspeed::DataBuffer db(b, rawspeed::Endianness::little); rawspeed::ByteStream bs(db); - rawspeed::RawImage mRaw(CreateRawImage(bs)); + auto mRaw(CreateRawImage(bs)); const auto bitsPS = bs.get(); const auto uncorrectedRawValues = bs.get(); @@ -47,7 +47,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { rawspeed::ByteStream metaData = bs.getStream(medataLength); rawspeed::ByteStream rawData = bs.getStream(bs.getRemainSize()); - rawspeed::NikonDecompressor n(mRaw, metaData, bitsPS); + rawspeed::NikonDecompressor n(mRaw.get(), metaData, bitsPS); mRaw->createData(); n.decompress(rawData, uncorrectedRawValues); diff --git a/fuzz/librawspeed/decompressors/OlympusDecompressor.cpp b/fuzz/librawspeed/decompressors/OlympusDecompressor.cpp index 54017dcc3..cb70a9ca2 100644 --- a/fuzz/librawspeed/decompressors/OlympusDecompressor.cpp +++ b/fuzz/librawspeed/decompressors/OlympusDecompressor.cpp @@ -39,9 +39,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { const rawspeed::DataBuffer db(b, rawspeed::Endianness::little); rawspeed::ByteStream bs(db); - rawspeed::RawImage mRaw(CreateRawImage(bs)); + auto mRaw(CreateRawImage(bs)); - rawspeed::OlympusDecompressor o(mRaw); + rawspeed::OlympusDecompressor o(mRaw.get()); mRaw->createData(); diff --git a/fuzz/librawspeed/decompressors/PanasonicV4Decompressor.cpp b/fuzz/librawspeed/decompressors/PanasonicV4Decompressor.cpp index 8986f6c56..36890962f 100644 --- a/fuzz/librawspeed/decompressors/PanasonicV4Decompressor.cpp +++ b/fuzz/librawspeed/decompressors/PanasonicV4Decompressor.cpp @@ -39,13 +39,13 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { const rawspeed::DataBuffer db(b, rawspeed::Endianness::little); rawspeed::ByteStream bs(db); - rawspeed::RawImage mRaw(CreateRawImage(bs)); + auto mRaw(CreateRawImage(bs)); const auto zero_is_not_bad = bs.get(); const auto section_split_offset = bs.get(); rawspeed::ByteStream rawData = bs.getStream(bs.getRemainSize()); - rawspeed::PanasonicV4Decompressor p(mRaw, rawData, zero_is_not_bad, + rawspeed::PanasonicV4Decompressor p(mRaw.get(), rawData, zero_is_not_bad, section_split_offset); mRaw->createData(); p.decompress(); diff --git a/fuzz/librawspeed/decompressors/PanasonicV5Decompressor.cpp b/fuzz/librawspeed/decompressors/PanasonicV5Decompressor.cpp index f0667c162..b0445eb23 100644 --- a/fuzz/librawspeed/decompressors/PanasonicV5Decompressor.cpp +++ b/fuzz/librawspeed/decompressors/PanasonicV5Decompressor.cpp @@ -38,12 +38,12 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { const rawspeed::DataBuffer db(b, rawspeed::Endianness::little); rawspeed::ByteStream bs(db); - rawspeed::RawImage mRaw(CreateRawImage(bs)); + auto mRaw(CreateRawImage(bs)); const auto bps = bs.get(); rawspeed::ByteStream rawData = bs.getStream(bs.getRemainSize()); - rawspeed::PanasonicV5Decompressor p(mRaw, rawData, bps); + rawspeed::PanasonicV5Decompressor p(mRaw.get(), rawData, bps); mRaw->createData(); p.decompress(); diff --git a/fuzz/librawspeed/decompressors/PanasonicV6Decompressor.cpp b/fuzz/librawspeed/decompressors/PanasonicV6Decompressor.cpp index d96c4fc38..3f2957d6d 100644 --- a/fuzz/librawspeed/decompressors/PanasonicV6Decompressor.cpp +++ b/fuzz/librawspeed/decompressors/PanasonicV6Decompressor.cpp @@ -39,11 +39,11 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { const rawspeed::DataBuffer db(b, rawspeed::Endianness::little); rawspeed::ByteStream bs(db); - rawspeed::RawImage mRaw(CreateRawImage(bs)); + auto mRaw(CreateRawImage(bs)); rawspeed::ByteStream rawData = bs.getStream(bs.getRemainSize()); - rawspeed::PanasonicV6Decompressor p(mRaw, rawData); + rawspeed::PanasonicV6Decompressor p(mRaw.get(), rawData); mRaw->createData(); p.decompress(); diff --git a/fuzz/librawspeed/decompressors/PentaxDecompressor.cpp b/fuzz/librawspeed/decompressors/PentaxDecompressor.cpp index 5ca921947..205ed08e8 100644 --- a/fuzz/librawspeed/decompressors/PentaxDecompressor.cpp +++ b/fuzz/librawspeed/decompressors/PentaxDecompressor.cpp @@ -39,7 +39,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { const rawspeed::DataBuffer db(b, rawspeed::Endianness::little); rawspeed::ByteStream bs(db); - rawspeed::RawImage mRaw(CreateRawImage(bs)); + auto mRaw(CreateRawImage(bs)); std::optional metaData; @@ -51,7 +51,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { rawspeed::ByteStream rawData = bs.getStream(bs.getRemainSize()); - rawspeed::PentaxDecompressor p(mRaw, metaData); + rawspeed::PentaxDecompressor p(mRaw.get(), metaData); mRaw->createData(); p.decompress(rawData); diff --git a/fuzz/librawspeed/decompressors/PhaseOneDecompressor.cpp b/fuzz/librawspeed/decompressors/PhaseOneDecompressor.cpp index 47d160a35..f0c23cc66 100644 --- a/fuzz/librawspeed/decompressors/PhaseOneDecompressor.cpp +++ b/fuzz/librawspeed/decompressors/PhaseOneDecompressor.cpp @@ -41,7 +41,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { const rawspeed::DataBuffer db(b, rawspeed::Endianness::little); rawspeed::ByteStream bs(db); - rawspeed::RawImage mRaw(CreateRawImage(bs)); + auto mRaw(CreateRawImage(bs)); const auto numStrips = bs.getU32(); std::vector strips; @@ -53,7 +53,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { }); assert(strips.size() == numStrips); - rawspeed::PhaseOneDecompressor f(mRaw, std::move(strips)); + rawspeed::PhaseOneDecompressor f(mRaw.get(), std::move(strips)); mRaw->createData(); f.decompress(); diff --git a/fuzz/librawspeed/decompressors/SamsungV0Decompressor.cpp b/fuzz/librawspeed/decompressors/SamsungV0Decompressor.cpp index e3274f9df..7918cc477 100644 --- a/fuzz/librawspeed/decompressors/SamsungV0Decompressor.cpp +++ b/fuzz/librawspeed/decompressors/SamsungV0Decompressor.cpp @@ -39,13 +39,13 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { const rawspeed::DataBuffer db(b, rawspeed::Endianness::little); rawspeed::ByteStream bs(db); - rawspeed::RawImage mRaw(CreateRawImage(bs)); + auto mRaw(CreateRawImage(bs)); const auto bsoLength = bs.get(); rawspeed::ByteStream bso = bs.getStream(bsoLength); rawspeed::ByteStream bsr = bs.getStream(bs.getRemainSize()); - rawspeed::SamsungV0Decompressor p(mRaw, bso, bsr); + rawspeed::SamsungV0Decompressor p(mRaw.get(), bso, bsr); mRaw->createData(); p.decompress(); diff --git a/fuzz/librawspeed/decompressors/SamsungV1Decompressor.cpp b/fuzz/librawspeed/decompressors/SamsungV1Decompressor.cpp index 68cacd8af..da27c2d3d 100644 --- a/fuzz/librawspeed/decompressors/SamsungV1Decompressor.cpp +++ b/fuzz/librawspeed/decompressors/SamsungV1Decompressor.cpp @@ -39,12 +39,12 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { const rawspeed::DataBuffer db(b, rawspeed::Endianness::little); rawspeed::ByteStream bs(db); - rawspeed::RawImage mRaw(CreateRawImage(bs)); + auto mRaw(CreateRawImage(bs)); const auto bit = bs.get(); rawspeed::ByteStream rawData = bs.getStream(bs.getRemainSize()); - rawspeed::SamsungV1Decompressor p(mRaw, rawData, bit); + rawspeed::SamsungV1Decompressor p(mRaw.get(), rawData, bit); mRaw->createData(); p.decompress(); diff --git a/fuzz/librawspeed/decompressors/SamsungV2Decompressor.cpp b/fuzz/librawspeed/decompressors/SamsungV2Decompressor.cpp index 1dddbbc9a..cab70b3d7 100644 --- a/fuzz/librawspeed/decompressors/SamsungV2Decompressor.cpp +++ b/fuzz/librawspeed/decompressors/SamsungV2Decompressor.cpp @@ -39,12 +39,12 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { const rawspeed::DataBuffer db(b, rawspeed::Endianness::little); rawspeed::ByteStream bs(db); - rawspeed::RawImage mRaw(CreateRawImage(bs)); + auto mRaw(CreateRawImage(bs)); const auto bit = bs.get(); rawspeed::ByteStream rawData = bs.getStream(bs.getRemainSize()); - rawspeed::SamsungV2Decompressor p(mRaw, rawData, bit); + rawspeed::SamsungV2Decompressor p(mRaw.get(), rawData, bit); mRaw->createData(); p.decompress(); diff --git a/fuzz/librawspeed/decompressors/SonyArw1Decompressor.cpp b/fuzz/librawspeed/decompressors/SonyArw1Decompressor.cpp index 16a4bedcd..3334f36ef 100644 --- a/fuzz/librawspeed/decompressors/SonyArw1Decompressor.cpp +++ b/fuzz/librawspeed/decompressors/SonyArw1Decompressor.cpp @@ -39,9 +39,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { const rawspeed::DataBuffer db(b, rawspeed::Endianness::little); rawspeed::ByteStream bs(db); - rawspeed::RawImage mRaw(CreateRawImage(bs)); + auto mRaw(CreateRawImage(bs)); - rawspeed::SonyArw1Decompressor a(mRaw); + rawspeed::SonyArw1Decompressor a(mRaw.get()); mRaw->createData(); diff --git a/fuzz/librawspeed/decompressors/SonyArw2Decompressor.cpp b/fuzz/librawspeed/decompressors/SonyArw2Decompressor.cpp index f17f4b30b..baba309b1 100644 --- a/fuzz/librawspeed/decompressors/SonyArw2Decompressor.cpp +++ b/fuzz/librawspeed/decompressors/SonyArw2Decompressor.cpp @@ -39,9 +39,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { const rawspeed::DataBuffer db(b, rawspeed::Endianness::little); rawspeed::ByteStream bs(db); - rawspeed::RawImage mRaw(CreateRawImage(bs)); + auto mRaw(CreateRawImage(bs)); - rawspeed::SonyArw2Decompressor a(mRaw, bs.getStream(bs.getRemainSize())); + rawspeed::SonyArw2Decompressor a(mRaw.get(), bs.getStream(bs.getRemainSize())); mRaw->createData(); diff --git a/fuzz/librawspeed/decompressors/VC5Decompressor.cpp b/fuzz/librawspeed/decompressors/VC5Decompressor.cpp index 807aab8e8..893fe0d3a 100644 --- a/fuzz/librawspeed/decompressors/VC5Decompressor.cpp +++ b/fuzz/librawspeed/decompressors/VC5Decompressor.cpp @@ -39,7 +39,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { const rawspeed::DataBuffer db(b, rawspeed::Endianness::little); rawspeed::ByteStream bs(db); - rawspeed::RawImage mRaw(CreateRawImage(bs)); + auto mRaw(CreateRawImage(bs)); mRaw->whitePoint = bs.getI32(); const auto offsetX = bs.getU32(); @@ -47,7 +47,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) { const auto width = bs.getU32(); const auto height = bs.getU32(); - rawspeed::VC5Decompressor v(bs, mRaw); + rawspeed::VC5Decompressor v(bs, mRaw.get()); mRaw->createData(); v.decode(offsetX, offsetY, width, height); diff --git a/fuzz/librawspeed/fuzz/Common.cpp b/fuzz/librawspeed/fuzz/Common.cpp index dc89d92f1..03f457d33 100644 --- a/fuzz/librawspeed/fuzz/Common.cpp +++ b/fuzz/librawspeed/fuzz/Common.cpp @@ -29,7 +29,7 @@ #include // for uint32_t #include // for numeric_limits -rawspeed::RawImage CreateRawImage(rawspeed::ByteStream& bs) { +std::shared_ptr CreateRawImage(rawspeed::ByteStream& bs) { const uint32_t width = bs.getU32(); const uint32_t height = bs.getU32(); const uint32_t type = bs.getU32(); @@ -40,8 +40,16 @@ rawspeed::RawImage CreateRawImage(rawspeed::ByteStream& bs) { type != static_cast(rawspeed::RawImageType::F32)) ThrowRSE("Unknown image type: %u", type); - rawspeed::RawImage mRaw( - rawspeed::RawImage::create(static_cast(type))); + /*rawspeed::RawImage mRaw( + rawspeed::RawImage::create(static_cast(type)));*/ + std::shared_ptr mRaw; + + if(type != static_cast(rawspeed::RawImageType::UINT16)) + mRaw = std::make_shared(); + + if(type != static_cast(rawspeed::RawImageType::F32)) + mRaw = std::make_shared(); + mRaw->dim = rawspeed::iPoint2D(static_cast(width), diff --git a/fuzz/librawspeed/fuzz/Common.h b/fuzz/librawspeed/fuzz/Common.h index 5e1da5b2f..5e45d2841 100644 --- a/fuzz/librawspeed/fuzz/Common.h +++ b/fuzz/librawspeed/fuzz/Common.h @@ -27,5 +27,5 @@ namespace rawspeed { class ByteStream; } // namespace rawspeed -rawspeed::RawImage CreateRawImage(rawspeed::ByteStream& bs); +std::shared_ptr CreateRawImage(rawspeed::ByteStream& bs); rawspeed::ColorFilterArray CreateCFA(rawspeed::ByteStream& bs); diff --git a/src/librawspeed/common/DngOpcodes.cpp b/src/librawspeed/common/DngOpcodes.cpp index 452fd40bd..3b16c4031 100644 --- a/src/librawspeed/common/DngOpcodes.cpp +++ b/src/librawspeed/common/DngOpcodes.cpp @@ -51,12 +51,12 @@ class DngOpcodes::DngOpcode { // Will be called once before processing. // Can be used for preparing pre-calculated values, etc. - virtual void setup(const RawImage& ri) { + virtual void setup(RawImageData* ri) { // NOP by default. child class shall override this if needed. } // Will be called for actual processing. - virtual void apply(const RawImage& ri) = 0; + virtual void apply(RawImageData* ri) = 0; }; // **************************************************************************** @@ -65,12 +65,12 @@ class DngOpcodes::FixBadPixelsConstant final : public DngOpcodes::DngOpcode { uint32_t value; public: - explicit FixBadPixelsConstant(const RawImage& ri, ByteStream& bs) + explicit FixBadPixelsConstant(RawImageData* ri, ByteStream& bs) : value(bs.getU32()) { bs.getU32(); // Bayer Phase not used } - void setup(const RawImage& ri) override { + void setup(RawImageData* ri) override { // These limitations are present within the DNG SDK as well. if (ri->getDataType() != RawImageType::UINT16) ThrowRDE("Only 16 bit images supported"); @@ -79,9 +79,12 @@ class DngOpcodes::FixBadPixelsConstant final : public DngOpcodes::DngOpcode { ThrowRDE("Only 1 component images supported"); } - void apply(const RawImage& ri) override { + void apply(RawImageData* ri) override { MutexLocker guard(&ri->mBadPixelMutex); - const CroppedArray2DRef img(ri->getU16DataAsCroppedArray2DRef()); + auto *rawU16 = dynamic_cast(ri); + assert(rawU16); + const CroppedArray2DRef img( + rawU16->getU16DataAsCroppedArray2DRef()); iPoint2D crop = ri->getCropOffset(); uint32_t offset = crop.x | (crop.y << 16); for (auto row = 0; row < img.croppedHeight; ++row) { @@ -99,7 +102,7 @@ class DngOpcodes::ROIOpcode : public DngOpcodes::DngOpcode { iRectangle2D roi; protected: - explicit ROIOpcode(const RawImage& ri, ByteStream& bs, bool minusOne) { + explicit ROIOpcode(RawImageData* ri, ByteStream& bs, bool minusOne) { const iRectangle2D fullImage = minusOne ? iRectangle2D(0, 0, ri->dim.x - 1, ri->dim.y - 1) : iRectangle2D(0, 0, ri->dim.x, ri->dim.y); @@ -135,14 +138,14 @@ class DngOpcodes::ROIOpcode : public DngOpcodes::DngOpcode { class DngOpcodes::DummyROIOpcode final : public ROIOpcode { public: - explicit DummyROIOpcode(const RawImage& ri, ByteStream& bs) + explicit DummyROIOpcode(RawImageData* ri, ByteStream& bs) : ROIOpcode(ri, bs, true) {} [[nodiscard]] const iRectangle2D& __attribute__((pure)) getRoi() const { return ROIOpcode::getRoi(); } - [[noreturn]] void apply(const RawImage& ri) override { + [[noreturn]] void apply(RawImageData* ri) override { // NOLINTNEXTLINE: https://bugs.llvm.org/show_bug.cgi?id=50532 assert(false && "You should not be calling this."); __builtin_unreachable(); @@ -155,7 +158,7 @@ class DngOpcodes::FixBadPixelsList final : public DngOpcodes::DngOpcode { std::vector badPixels; public: - explicit FixBadPixelsList(const RawImage& ri, ByteStream& bs) { + explicit FixBadPixelsList(RawImageData* ri, ByteStream& bs) { const iRectangle2D fullImage(0, 0, ri->getUncroppedDim().x - 1, ri->getUncroppedDim().y - 1); @@ -199,7 +202,7 @@ class DngOpcodes::FixBadPixelsList final : public DngOpcodes::DngOpcode { } } - void apply(const RawImage& ri) override { + void apply(RawImageData* ri) override { MutexLocker guard(&ri->mBadPixelMutex); ri->mBadPixelPositions.insert(ri->mBadPixelPositions.begin(), badPixels.begin(), badPixels.end()); @@ -210,10 +213,10 @@ class DngOpcodes::FixBadPixelsList final : public DngOpcodes::DngOpcode { class DngOpcodes::TrimBounds final : public ROIOpcode { public: - explicit TrimBounds(const RawImage& ri, ByteStream& bs) + explicit TrimBounds(RawImageData* ri, ByteStream& bs) : ROIOpcode(ri, bs, false) {} - void apply(const RawImage& ri) override { ri->subFrame(getRoi()); } + void apply(RawImageData* ri) override { ri->subFrame(getRoi()); } }; // **************************************************************************** @@ -225,7 +228,7 @@ class DngOpcodes::PixelOpcode : public ROIOpcode { uint32_t colPitch; protected: - explicit PixelOpcode(const RawImage& ri, ByteStream& bs) + explicit PixelOpcode(RawImageData* ri, ByteStream& bs) : ROIOpcode(ri, bs, false), firstPlane(bs.getU32()), planes(bs.getU32()) { if (planes == 0 || firstPlane > ri->getCpp() || planes > ri->getCpp() || @@ -247,7 +250,7 @@ class DngOpcodes::PixelOpcode : public ROIOpcode { // traverses the current ROI and applies the operation OP to each pixel, // i.e. each pixel value v is replaced by op(x, y, v), where x/y are the // coordinates of the pixel value v. - template void applyOP(const RawImage& ri, OP op) { + template void applyOP(RawImageData* ri, OP op) { int cpp = ri->getCpp(); const iRectangle2D& ROI = getRoi(); for (auto y = ROI.getTop(); y < ROI.getBottom(); y += rowPitch) { @@ -270,16 +273,16 @@ class DngOpcodes::LookupOpcode : public PixelOpcode { protected: vector lookup; - explicit LookupOpcode(const RawImage& ri, ByteStream& bs) + explicit LookupOpcode(RawImageData* ri, ByteStream& bs) : PixelOpcode(ri, bs), lookup(65536) {} - void setup(const RawImage& ri) override { + void setup(RawImageData* ri) override { PixelOpcode::setup(ri); if (ri->getDataType() != RawImageType::UINT16) ThrowRDE("Only 16 bit images supported"); } - void apply(const RawImage& ri) override { + void apply(RawImageData* ri) override { applyOP(ri, [this]([[maybe_unused]] uint32_t x, [[maybe_unused]] uint32_t y, uint16_t v) { return lookup[v]; }); @@ -290,7 +293,7 @@ class DngOpcodes::LookupOpcode : public PixelOpcode { class DngOpcodes::TableMap final : public LookupOpcode { public: - explicit TableMap(const RawImage& ri, ByteStream& bs) : LookupOpcode(ri, bs) { + explicit TableMap(RawImageData* ri, ByteStream& bs) : LookupOpcode(ri, bs) { auto count = bs.getU32(); if (count == 0 || count > 65536) @@ -308,7 +311,7 @@ class DngOpcodes::TableMap final : public LookupOpcode { class DngOpcodes::PolynomialMap final : public LookupOpcode { public: - explicit PolynomialMap(const RawImage& ri, ByteStream& bs) + explicit PolynomialMap(RawImageData* ri, ByteStream& bs) : LookupOpcode(ri, bs) { vector polynomial; @@ -345,13 +348,13 @@ class DngOpcodes::DeltaRowOrColBase : public PixelOpcode { }; protected: - DeltaRowOrColBase(const RawImage& ri, ByteStream& bs) : PixelOpcode(ri, bs) {} + DeltaRowOrColBase(RawImageData* ri, ByteStream& bs) : PixelOpcode(ri, bs) {} }; template class DngOpcodes::DeltaRowOrCol : public DeltaRowOrColBase { public: - void setup(const RawImage& ri) override { + void setup(RawImageData* ri) override { PixelOpcode::setup(ri); // If we are working on a float image, no need to convert to int @@ -374,7 +377,7 @@ class DngOpcodes::DeltaRowOrCol : public DeltaRowOrColBase { // only meaningful for uint16_t images! virtual bool valueIsOk(float value) = 0; - DeltaRowOrCol(const RawImage& ri, ByteStream& bs, float f2iScale_) + DeltaRowOrCol(RawImageData* ri, ByteStream& bs, float f2iScale_) : DeltaRowOrColBase(ri, bs), f2iScale(f2iScale_) { const auto deltaF_count = bs.getU32(); (void)bs.check(deltaF_count, 4); @@ -413,12 +416,12 @@ class DngOpcodes::OffsetPerRowOrCol final : public DeltaRowOrCol { bool valueIsOk(float value) override { return std::abs(value) <= absLimit; } public: - explicit OffsetPerRowOrCol(const RawImage& ri, ByteStream& bs) + explicit OffsetPerRowOrCol(RawImageData* ri, ByteStream& bs) : DeltaRowOrCol(ri, bs, 65535.0F), absLimit(double(std::numeric_limits::max()) / this->f2iScale) {} - void apply(const RawImage& ri) override { + void apply(RawImageData* ri) override { if (ri->getDataType() == RawImageType::UINT16) { this->template applyOP( ri, [this](uint32_t x, uint32_t y, uint16_t v) { @@ -450,13 +453,13 @@ class DngOpcodes::ScalePerRowOrCol final : public DeltaRowOrCol { } public: - explicit ScalePerRowOrCol(const RawImage& ri, ByteStream& bs) + explicit ScalePerRowOrCol(RawImageData* ri, ByteStream& bs) : DeltaRowOrCol(ri, bs, 1024.0F), maxLimit((double(std::numeric_limits::max() - rounding) / double(std::numeric_limits::max())) / this->f2iScale) {} - void apply(const RawImage& ri) override { + void apply(RawImageData* ri) override { if (ri->getDataType() == RawImageType::UINT16) { this->template applyOP(ri, [this](uint32_t x, uint32_t y, uint16_t v) { @@ -473,7 +476,7 @@ class DngOpcodes::ScalePerRowOrCol final : public DeltaRowOrCol { // **************************************************************************** -DngOpcodes::DngOpcodes(const RawImage& ri, const TiffEntry* entry) { +DngOpcodes::DngOpcodes(RawImageData *ri, const TiffEntry* entry) { ByteStream bs = entry->getData(); // DNG opcodes are always stored in big-endian byte order. @@ -538,7 +541,7 @@ DngOpcodes::DngOpcodes(const RawImage& ri, const TiffEntry* entry) { // of the DngOpcode type in DngOpcodes.h DngOpcodes::~DngOpcodes() = default; -void DngOpcodes::applyOpCodes(const RawImage& ri) const { +void DngOpcodes::applyOpCodes(RawImageData *ri) const { for (const auto& code : opcodes) { code->setup(ri); code->apply(ri); @@ -547,7 +550,7 @@ void DngOpcodes::applyOpCodes(const RawImage& ri) const { template std::unique_ptr -DngOpcodes::constructor(const RawImage& ri, ByteStream& bs) { +DngOpcodes::constructor(RawImageData* ri, ByteStream& bs) { return std::make_unique(ri, bs); } diff --git a/src/librawspeed/common/DngOpcodes.h b/src/librawspeed/common/DngOpcodes.h index 0d9d76f7f..80ff19f41 100644 --- a/src/librawspeed/common/DngOpcodes.h +++ b/src/librawspeed/common/DngOpcodes.h @@ -29,7 +29,7 @@ namespace rawspeed { -class RawImage; +class RawImageData; class TiffEntry; @@ -38,9 +38,9 @@ class ByteStream; class DngOpcodes { public: - DngOpcodes(const RawImage& ri, const TiffEntry* entry); + DngOpcodes(RawImageData* ri, const TiffEntry* entry); ~DngOpcodes(); - void applyOpCodes(const RawImage& ri) const; + void applyOpCodes(RawImageData* ri) const; private: class DngOpcode; @@ -62,10 +62,10 @@ class DngOpcodes template class ScalePerRowOrCol; template - static std::unique_ptr constructor(const RawImage& ri, + static std::unique_ptr constructor(RawImageData* ri, ByteStream& bs); - using constructor_t = std::unique_ptr (*)(const RawImage& ri, + using constructor_t = std::unique_ptr (*)(RawImageData* ri, ByteStream& bs); static const std::map> Map; }; diff --git a/src/librawspeed/common/RawImage.cpp b/src/librawspeed/common/RawImage.cpp index 0f27624e6..36df9f465 100644 --- a/src/librawspeed/common/RawImage.cpp +++ b/src/librawspeed/common/RawImage.cpp @@ -57,7 +57,6 @@ RawImageData::RawImageData(const iPoint2D& _dim, int _bpc, int _cpp) } RawImageData::~RawImageData() { - assert(dataRefCount == 0); mOffset = iPoint2D(0, 0); destroyData(); @@ -281,30 +280,6 @@ void RawImageData::createBadPixelMap() ThrowRDE("Memory Allocation failed."); } -RawImage::RawImage(RawImageData* p) : p_(p) { - MutexLocker guard(&p_->mymutex); - ++p_->dataRefCount; -} - -RawImage::RawImage(const RawImage& p) : p_(p.p_) { - MutexLocker guard(&p_->mymutex); - ++p_->dataRefCount; -} - -RawImage::~RawImage() { - p_->mymutex.Lock(); - - --p_->dataRefCount; - - if (p_->dataRefCount == 0) { - p_->mymutex.Unlock(); - delete p_; - return; - } - - p_->mymutex.Unlock(); -} - void RawImageData::transferBadPixelsToMap() { MutexLocker guard(&mBadPixelMutex); @@ -428,7 +403,7 @@ void RawImageData::fixBadPixelsThread(int start_y, int end_y) { } } -void RawImageData::blitFrom(const RawImage& src, const iPoint2D& srcPos, +void RawImageData::blitFrom(RawImageData* src, const iPoint2D& srcPos, const iPoint2D& size, const iPoint2D& destPos) { iRectangle2D src_rect(srcPos, size); iRectangle2D dest_rect(destPos, size); @@ -503,25 +478,6 @@ void RawImageData::clearArea(iRectangle2D area, uint8_t val /*= 0*/) { static_cast(area.getWidth()) * bpp); } -RawImage& RawImage::operator=(RawImage&& rhs) noexcept { - if (this == &rhs) - return *this; - - std::swap(p_, rhs.p_); - - return *this; -} - -RawImage& RawImage::operator=(const RawImage& rhs) noexcept { - if (this == &rhs) - return *this; - - RawImage tmp(rhs); - *this = std::move(tmp); - - return *this; -} - RawImageWorker::RawImageWorker(RawImageData* _img, RawImageWorkerTask _task, int _start_y, int _end_y) noexcept : data(_img), task(_task), start_y(_start_y), end_y(_end_y) { diff --git a/src/librawspeed/common/RawImage.h b/src/librawspeed/common/RawImage.h index 38acb19fb..695fdbb10 100644 --- a/src/librawspeed/common/RawImage.h +++ b/src/librawspeed/common/RawImage.h @@ -41,8 +41,6 @@ namespace rawspeed { -class RawImage; - class RawImageData; enum class RawImageType { UINT16, F32 }; @@ -88,7 +86,6 @@ class ImageMetaData { // corners are when the image is rotated 45 degrees in Fuji rotated sensors. uint32_t fujiRotationPos = 0; - iPoint2D subsampling = {1, 1}; std::string make; std::string model; std::string mode; @@ -115,13 +112,9 @@ class RawImageData : public ErrorLog { void checkRowIsInitialized(int row) const; void checkMemIsInitialized() const; void destroyData(); - void blitFrom(const RawImage& src, const iPoint2D& srcPos, + void blitFrom(RawImageData *src, const iPoint2D& srcPos, const iPoint2D& size, const iPoint2D& destPos); [[nodiscard]] rawspeed::RawImageType getDataType() const { return dataType; } - [[nodiscard]] Array2DRef - getU16DataAsUncroppedArray2DRef() const noexcept; - [[nodiscard]] CroppedArray2DRef - getU16DataAsCroppedArray2DRef() const noexcept; [[nodiscard]] uint8_t* getData() const; uint8_t* getData(uint32_t x, @@ -167,13 +160,10 @@ class RawImageData : public ErrorLog { uint32_t mBadPixelMapPitch = 0; bool mDitherScale = true; // Should upscaling be done with dither to minimize banding? - ImageMetaData metadata; - + iPoint2D subsampling = {1, 1}; Mutex mBadPixelMutex; // Mutex for 'mBadPixelPositions, must be used if more // than 1 thread is accessing vector -private: - uint32_t dataRefCount GUARDED_BY(mymutex) = 0; protected: RawImageType dataType; @@ -191,14 +181,19 @@ class RawImageData : public ErrorLog { iPoint2D mOffset; iPoint2D uncropped_dim; std::unique_ptr table; - Mutex mymutex; }; class RawImageDataU16 final : public RawImageData { public: + RawImageDataU16(); + explicit RawImageDataU16(const iPoint2D& dim_, uint32_t cpp_ = 1); void scaleBlackWhite() override; void calculateBlackAreas() override; void setWithLookUp(uint16_t value, uint8_t* dst, uint32_t* random) override; + [[nodiscard]] Array2DRef + getU16DataAsUncroppedArray2DRef() const noexcept; + [[nodiscard]] CroppedArray2DRef + getU16DataAsCroppedArray2DRef() const noexcept; private: void scaleValues_plain(int start_y, int end_y); @@ -209,13 +204,13 @@ class RawImageDataU16 final : public RawImageData { void fixBadPixel(uint32_t x, uint32_t y, int component = 0) override; void doLookup(int start_y, int end_y) override; - RawImageDataU16(); - explicit RawImageDataU16(const iPoint2D& dim_, uint32_t cpp_ = 1); friend class RawImage; }; class RawImageDataFloat final : public RawImageData { public: + RawImageDataFloat(); + explicit RawImageDataFloat(const iPoint2D& dim_, uint32_t cpp_ = 1); void scaleBlackWhite() override; void calculateBlackAreas() override; void setWithLookUp(uint16_t value, uint8_t* dst, uint32_t* random) override; @@ -224,75 +219,40 @@ class RawImageDataFloat final : public RawImageData { void scaleValues(int start_y, int end_y) override; void fixBadPixel(uint32_t x, uint32_t y, int component = 0) override; [[noreturn]] void doLookup(int start_y, int end_y) override; - RawImageDataFloat(); - explicit RawImageDataFloat(const iPoint2D& dim_, uint32_t cpp_ = 1); friend class RawImage; }; - class RawImage { - public: - static RawImage create(RawImageType type = RawImageType::UINT16); - static RawImage create(const iPoint2D& dim, - RawImageType type = RawImageType::UINT16, - uint32_t componentsPerPixel = 1); - RawImageData* operator->() const { return p_; } - RawImageData& operator*() const { return *p_; } - explicit RawImage(RawImageData* p); // p must not be NULL - ~RawImage(); - RawImage(const RawImage& p); - RawImage& operator=(const RawImage& p) noexcept; - RawImage& operator=(RawImage&& p) noexcept; - - RawImageData* get() { return p_; } - private: - RawImageData* p_; // p_ is never NULL - }; - -inline RawImage RawImage::create(RawImageType type) { - switch (type) - { - case RawImageType::UINT16: - return RawImage(new RawImageDataU16()); - case RawImageType::F32: - return RawImage(new RawImageDataFloat()); - default: - writeLog(DEBUG_PRIO::ERROR, "RawImage::create: Unknown Image type!"); - __builtin_unreachable(); - } -} +class RawImage { +public: + using frame_ptr_t = std::shared_ptr; + using storage_t = std::vector; + using const_iterator = storage_t::const_iterator; -inline RawImage RawImage::create(const iPoint2D& dim, RawImageType type, - uint32_t componentsPerPixel) { - switch (type) { - case RawImageType::UINT16: - return RawImage(new RawImageDataU16(dim, componentsPerPixel)); - case RawImageType::F32: - return RawImage(new RawImageDataFloat(dim, componentsPerPixel)); - default: - writeLog(DEBUG_PRIO::ERROR, "RawImage::create: Unknown Image type!"); - __builtin_unreachable(); + [[nodiscard]] std::shared_ptr + get(storage_t::size_type pos) const { + return data.at(pos); } -} + [[nodiscard]] storage_t::size_type numFrames() const { return data.size(); } + void clear() { data.clear(); } + void appendFrame(const std::shared_ptr& frame) { + data.emplace_back(frame); + } + [[nodiscard]] storage_t::size_type size() const { return data.size(); } -inline Array2DRef -RawImageData::getU16DataAsUncroppedArray2DRef() const noexcept { - assert(dataType == RawImageType::UINT16 && - "Attempting to access floating-point buffer as uint16_t."); - assert(data && "Data not yet allocated."); - return {reinterpret_cast(data), cpp * uncropped_dim.x, - uncropped_dim.y, static_cast(pitch / sizeof(uint16_t))}; -} + [[nodiscard]] const_iterator begin() const { return data.begin(); } + [[nodiscard]] const_iterator end() const { return data.end(); } -inline CroppedArray2DRef -RawImageData::getU16DataAsCroppedArray2DRef() const noexcept { - return {getU16DataAsUncroppedArray2DRef(), cpp * mOffset.x, mOffset.y, - cpp * dim.x, dim.y}; -} + ImageMetaData metadata; + +private: + storage_t data; +}; // setWithLookUp will set a single pixel by using the lookup table if supplied, -// You must supply the destination where the value should be written, and a pointer to -// a value that will be used to store a random counter that can be reused between calls. -// this needs to be inline to speed up tight decompressor loops +// You must supply the destination where the value should be written, and a +// pointer to a value that will be used to store a random counter that can be +// reused between calls. this needs to be inline to speed up tight decompressor +// loops inline void RawImageDataU16::setWithLookUp(uint16_t value, uint8_t* dst, uint32_t* random) { auto* dest = reinterpret_cast(dst); @@ -315,8 +275,21 @@ inline void RawImageDataU16::setWithLookUp(uint16_t value, uint8_t* dst, *dest = table->tables[value]; } +inline Array2DRef +RawImageDataU16::getU16DataAsUncroppedArray2DRef() const noexcept { + assert(data && "Data not yet allocated."); + return {reinterpret_cast(data), cpp * uncropped_dim.x, + uncropped_dim.y, static_cast(pitch / sizeof(uint16_t))}; +} + +inline CroppedArray2DRef +RawImageDataU16::getU16DataAsCroppedArray2DRef() const noexcept { + return {getU16DataAsUncroppedArray2DRef(), cpp * mOffset.x, mOffset.y, + cpp * dim.x, dim.y}; +} + class RawImageCurveGuard final { - const RawImage* mRaw; + RawImageData* mRaw; const std::vector& curve; const bool uncorrectedRawValues; @@ -327,21 +300,21 @@ class RawImageCurveGuard final { RawImageCurveGuard& operator=(const RawImageCurveGuard&) noexcept = delete; RawImageCurveGuard& operator=(RawImageCurveGuard&&) noexcept = delete; - RawImageCurveGuard(const RawImage* raw, const std::vector& curve_, + RawImageCurveGuard(RawImageData* raw, const std::vector& curve_, bool uncorrectedRawValues_) : mRaw(raw), curve(curve_), uncorrectedRawValues(uncorrectedRawValues_) { if (uncorrectedRawValues) return; - (*mRaw)->setTable(curve, true); + mRaw->setTable(curve, true); } ~RawImageCurveGuard() { // Set the table, if it should be needed later. if (uncorrectedRawValues) - (*mRaw)->setTable(curve, false); + mRaw->setTable(curve, false); else - (*mRaw)->setTable(nullptr); + mRaw->setTable(nullptr); } }; diff --git a/src/librawspeed/common/RawImageDataFloat.cpp b/src/librawspeed/common/RawImageDataFloat.cpp index ddd9a3413..22bf7884f 100644 --- a/src/librawspeed/common/RawImageDataFloat.cpp +++ b/src/librawspeed/common/RawImageDataFloat.cpp @@ -141,7 +141,7 @@ RawImageDataFloat::RawImageDataFloat() { calculateBlackAreas(); startWorker(RawImageWorker::RawImageWorkerTask::SCALE_VALUES, true); -} + } #if 0 // def WITH_SSE2 diff --git a/src/librawspeed/common/RawImageDataU16.cpp b/src/librawspeed/common/RawImageDataU16.cpp index f8646c3b2..983744022 100644 --- a/src/librawspeed/common/RawImageDataU16.cpp +++ b/src/librawspeed/common/RawImageDataU16.cpp @@ -152,8 +152,8 @@ void RawImageDataU16::scaleBlackWhite() { if (whitePoint >= 65536) whitePoint = m; writeLog(DEBUG_PRIO::INFO, - "ISO:%d, Estimated black:%d, Estimated white: %d", - metadata.isoSpeed, blackLevel, whitePoint); + "Estimated black:%d, Estimated white: %d", + blackLevel, whitePoint); } /* Skip, if not needed */ diff --git a/src/librawspeed/decoders/ArwDecoder.cpp b/src/librawspeed/decoders/ArwDecoder.cpp index b1df58d70..d3bad9f52 100644 --- a/src/librawspeed/decoders/ArwDecoder.cpp +++ b/src/librawspeed/decoders/ArwDecoder.cpp @@ -57,7 +57,7 @@ bool ArwDecoder::isAppropriateDecoder(const TiffRootIFD* rootIFD, return make == "SONY"; } -RawImage ArwDecoder::decodeSRF(const TiffIFD* raw) { +void ArwDecoder::decodeSRF(const TiffIFD* raw) { raw = mRootIFD->getIFDWithTag(TiffTag::IMAGEWIDTH); uint32_t width = raw->getEntry(TiffTag::IMAGEWIDTH)->getU32(); @@ -95,17 +95,16 @@ RawImage ArwDecoder::decodeSRF(const TiffIFD* raw) { Buffer di(std::move(image_decoded), len); // And now decode as a normal 16bit raw - mRaw->dim = iPoint2D(width, height); - mRaw->createData(); + mRaw.get(0)->dim = iPoint2D(width, height); + mRaw.get(0)->createData(); UncompressedDecompressor u( - ByteStream(DataBuffer(di.getSubView(0, len), Endianness::little)), mRaw); + ByteStream(DataBuffer(di.getSubView(0, len), Endianness::little)), + mRaw.get(0).get()); u.decodeRawUnpacked<16, Endianness::big>(width, height); - - return mRaw; } -RawImage ArwDecoder::decodeRawInternal() { +void ArwDecoder::decodeRawInternal() { const TiffIFD* raw = nullptr; vector data = mRootIFD->getIFDsWithTag(TiffTag::STRIPOFFSETS); @@ -120,18 +119,20 @@ RawImage ArwDecoder::decodeRawInternal() { uint32_t width = 3881; uint32_t height = 2608; - mRaw->dim = iPoint2D(width, height); + mRaw.get(0)->dim = iPoint2D(width, height); ByteStream input(DataBuffer(mFile.getSubView(off), Endianness::little)); - SonyArw1Decompressor a(mRaw); - mRaw->createData(); + SonyArw1Decompressor a(mRaw.get(0).get()); + mRaw.get(0)->createData(); a.decompress(input); - return mRaw; + return; } - if (hints.has("srf_format")) - return decodeSRF(raw); + if (hints.has("srf_format")) { + decodeSRF(raw); + return; + } ThrowRDE("No image data found"); } @@ -140,7 +141,7 @@ RawImage ArwDecoder::decodeRawInternal() { int compression = raw->getEntry(TiffTag::COMPRESSION)->getU32(); if (1 == compression) { DecodeUncompressed(raw); - return mRaw; + return; } if (32767 != compression) @@ -176,7 +177,7 @@ RawImage ArwDecoder::decodeRawInternal() { // to detect it this way in the future. data = mRootIFD->getIFDsWithTag(TiffTag::MAKE); if (data.size() > 1) { - for (auto &i : data) { + for (auto& i : data) { std::string make = i->getEntry(TiffTag::MAKE)->getString(); /* Check for maker "SONY" without spaces */ if (make == "SONY") @@ -192,23 +193,23 @@ RawImage ArwDecoder::decodeRawInternal() { if (arw1) height += 8; - mRaw->dim = iPoint2D(width, height); + mRaw.get(0)->dim = iPoint2D(width, height); std::vector curve(0x4001); const TiffEntry* c = raw->getEntry(TiffTag::SONY_CURVE); std::array sony_curve = {{0, 0, 0, 0, 0, 4095}}; for (uint32_t i = 0; i < 4; i++) - sony_curve[i+1] = (c->getU16(i) >> 2) & 0xfff; + sony_curve[i + 1] = (c->getU16(i) >> 2) & 0xfff; for (uint32_t i = 0; i < 0x4001; i++) curve[i] = i; for (uint32_t i = 0; i < 5; i++) for (uint32_t j = sony_curve[i] + 1; j <= sony_curve[i + 1]; j++) - curve[j] = curve[j-1] + (1 << i); + curve[j] = curve[j - 1] + (1 << i); - RawImageCurveGuard curveHandler(&mRaw, curve, uncorrectedRawValues); + RawImageCurveGuard curveHandler(mRaw.get(0).get(), curve, uncorrectedRawValues); uint32_t c2 = counts->getU32(); uint32_t off = offsets->getU32(); @@ -222,13 +223,11 @@ RawImage ArwDecoder::decodeRawInternal() { ByteStream input(DataBuffer(mFile.getSubView(off, c2), Endianness::little)); if (arw1) { - SonyArw1Decompressor a(mRaw); - mRaw->createData(); + SonyArw1Decompressor a(mRaw.get(0).get()); + mRaw.get(0)->createData(); a.decompress(input); } else DecodeARW2(input, width, height, bitPerPixel); - - return mRaw; } void ArwDecoder::DecodeUncompressed(const TiffIFD* raw) const { @@ -237,7 +236,7 @@ void ArwDecoder::DecodeUncompressed(const TiffIFD* raw) const { uint32_t off = raw->getEntry(TiffTag::STRIPOFFSETS)->getU32(); uint32_t c2 = raw->getEntry(TiffTag::STRIPBYTECOUNTS)->getU32(); - mRaw->dim = iPoint2D(width, height); + mRaw.get(0)->dim = iPoint2D(width, height); if (width == 0 || height == 0 || width > 9600 || height > 6376) ThrowRDE("Unexpected image dimensions found: (%u; %u)", width, height); @@ -247,10 +246,10 @@ void ArwDecoder::DecodeUncompressed(const TiffIFD* raw) const { const Buffer buf(mFile.getSubView(off, c2)); - mRaw->createData(); + mRaw.get(0)->createData(); UncompressedDecompressor u(ByteStream(DataBuffer(buf, Endianness::little)), - mRaw); + mRaw.get(0).get()); if (hints.has("sr2_format")) u.decodeRawUnpacked<14, Endianness::big>(width, height); @@ -262,16 +261,16 @@ void ArwDecoder::DecodeARW2(const ByteStream& input, uint32_t w, uint32_t h, uint32_t bpp) { if (bpp == 8) { - SonyArw2Decompressor a2(mRaw, input); - mRaw->createData(); + SonyArw2Decompressor a2(mRaw.get(0).get(), input); + mRaw.get(0)->createData(); a2.decompress(); return; } // End bpp = 8 if (bpp == 12) { - mRaw->createData(); + mRaw.get(0)->createData(); UncompressedDecompressor u( - ByteStream(DataBuffer(input, Endianness::little)), mRaw); + ByteStream(DataBuffer(input, Endianness::little)), mRaw.get(0).get()); u.decode12BitRaw(w, h); // Shift scales, since black and white are the same as compressed precision @@ -281,7 +280,7 @@ void ArwDecoder::DecodeARW2(const ByteStream& input, uint32_t w, uint32_t h, ThrowRDE("Unsupported bit depth"); } -void ArwDecoder::ParseA100WB() const { +void ArwDecoder::ParseA100WB() { if (!mRootIFD->hasEntryRecursive(TiffTag::DNGPRIVATEDATA)) return; @@ -327,9 +326,9 @@ void ArwDecoder::ParseA100WB() const { for (auto& coeff : tmp) coeff = bs.getU16(); - mRaw->metadata.wbCoeffs[0] = static_cast(tmp[0]); - mRaw->metadata.wbCoeffs[1] = static_cast(tmp[1]); - mRaw->metadata.wbCoeffs[2] = static_cast(tmp[3]); + mRaw.metadata.wbCoeffs[0] = static_cast(tmp[0]); + mRaw.metadata.wbCoeffs[1] = static_cast(tmp[1]); + mRaw.metadata.wbCoeffs[2] = static_cast(tmp[3]); // only need this one block, no need to process any further break; @@ -340,7 +339,7 @@ void ArwDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { //Default int iso = 0; - mRaw->cfa.setCFA(iPoint2D(2, 2), CFAColor::RED, CFAColor::GREEN, + mRaw.get(0)->cfa.setCFA(iPoint2D(2, 2), CFAColor::RED, CFAColor::GREEN, CFAColor::GREEN, CFAColor::BLUE); if (mRootIFD->hasEntryRecursive(TiffTag::ISOSPEEDRATINGS)) @@ -349,8 +348,8 @@ void ArwDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { auto id = mRootIFD->getID(); setMetaData(meta, id, "", iso); - mRaw->whitePoint >>= mShiftDownScale; - mRaw->blackLevel >>= mShiftDownScale; + mRaw.get(0)->whitePoint >>= mShiftDownScale; + mRaw.get(0)->blackLevel >>= mShiftDownScale; // Set the whitebalance try { @@ -360,7 +359,7 @@ void ArwDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { GetWB(); } } catch (const RawspeedException& e) { - mRaw->setError(e.what()); + mRaw.get(0)->setError(e.what()); // We caught an exception reading WB, just ignore it } } @@ -402,7 +401,7 @@ void ArwDecoder::SonyDecrypt(const uint32_t* ibuf, uint32_t* obuf, uint32_t len, } } -void ArwDecoder::GetWB() const { +void ArwDecoder::GetWB() { // Set the whitebalance for all the modern ARW formats (everything after A100) if (mRootIFD->hasEntryRecursive(TiffTag::DNGPRIVATEDATA)) { NORangesSet ifds_undecoded; @@ -455,16 +454,16 @@ void ArwDecoder::GetWB() const { const TiffEntry* wb = encryptedIFD.getEntry(TiffTag::SONYGRBGLEVELS); if (wb->count != 4) ThrowRDE("WB has %d entries instead of 4", wb->count); - mRaw->metadata.wbCoeffs[0] = wb->getFloat(1); - mRaw->metadata.wbCoeffs[1] = wb->getFloat(0); - mRaw->metadata.wbCoeffs[2] = wb->getFloat(2); + mRaw.metadata.wbCoeffs[0] = wb->getFloat(1); + mRaw.metadata.wbCoeffs[1] = wb->getFloat(0); + mRaw.metadata.wbCoeffs[2] = wb->getFloat(2); } else if (encryptedIFD.hasEntry(TiffTag::SONYRGGBLEVELS)) { const TiffEntry* wb = encryptedIFD.getEntry(TiffTag::SONYRGGBLEVELS); if (wb->count != 4) ThrowRDE("WB has %d entries instead of 4", wb->count); - mRaw->metadata.wbCoeffs[0] = wb->getFloat(0); - mRaw->metadata.wbCoeffs[1] = wb->getFloat(1); - mRaw->metadata.wbCoeffs[2] = wb->getFloat(3); + mRaw.metadata.wbCoeffs[0] = wb->getFloat(0); + mRaw.metadata.wbCoeffs[1] = wb->getFloat(1); + mRaw.metadata.wbCoeffs[2] = wb->getFloat(3); } } } diff --git a/src/librawspeed/decoders/ArwDecoder.h b/src/librawspeed/decoders/ArwDecoder.h index 0528a5493..11e39edb6 100644 --- a/src/librawspeed/decoders/ArwDecoder.h +++ b/src/librawspeed/decoders/ArwDecoder.h @@ -42,20 +42,20 @@ class ArwDecoder final : public AbstractTiffDecoder ArwDecoder(TiffRootIFDOwner&& root, const Buffer& file) : AbstractTiffDecoder(std::move(root), file) {} - RawImage decodeRawInternal() override; + void decodeRawInternal() override; void decodeMetaDataInternal(const CameraMetaData* meta) override; private: - void ParseA100WB() const; + void ParseA100WB(); [[nodiscard]] int getDecoderVersion() const override { return 1; } - RawImage decodeSRF(const TiffIFD* raw); + void decodeSRF(const TiffIFD* raw); void DecodeARW2(const ByteStream& input, uint32_t w, uint32_t h, uint32_t bpp); void DecodeUncompressed(const TiffIFD* raw) const; static void SonyDecrypt(const uint32_t* ibuf, uint32_t* obuf, uint32_t len, uint32_t key); - void GetWB() const; + void GetWB(); ByteStream in; int mShiftDownScale = 0; }; diff --git a/src/librawspeed/decoders/Cr2Decoder.cpp b/src/librawspeed/decoders/Cr2Decoder.cpp index fd7646157..7902841bf 100644 --- a/src/librawspeed/decoders/Cr2Decoder.cpp +++ b/src/librawspeed/decoders/Cr2Decoder.cpp @@ -56,7 +56,7 @@ bool Cr2Decoder::isAppropriateDecoder(const TiffRootIFD* rootIFD, (make == "Kodak" && (model == "DCS520C" || model == "DCS560C")); } -RawImage Cr2Decoder::decodeOldFormat() { +void Cr2Decoder::decodeOldFormat() { uint32_t offset = 0; if (mRootIFD->getEntryRecursive(TiffTag::CANON_RAW_DATA_OFFSET)) { offset = @@ -77,18 +77,18 @@ RawImage Cr2Decoder::decodeOldFormat() { // some old models (1D/1DS/D2000C) encode two lines as one // see: FIX_CANON_HALF_HEIGHT_DOUBLE_WIDTH - if (width > 2*height) { + if (width > 2 * height) { height *= 2; width /= 2; } width *= 2; // components - mRaw->dim = {width, height}; + mRaw.get(0)->dim = {width, height}; const ByteStream bs(DataBuffer(mFile.getSubView(offset), Endianness::little)); - Cr2Decompressor l(bs, mRaw); - mRaw->createData(); + Cr2Decompressor l(bs, mRaw.get(0).get()); + mRaw.get(0)->createData(); Cr2Slicing slicing(/*numSlices=*/1, /*sliceWidth=don't care*/ 0, /*lastSliceWidth=*/width); @@ -99,19 +99,17 @@ RawImage Cr2Decoder::decodeOldFormat() { mRootIFD->getEntryRecursive(static_cast(0x123)); curve && curve->type == TiffDataType::SHORT && curve->count == 4096) { auto table = curve->getU16Array(curve->count); - RawImageCurveGuard curveHandler(&mRaw, table, uncorrectedRawValues); + RawImageCurveGuard curveHandler(mRaw.get(0).get(), table, uncorrectedRawValues); // Apply table if (!uncorrectedRawValues) - mRaw->sixteenBitLookup(); + mRaw.get(0)->sixteenBitLookup(); } - - return mRaw; } // for technical details about Cr2 mRAW/sRAW, see http://lclevy.free.fr/cr2/ -RawImage Cr2Decoder::decodeNewFormat() { +void Cr2Decoder::decodeNewFormat() { const TiffEntry* sensorInfoE = mRootIFD->getEntryRecursive(TiffTag::CANON_SENSOR_INFO); if (!sensorInfoE) @@ -122,25 +120,25 @@ RawImage Cr2Decoder::decodeNewFormat() { if (isSubSampled() != (getSubSampling() != iPoint2D{1, 1})) ThrowTPE("Subsampling sanity check failed"); - mRaw->dim = {sensorInfoE->getU16(1), sensorInfoE->getU16(2)}; - mRaw->setCpp(1); - mRaw->isCFA = !isSubSampled(); + mRaw.get(0)->dim = {sensorInfoE->getU16(1), sensorInfoE->getU16(2)}; + mRaw.get(0)->setCpp(1); + mRaw.get(0)->isCFA = !isSubSampled(); if (isSubSampled()) { - iPoint2D& subSampling = mRaw->metadata.subsampling; + iPoint2D& subSampling = mRaw.get(0)->subsampling; subSampling = getSubSampling(); if (!(subSampling.x > 1 || subSampling.y > 1)) ThrowRDE("RAW is expected to be subsampled, but it's not"); - if (mRaw->dim.x % subSampling.x != 0) + if (mRaw.get(0)->dim.x % subSampling.x != 0) ThrowRDE("Raw width is not a multiple of horizontal subsampling factor"); - mRaw->dim.x /= subSampling.x; + mRaw.get(0)->dim.x /= subSampling.x; - if (mRaw->dim.y % subSampling.y != 0) + if (mRaw.get(0)->dim.y % subSampling.y != 0) ThrowRDE("Raw height is not a multiple of vertical subsampling factor"); - mRaw->dim.y /= subSampling.y; + mRaw.get(0)->dim.y /= subSampling.y; - mRaw->dim.x *= 2 + subSampling.x * subSampling.y; + mRaw.get(0)->dim.x *= 2 + subSampling.x * subSampling.y; } const TiffIFD* raw = mRootIFD->getSubIFDs()[3].get(); @@ -184,23 +182,21 @@ RawImage Cr2Decoder::decodeNewFormat() { const ByteStream bs( DataBuffer(mFile.getSubView(offset, count), Endianness::little)); - Cr2Decompressor d(bs, mRaw); - mRaw->createData(); + Cr2Decompressor d(bs, mRaw.get(0).get()); + mRaw.get(0)->createData(); d.decode(slicing); - assert(getSubSampling() == mRaw->metadata.subsampling); + assert(getSubSampling() == mRaw.get(0)->subsampling); - if (mRaw->metadata.subsampling.x > 1 || mRaw->metadata.subsampling.y > 1) + if (mRaw.get(0)->subsampling.x > 1 || mRaw.get(0)->subsampling.y > 1) sRawInterpolate(); - - return mRaw; } -RawImage Cr2Decoder::decodeRawInternal() { +void Cr2Decoder::decodeRawInternal() { if (mRootIFD->getSubIFDs().size() < 4) - return decodeOldFormat(); + decodeOldFormat(); else // NOLINT ok, here it make sense - return decodeNewFormat(); + decodeNewFormat(); } void Cr2Decoder::checkSupportInternal(const CameraMetaData* meta) { @@ -216,15 +212,15 @@ void Cr2Decoder::checkSupportInternal(const CameraMetaData* meta) { void Cr2Decoder::decodeMetaDataInternal(const CameraMetaData* meta) { int iso = 0; - mRaw->cfa.setCFA(iPoint2D(2, 2), CFAColor::RED, CFAColor::GREEN, + mRaw.get(0)->cfa.setCFA(iPoint2D(2, 2), CFAColor::RED, CFAColor::GREEN, CFAColor::GREEN, CFAColor::BLUE); std::string mode; - if (mRaw->metadata.subsampling.y == 2 && mRaw->metadata.subsampling.x == 2) + if (mRaw.get(0)->subsampling.y == 2 && mRaw.get(0)->subsampling.x == 2) mode = "sRaw1"; - if (mRaw->metadata.subsampling.y == 1 && mRaw->metadata.subsampling.x == 2) + if (mRaw.get(0)->subsampling.y == 1 && mRaw.get(0)->subsampling.x == 2) mode = "sRaw2"; if (mRootIFD->hasEntryRecursive(TiffTag::ISOSPEEDRATINGS)) @@ -247,9 +243,9 @@ void Cr2Decoder::decodeMetaDataInternal(const CameraMetaData* meta) { int offset = hints.get("wb_offset", 126); offset /= 2; - mRaw->metadata.wbCoeffs[0] = static_cast(wb->getU16(offset + 0)); - mRaw->metadata.wbCoeffs[1] = static_cast(wb->getU16(offset + 1)); - mRaw->metadata.wbCoeffs[2] = static_cast(wb->getU16(offset + 3)); + mRaw.metadata.wbCoeffs[0] = static_cast(wb->getU16(offset + 0)); + mRaw.metadata.wbCoeffs[1] = static_cast(wb->getU16(offset + 1)); + mRaw.metadata.wbCoeffs[2] = static_cast(wb->getU16(offset + 3)); } else { if (mRootIFD->hasEntryRecursive(TiffTag::CANONSHOTINFO) && mRootIFD->hasEntryRecursive(TiffTag::CANONPOWERSHOTG9WB)) { @@ -262,27 +258,27 @@ void Cr2Decoder::decodeMetaDataInternal(const CameraMetaData* meta) { int wb_offset = (wb_index < 18) ? "012347800000005896"[wb_index]-'0' : 0; wb_offset = wb_offset*8 + 2; - mRaw->metadata.wbCoeffs[0] = + mRaw.metadata.wbCoeffs[0] = static_cast(g9_wb->getU32(wb_offset + 1)); - mRaw->metadata.wbCoeffs[1] = + mRaw.metadata.wbCoeffs[1] = (static_cast(g9_wb->getU32(wb_offset + 0)) + static_cast(g9_wb->getU32(wb_offset + 3))) / 2.0F; - mRaw->metadata.wbCoeffs[2] = + mRaw.metadata.wbCoeffs[2] = static_cast(g9_wb->getU32(wb_offset + 2)); } else if (mRootIFD->hasEntryRecursive(static_cast(0xa4))) { // WB for the old 1D and 1DS const TiffEntry* wb = mRootIFD->getEntryRecursive(static_cast(0xa4)); if (wb->count >= 3) { - mRaw->metadata.wbCoeffs[0] = wb->getFloat(0); - mRaw->metadata.wbCoeffs[1] = wb->getFloat(1); - mRaw->metadata.wbCoeffs[2] = wb->getFloat(2); + mRaw.metadata.wbCoeffs[0] = wb->getFloat(0); + mRaw.metadata.wbCoeffs[1] = wb->getFloat(1); + mRaw.metadata.wbCoeffs[2] = wb->getFloat(2); } } } } catch (const RawspeedException& e) { - mRaw->setError(e.what()); + mRaw.get(0)->setError(e.what()); // We caught an exception reading WB, just ignore it } setMetaData(meta, mode, iso); @@ -322,7 +318,7 @@ iPoint2D Cr2Decoder::getSubSampling() const { int Cr2Decoder::getHue() const { if (hints.has("old_sraw_hue")) - return (mRaw->metadata.subsampling.y * mRaw->metadata.subsampling.x); + return (mRaw.get(0)->subsampling.y * mRaw.get(0)->subsampling.x); if (!mRootIFD->hasEntryRecursive(static_cast(0x10))) { return 0; @@ -331,9 +327,9 @@ int Cr2Decoder::getHue() const { mRootIFD->getEntryRecursive(static_cast(0x10))->getU32(); model_id >= 0x80000281 || model_id == 0x80000218 || (hints.has("force_new_sraw_hue"))) - return ((mRaw->metadata.subsampling.y * mRaw->metadata.subsampling.x) - 1) >> 1; + return ((mRaw.get(0)->subsampling.y * mRaw.get(0)->subsampling.x) - 1) >> 1; - return (mRaw->metadata.subsampling.y * mRaw->metadata.subsampling.x); + return (mRaw.get(0)->subsampling.y * mRaw.get(0)->subsampling.x); } // Interpolate and convert sRaw data. @@ -360,22 +356,27 @@ void Cr2Decoder::sRawInterpolate() { 1024.0F / (static_cast(sraw_coeffs[2]) / 1024.0F)); } - mRaw->checkMemIsInitialized(); - RawImage subsampledRaw = mRaw; + mRaw.get(0)->checkMemIsInitialized(); + auto subsampledRaw = mRaw.get(0); int hue = getHue(); iPoint2D interpolatedDims = { - subsampledRaw->metadata.subsampling.x * + subsampledRaw->subsampling.x * (subsampledRaw->dim.x / - (2 + subsampledRaw->metadata.subsampling.x * - subsampledRaw->metadata.subsampling.y)), - subsampledRaw->metadata.subsampling.y * subsampledRaw->dim.y}; - - mRaw = RawImage::create(interpolatedDims, RawImageType::UINT16, 3); - mRaw->metadata.subsampling = subsampledRaw->metadata.subsampling; - mRaw->isCFA = false; - - Cr2sRawInterpolator i(mRaw, subsampledRaw->getU16DataAsUncroppedArray2DRef(), + (2 + subsampledRaw->subsampling.x * + subsampledRaw->subsampling.y)), + subsampledRaw->subsampling.y * subsampledRaw->dim.y}; + + mRaw.clear(); + //mRaw = std::make_shared(interpolatedDims, 3); + mRaw.appendFrame(std::make_shared(interpolatedDims,3)); + mRaw.get(0)->subsampling = subsampledRaw->subsampling; + mRaw.get(0)->isCFA = false; + + auto *rawU16 = dynamic_cast(subsampledRaw.get()); + assert(rawU16); + Cr2sRawInterpolator i(mRaw.get(0).get(), + rawU16->getU16DataAsUncroppedArray2DRef(), sraw_coeffs, hue); /* Determine sRaw coefficients */ diff --git a/src/librawspeed/decoders/Cr2Decoder.h b/src/librawspeed/decoders/Cr2Decoder.h index 37990e1fb..b1f39ece1 100644 --- a/src/librawspeed/decoders/Cr2Decoder.h +++ b/src/librawspeed/decoders/Cr2Decoder.h @@ -39,14 +39,14 @@ class Cr2Decoder final : public AbstractTiffDecoder Cr2Decoder(TiffRootIFDOwner&& root, const Buffer& file) : AbstractTiffDecoder(std::move(root), file) {} - RawImage decodeRawInternal() override; + void decodeRawInternal() override; void checkSupportInternal(const CameraMetaData* meta) override; void decodeMetaDataInternal(const CameraMetaData* meta) override; private: [[nodiscard]] int getDecoderVersion() const override { return 9; } - RawImage decodeOldFormat(); - RawImage decodeNewFormat(); + void decodeOldFormat(); + void decodeNewFormat(); void sRawInterpolate(); [[nodiscard]] bool isSubSampled() const; [[nodiscard]] iPoint2D getSubSampling() const; diff --git a/src/librawspeed/decoders/CrwDecoder.cpp b/src/librawspeed/decoders/CrwDecoder.cpp index 9729242d4..0d4cd19f1 100644 --- a/src/librawspeed/decoders/CrwDecoder.cpp +++ b/src/librawspeed/decoders/CrwDecoder.cpp @@ -60,7 +60,7 @@ CrwDecoder::CrwDecoder(std::unique_ptr rootIFD, const Buffer& file) : RawDecoder(file), mRootIFD(std::move(rootIFD)) {} -RawImage CrwDecoder::decodeRawInternal() { +void CrwDecoder::decodeRawInternal() { const CiffEntry* rawData = mRootIFD->getEntry(CiffTag::RAWDATA); if (!rawData) ThrowRDE("Couldn't find the raw data chunk"); @@ -74,7 +74,7 @@ RawImage CrwDecoder::decodeRawInternal() { assert(sensorInfo != nullptr); uint32_t width = sensorInfo->getU16(1); uint32_t height = sensorInfo->getU16(2); - mRaw->dim = iPoint2D(width, height); + mRaw.get(0)->dim = iPoint2D(width, height); const CiffEntry* decTable = mRootIFD->getEntryRecursive(CiffTag::DECODERTABLE); @@ -84,13 +84,11 @@ RawImage CrwDecoder::decodeRawInternal() { assert(decTable != nullptr); uint32_t dec_table = decTable->getU32(); - bool lowbits = ! hints.has("no_decompressed_lowbits"); + bool lowbits = !hints.has("no_decompressed_lowbits"); - CrwDecompressor c(mRaw, dec_table, lowbits, rawData->getData()); - mRaw->createData(); + CrwDecompressor c(mRaw.get(0).get(), dec_table, lowbits, rawData->getData()); + mRaw.get(0)->createData(); c.decompress(); - - return mRaw; } void CrwDecoder::checkSupportInternal(const CameraMetaData* meta) { @@ -126,7 +124,7 @@ float __attribute__((const)) CrwDecoder::canonEv(const int64_t in) { void CrwDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { int iso = 0; - mRaw->cfa.setCFA(iPoint2D(2, 2), CFAColor::RED, CFAColor::GREEN, + mRaw.get(0)->cfa.setCFA(iPoint2D(2, 2), CFAColor::RED, CFAColor::GREEN, CFAColor::GREEN, CFAColor::BLUE); vector data = mRootIFD->getIFDsWithTag(CiffTag::MAKEMODEL); if (data.empty()) @@ -164,11 +162,11 @@ void CrwDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { ThrowRDE("WB coefficient is zero!"); } - mRaw->metadata.wbCoeffs[0] = static_cast(1024.0 / wbMuls[0]); - mRaw->metadata.wbCoeffs[1] = + mRaw.metadata.wbCoeffs[0] = static_cast(1024.0 / wbMuls[0]); + mRaw.metadata.wbCoeffs[1] = static_cast((1024.0 / wbMuls[1]) + (1024.0 / wbMuls[2])) / 2.0F; - mRaw->metadata.wbCoeffs[2] = static_cast(1024.0 / wbMuls[3]); + mRaw.metadata.wbCoeffs[2] = static_cast(1024.0 / wbMuls[3]); } else if (wb->type == CiffDataType::BYTE && wb->count > 768) { // Other G series and S series cameras // correct offset for most cameras @@ -179,11 +177,11 @@ void CrwDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { key[0] = key[1] = 0; offset /= 2; - mRaw->metadata.wbCoeffs[0] = + mRaw.metadata.wbCoeffs[0] = static_cast(wb->getU16(offset + 1) ^ key[1]); - mRaw->metadata.wbCoeffs[1] = + mRaw.metadata.wbCoeffs[1] = static_cast(wb->getU16(offset + 0) ^ key[0]); - mRaw->metadata.wbCoeffs[2] = + mRaw.metadata.wbCoeffs[2] = static_cast(wb->getU16(offset + 2) ^ key[0]); } } @@ -192,17 +190,17 @@ void CrwDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { mRootIFD->getEntryRecursive(static_cast(0x102c)); if (entry->type == CiffDataType::SHORT && entry->getU16() > 512) { // G1/Pro90 CYGM pattern - mRaw->metadata.wbCoeffs[0] = static_cast(entry->getU16(62)); - mRaw->metadata.wbCoeffs[1] = static_cast(entry->getU16(63)); - mRaw->metadata.wbCoeffs[2] = static_cast(entry->getU16(60)); - mRaw->metadata.wbCoeffs[3] = static_cast(entry->getU16(61)); + mRaw.metadata.wbCoeffs[0] = static_cast(entry->getU16(62)); + mRaw.metadata.wbCoeffs[1] = static_cast(entry->getU16(63)); + mRaw.metadata.wbCoeffs[2] = static_cast(entry->getU16(60)); + mRaw.metadata.wbCoeffs[3] = static_cast(entry->getU16(61)); } else if (entry->type == CiffDataType::SHORT && entry->getU16() != 276) { /* G2, S30, S40 */ - mRaw->metadata.wbCoeffs[0] = static_cast(entry->getU16(51)); - mRaw->metadata.wbCoeffs[1] = (static_cast(entry->getU16(50)) + + mRaw.metadata.wbCoeffs[0] = static_cast(entry->getU16(51)); + mRaw.metadata.wbCoeffs[1] = (static_cast(entry->getU16(50)) + static_cast(entry->getU16(53))) / 2.0F; - mRaw->metadata.wbCoeffs[2] = static_cast(entry->getU16(52)); + mRaw.metadata.wbCoeffs[2] = static_cast(entry->getU16(52)); } } if (mRootIFD->hasEntryRecursive(CiffTag::SHOTINFO) && @@ -216,12 +214,12 @@ void CrwDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { if (wb_index > 9) ThrowRDE("Invalid white balance index"); int wb_offset = 1 + ("0134567028"[wb_index]-'0') * 4; - mRaw->metadata.wbCoeffs[0] = wb_data->getU16(wb_offset + 0); - mRaw->metadata.wbCoeffs[1] = wb_data->getU16(wb_offset + 1); - mRaw->metadata.wbCoeffs[2] = wb_data->getU16(wb_offset + 3); + mRaw.metadata.wbCoeffs[0] = wb_data->getU16(wb_offset + 0); + mRaw.metadata.wbCoeffs[1] = wb_data->getU16(wb_offset + 1); + mRaw.metadata.wbCoeffs[2] = wb_data->getU16(wb_offset + 3); } } catch (const RawspeedException& e) { - mRaw->setError(e.what()); + mRaw.get(0)->setError(e.what()); // We caught an exception reading WB, just ignore it } diff --git a/src/librawspeed/decoders/CrwDecoder.h b/src/librawspeed/decoders/CrwDecoder.h index 2ac986609..c847e7ee2 100644 --- a/src/librawspeed/decoders/CrwDecoder.h +++ b/src/librawspeed/decoders/CrwDecoder.h @@ -38,7 +38,7 @@ class CrwDecoder final : public RawDecoder { public: CrwDecoder(std::unique_ptr rootIFD, const Buffer& file); - RawImage decodeRawInternal() override; + void decodeRawInternal() override; void checkSupportInternal(const CameraMetaData* meta) override; void decodeMetaDataInternal(const CameraMetaData* meta) override; static bool isCRW(const Buffer& input); diff --git a/src/librawspeed/decoders/DcrDecoder.cpp b/src/librawspeed/decoders/DcrDecoder.cpp index 1dd9ef555..458dfc394 100644 --- a/src/librawspeed/decoders/DcrDecoder.cpp +++ b/src/librawspeed/decoders/DcrDecoder.cpp @@ -53,7 +53,7 @@ void DcrDecoder::checkImageDimensions() { ThrowRDE("Unexpected image dimensions found: (%u; %u)", width, height); } -RawImage DcrDecoder::decodeRawInternal() { +void DcrDecoder::decodeRawInternal() { SimpleTiffDecoder::prepareForRawDecoding(); ByteStream input(DataBuffer(mFile.getSubView(off), Endianness::little)); @@ -82,7 +82,7 @@ RawImage DcrDecoder::decodeRawInternal() { assert(linearization != nullptr); auto linTable = linearization->getU16Array(linearization->count); - RawImageCurveGuard curveHandler(&mRaw, linTable, uncorrectedRawValues); + RawImageCurveGuard curveHandler(mRaw.get(0).get(), linTable, uncorrectedRawValues); // FIXME: dcraw does all sorts of crazy things besides this to fetch // WB from what appear to be presets and calculate it in weird ways @@ -95,7 +95,7 @@ RawImage DcrDecoder::decodeRawInternal() { const auto mul = blob->getU16(20 + i); if (0 == mul) ThrowRDE("WB coefficient is zero!"); - mRaw->metadata.wbCoeffs[i] = 2048.0F / mul; + mRaw.metadata.wbCoeffs[i] = 2048.0F / mul; } } @@ -110,10 +110,8 @@ RawImage DcrDecoder::decodeRawInternal() { } }(); - KodakDecompressor k(mRaw, input, bps, uncorrectedRawValues); + KodakDecompressor k(mRaw.get(0).get(), input, bps, uncorrectedRawValues); k.decompress(); - - return mRaw; } void DcrDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { diff --git a/src/librawspeed/decoders/DcrDecoder.h b/src/librawspeed/decoders/DcrDecoder.h index 25060af88..88d87b3df 100644 --- a/src/librawspeed/decoders/DcrDecoder.h +++ b/src/librawspeed/decoders/DcrDecoder.h @@ -41,7 +41,7 @@ class DcrDecoder final : public SimpleTiffDecoder { DcrDecoder(TiffRootIFDOwner&& root, const Buffer& file) : SimpleTiffDecoder(std::move(root), file) {} - RawImage decodeRawInternal() override; + void decodeRawInternal() override; void decodeMetaDataInternal(const CameraMetaData* meta) override; private: diff --git a/src/librawspeed/decoders/DcsDecoder.cpp b/src/librawspeed/decoders/DcsDecoder.cpp index 9f566109a..2142894f9 100644 --- a/src/librawspeed/decoders/DcsDecoder.cpp +++ b/src/librawspeed/decoders/DcsDecoder.cpp @@ -51,7 +51,7 @@ void DcsDecoder::checkImageDimensions() { ThrowRDE("Unexpected image dimensions found: (%u; %u)", width, height); } -RawImage DcsDecoder::decodeRawInternal() { +void DcsDecoder::decodeRawInternal() { SimpleTiffDecoder::prepareForRawDecoding(); const TiffEntry* linearization = @@ -63,18 +63,16 @@ RawImage DcsDecoder::decodeRawInternal() { assert(linearization != nullptr); auto table = linearization->getU16Array(256); - RawImageCurveGuard curveHandler(&mRaw, table, uncorrectedRawValues); + RawImageCurveGuard curveHandler(mRaw.get(0).get(), table, uncorrectedRawValues); UncompressedDecompressor u( ByteStream(DataBuffer(mFile.getSubView(off, c2), Endianness::little)), - mRaw); + mRaw.get(0).get()); if (uncorrectedRawValues) u.decode8BitRaw(width, height); else u.decode8BitRaw(width, height); - - return mRaw; } void DcsDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { diff --git a/src/librawspeed/decoders/DcsDecoder.h b/src/librawspeed/decoders/DcsDecoder.h index bf23bc95c..f51e17dce 100644 --- a/src/librawspeed/decoders/DcsDecoder.h +++ b/src/librawspeed/decoders/DcsDecoder.h @@ -41,7 +41,7 @@ class DcsDecoder final : public SimpleTiffDecoder { DcsDecoder(TiffRootIFDOwner&& root, const Buffer& file) : SimpleTiffDecoder(std::move(root), file) {} - RawImage decodeRawInternal() override; + void decodeRawInternal() override; void decodeMetaDataInternal(const CameraMetaData* meta) override; private: diff --git a/src/librawspeed/decoders/DngDecoder.cpp b/src/librawspeed/decoders/DngDecoder.cpp index d2163fb2c..cef780cae 100644 --- a/src/librawspeed/decoders/DngDecoder.cpp +++ b/src/librawspeed/decoders/DngDecoder.cpp @@ -35,21 +35,21 @@ #include "metadata/ColorFilterArray.h" // for CFAColor, ColorFi... #include "parsers/TiffParserException.h" // for ThrowTPE #include "tiff/TiffEntry.h" // for TiffEntry, TiffDataType::LONG -#include "tiff/TiffIFD.h" // for TiffIFD, TiffRootIFD -#include "tiff/TiffTag.h" // for ACTIVEAREA, TILEO... -#include // for any_of -#include // for array, array<>::v... -#include // for assert -#include // for numeric_limits -#include // for map -#include // for unique_ptr -#include // for out_of_range -#include // for string, operator+ -#include // for move, pair -#include // for vector, allocator +#include "tiff/TiffIFD.h" // for TiffIFD, TiffRootIFD +#include "tiff/TiffTag.h" // for ACTIVEAREA, TILEO... +#include // for any_of +#include // for array, array<>::v... +#include // for assert +#include // for numeric_limits +#include // for map +#include // for unique_ptr +#include // for out_of_range +#include // for string, operator+ +#include // for move, pair +#include // for vector, allocator -using std::vector; using std::map; +using std::vector; namespace rawspeed { @@ -68,9 +68,11 @@ DngDecoder::DngDecoder(TiffRootIFDOwner&& rootIFD, const Buffer& file) mRootIFD->getEntryRecursive(TiffTag::DNGVERSION)->getData().getData(4); if (v[0] != 1) - ThrowRDE("Not a supported DNG image format: v%u.%u.%u.%u", (int)v[0], (int)v[1], (int)v[2], (int)v[3]); -// if (v[1] > 4) -// ThrowRDE("Not a supported DNG image format: v%u.%u.%u.%u", (int)v[0], (int)v[1], (int)v[2], (int)v[3]); + ThrowRDE("Not a supported DNG image format: v%u.%u.%u.%u", (int)v[0], + (int)v[1], (int)v[2], (int)v[3]); + // if (v[1] > 4) + // ThrowRDE("Not a supported DNG image format: v%u.%u.%u.%u", (int)v[0], + // (int)v[1], (int)v[2], (int)v[3]); // Prior to v1.1.xxx fix LJPEG encoding bug mFixLjpeg = (v[0] <= 1) && (v[1] < 1); @@ -112,7 +114,7 @@ void DngDecoder::dropUnsuportedChunks(std::vector* data) { #ifdef HAVE_JPEG case 0x884c: // lossy JPEG #endif - // no change, if supported, then is still supported. + // no change, if supported, then is still supported. break; #ifndef HAVE_ZLIB @@ -145,7 +147,7 @@ void DngDecoder::dropUnsuportedChunks(std::vector* data) { } } -void DngDecoder::parseCFA(const TiffIFD* raw) const { +void DngDecoder::parseCFA(const TiffIFD* raw, const RawImage::frame_ptr_t &frame) { // Check if layout is OK, if present if (raw->hasEntry(TiffTag::CFALAYOUT) && @@ -166,7 +168,7 @@ void DngDecoder::parseCFA(const TiffIFD* raw) const { cPat->count); } - mRaw->cfa.setSize(cfaSize); + frame->cfa.setSize(cfaSize); static const map int2enum = { {0, CFAColor::RED}, {1, CFAColor::GREEN}, {2, CFAColor::BLUE}, @@ -185,7 +187,7 @@ void DngDecoder::parseCFA(const TiffIFD* raw) const { ThrowRDE("Unsupported CFA Color: %u", c1); } - mRaw->cfa.setColorAt(iPoint2D(x, y), c2); + frame->cfa.setColorAt(iPoint2D(x, y), c2); } } @@ -206,12 +208,13 @@ void DngDecoder::parseCFA(const TiffIFD* raw) const { })) ThrowRDE("Error decoding active area"); - mRaw->cfa.shiftLeft(aa[1]); - mRaw->cfa.shiftDown(aa[0]); + frame->cfa.shiftLeft(aa[1]); + frame->cfa.shiftDown(aa[0]); } DngTilingDescription -DngDecoder::getTilingDescription(const TiffIFD* raw) const { +DngDecoder::getTilingDescription(const TiffIFD* raw, + const RawImage::frame_ptr_t &frame) { if (raw->hasEntry(TiffTag::TILEOFFSETS)) { const uint32_t tilew = raw->getEntry(TiffTag::TILEWIDTH)->getU32(); const uint32_t tileh = raw->getEntry(TiffTag::TILELENGTH)->getU32(); @@ -220,12 +223,12 @@ DngDecoder::getTilingDescription(const TiffIFD* raw) const { ThrowRDE("Invalid tile size: (%u, %u)", tilew, tileh); assert(tilew > 0); - const uint32_t tilesX = roundUpDivision(mRaw->dim.x, tilew); + const uint32_t tilesX = roundUpDivision(frame->dim.x, tilew); if (!tilesX) ThrowRDE("Zero tiles horizontally"); assert(tileh > 0); - const uint32_t tilesY = roundUpDivision(mRaw->dim.y, tileh); + const uint32_t tilesY = roundUpDivision(frame->dim.y, tileh); if (!tilesY) ThrowRDE("Zero tiles vertically"); @@ -243,7 +246,7 @@ DngDecoder::getTilingDescription(const TiffIFD* raw) const { tilesX, tilesY); } - return {mRaw->dim, tilew, tileh}; + return {frame->dim, tilew, tileh}; } // Strips @@ -258,18 +261,20 @@ DngDecoder::getTilingDescription(const TiffIFD* raw) const { uint32_t yPerSlice = raw->hasEntry(TiffTag::ROWSPERSTRIP) ? raw->getEntry(TiffTag::ROWSPERSTRIP)->getU32() - : mRaw->dim.y; + : frame->dim.y; - if (yPerSlice == 0 || yPerSlice > static_cast(mRaw->dim.y) || - roundUpDivision(mRaw->dim.y, yPerSlice) != counts->count) { + if (yPerSlice == 0 || yPerSlice > static_cast(frame->dim.y) || + roundUpDivision(frame->dim.y, yPerSlice) != counts->count) { ThrowRDE("Invalid y per slice %u or strip count %u (height = %u)", - yPerSlice, counts->count, mRaw->dim.y); + yPerSlice, counts->count, frame->dim.y); } - return {mRaw->dim, static_cast(mRaw->dim.x), yPerSlice}; + return {frame->dim, static_cast(frame->dim.x), yPerSlice}; } -void DngDecoder::decodeData(const TiffIFD* raw, uint32_t sample_format) const { +void DngDecoder::decodeData(const TiffIFD* raw, uint32_t sample_format, + int compression, int bps, + const RawImage::frame_ptr_t &frame) { if (compression == 8 && sample_format != 3) { ThrowRDE("Only float format is supported for " "deflate-compressed data."); @@ -287,11 +292,11 @@ void DngDecoder::decodeData(const TiffIFD* raw, uint32_t sample_format) const { if (raw->hasEntry(TiffTag::WHITELEVEL)) { const TiffEntry* whitelevel = raw->getEntry(TiffTag::WHITELEVEL); if (whitelevel->isInt()) - mRaw->whitePoint = whitelevel->getU32(); + frame->whitePoint = whitelevel->getU32(); } - AbstractDngDecompressor slices(mRaw, getTilingDescription(raw), compression, - mFixLjpeg, bps, predictor); + AbstractDngDecompressor slices(frame.get(), getTilingDescription(raw, frame), + compression, mFixLjpeg, bps, predictor); slices.slices.reserve(slices.dsc.numTiles); @@ -330,12 +335,12 @@ void DngDecoder::decodeData(const TiffIFD* raw, uint32_t sample_format) const { // FIXME: should we sort the tiles, to linearize the input reading? - mRaw->createData(); + frame->createData(); slices.decompress(); } -RawImage DngDecoder::decodeRawInternal() { +void DngDecoder::decodeRawInternal() { vector data = mRootIFD->getIFDsWithTag(TiffTag::COMPRESSION); if (data.empty()) @@ -346,91 +351,92 @@ RawImage DngDecoder::decodeRawInternal() { if (data.empty()) ThrowRDE("No RAW chunks found"); - if (data.size() > 1) { - writeLog(DEBUG_PRIO::EXTRA, - "Multiple RAW chunks found - using first only!"); - } + mRaw.clear(); - const TiffIFD* raw = data[0]; - - bps = raw->getEntry(TiffTag::BITSPERSAMPLE)->getU32(); - if (bps < 1 || bps > 32) - ThrowRDE("Unsupported bit per sample count: %u.", bps); - - uint32_t sample_format = 1; - if (raw->hasEntry(TiffTag::SAMPLEFORMAT)) - sample_format = raw->getEntry(TiffTag::SAMPLEFORMAT)->getU32(); - - compression = raw->getEntry(TiffTag::COMPRESSION)->getU16(); - - switch (sample_format) { - case 1: - mRaw = RawImage::create(RawImageType::UINT16); - break; - case 3: - mRaw = RawImage::create(RawImageType::F32); - break; - default: - ThrowRDE("Only 16 bit unsigned or float point data supported. Sample " - "format %u is not supported.", - sample_format); - } + /// TODO paralelize? + for (const auto* raw : data) { + int bps = raw->getEntry(TiffTag::BITSPERSAMPLE)->getU32(); + if (bps < 1 || bps > 32) + ThrowRDE("Unsupported bit per sample count: %u.", bps); - mRaw->isCFA = - (raw->getEntry(TiffTag::PHOTOMETRICINTERPRETATION)->getU16() == 32803); + uint32_t sample_format = 1; + if (raw->hasEntry(TiffTag::SAMPLEFORMAT)) + sample_format = raw->getEntry(TiffTag::SAMPLEFORMAT)->getU32(); - if (mRaw->isCFA) - writeLog(DEBUG_PRIO::EXTRA, "This is a CFA image"); - else { - writeLog(DEBUG_PRIO::EXTRA, "This is NOT a CFA image"); - } + int compression = raw->getEntry(TiffTag::COMPRESSION)->getU16(); + + std::shared_ptr frame; + + switch (sample_format) { + case 1: + frame = std::make_shared(); + break; + case 3: + frame = std::make_shared(); + break; + default: + ThrowRDE("Only 16 bit unsigned or float point data supported. Sample " + "format %u is not supported.", + sample_format); + } + + frame->isCFA = + (raw->getEntry(TiffTag::PHOTOMETRICINTERPRETATION)->getU16() == 32803); + + if (frame->isCFA) + writeLog(DEBUG_PRIO::EXTRA, "This is a CFA image"); + else { + writeLog(DEBUG_PRIO::EXTRA, "This is NOT a CFA image"); + } - if (sample_format == 1 && bps > 16) - ThrowRDE("Integer precision larger than 16 bits currently not supported."); + if (sample_format == 1 && bps > 16) + ThrowRDE( + "Integer precision larger than 16 bits currently not supported."); - if (sample_format == 3 && bps != 16 && bps != 24 && bps != 32) - ThrowRDE("Floating point must be 16/24/32 bits per sample."); + if (sample_format == 3 && bps != 16 && bps != 24 && bps != 32) + ThrowRDE("Floating point must be 16/24/32 bits per sample."); - mRaw->dim.x = raw->getEntry(TiffTag::IMAGEWIDTH)->getU32(); - mRaw->dim.y = raw->getEntry(TiffTag::IMAGELENGTH)->getU32(); + frame->dim.x = raw->getEntry(TiffTag::IMAGEWIDTH)->getU32(); + frame->dim.y = raw->getEntry(TiffTag::IMAGELENGTH)->getU32(); - if (!mRaw->dim.hasPositiveArea()) - ThrowRDE("Image has zero size"); + if (!frame->dim.hasPositiveArea()) + ThrowRDE("Image has zero size"); #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION - // Yeah, sure, here it would be just dumb to leave this for production :) - if (mRaw->dim.x > 7424 || mRaw->dim.y > 5552) { - ThrowRDE("Unexpected image dimensions found: (%u; %u)", mRaw->dim.x, - mRaw->dim.y); - } + // Yeah, sure, here it would be just dumb to leave this for production :) + if (mRaw.get(0)->dim.x > 7424 || mRaw.get(0)->dim.y > 5552) { + ThrowRDE("Unexpected image dimensions found: (%u; %u)", + mRaw.get(0)->dim.x, mRaw.get(0)->dim.y); + } #endif - if (mRaw->isCFA) - parseCFA(raw); + if (frame->isCFA) + parseCFA(raw, frame); - uint32_t cpp = raw->getEntry(TiffTag::SAMPLESPERPIXEL)->getU32(); + uint32_t cpp = raw->getEntry(TiffTag::SAMPLESPERPIXEL)->getU32(); - if (cpp < 1 || cpp > 4) - ThrowRDE("Unsupported samples per pixel count: %u.", cpp); + if (cpp < 1 || cpp > 4) + ThrowRDE("Unsupported samples per pixel count: %u.", cpp); - mRaw->setCpp(cpp); + frame->setCpp(cpp); - // Now load the image - decodeData(raw, sample_format); + // Now load the image + decodeData(raw, sample_format, compression, bps, frame); - handleMetadata(raw); - - return mRaw; + handleMetadata(raw, compression, bps, frame); + mRaw.appendFrame(frame); + } } -void DngDecoder::handleMetadata(const TiffIFD* raw) { +void DngDecoder::handleMetadata(const TiffIFD* raw, int compression, int bps, + const RawImage::frame_ptr_t &frame) { // Crop if (raw->hasEntry(TiffTag::ACTIVEAREA)) { const TiffEntry* active_area = raw->getEntry(TiffTag::ACTIVEAREA); if (active_area->count != 4) ThrowRDE("active area has %d values instead of 4", active_area->count); - const iRectangle2D fullImage(0, 0, mRaw->dim.x, mRaw->dim.y); + const iRectangle2D fullImage(0, 0, frame->dim.x, frame->dim.y); const auto corners = active_area->getU32Array(4); const iPoint2D topLeft(corners[1], corners[0]); @@ -450,12 +456,12 @@ void DngDecoder::handleMetadata(const TiffIFD* raw) { crop.setBottomRightAbsolute(bottomRight); assert(fullImage.isThisInside(fullImage)); - mRaw->subFrame(crop); + frame->subFrame(crop); } if (raw->hasEntry(TiffTag::DEFAULTCROPORIGIN) && raw->hasEntry(TiffTag::DEFAULTCROPSIZE)) { - iRectangle2D cropped(0, 0, mRaw->dim.x, mRaw->dim.y); + iRectangle2D cropped(0, 0, frame->dim.x, frame->dim.y); const TiffEntry* origin_entry = raw->getEntry(TiffTag::DEFAULTCROPORIGIN); const TiffEntry* size_entry = raw->getEntry(TiffTag::DEFAULTCROPSIZE); @@ -471,7 +477,7 @@ void DngDecoder::handleMetadata(const TiffIFD* raw) { cropped.isPointInsideInclusive(cropOrigin)) cropped = iRectangle2D(cropOrigin, {0, 0}); - cropped.dim = mRaw->dim - cropped.pos; + cropped.dim = frame->dim - cropped.pos; /* Read size (sometimes is rational so use float) */ const auto sz = size_entry->getFloatArray(2); @@ -482,16 +488,16 @@ void DngDecoder::handleMetadata(const TiffIFD* raw) { ThrowRDE("Error decoding default crop size"); if (iPoint2D size(sz[0], sz[1]); - size.isThisInside(mRaw->dim) && - (size + cropped.pos).isThisInside(mRaw->dim)) + size.isThisInside(frame->dim) && + (size + cropped.pos).isThisInside(frame->dim)) cropped.dim = size; if (!cropped.hasPositiveArea()) ThrowRDE("No positive crop area"); - mRaw->subFrame(cropped); + frame->subFrame(cropped); } - if (mRaw->dim.area() <= 0) + if (frame->dim.area() <= 0) ThrowRDE("No image left after crop"); // Apply stage 1 opcodes @@ -500,13 +506,13 @@ void DngDecoder::handleMetadata(const TiffIFD* raw) { const TiffEntry* opcodes = raw->getEntry(TiffTag::OPCODELIST1); // The entry might exist, but it might be empty, which means no opcodes if (opcodes->count > 0) { - DngOpcodes codes(mRaw, opcodes); - codes.applyOpCodes(mRaw); + DngOpcodes codes(frame.get(), opcodes); + codes.applyOpCodes(frame.get()); } } catch (const RawDecoderException& e) { // We push back errors from the opcode parser, since the image may still // be usable - mRaw->setError(e.what()); + frame->setError(e.what()); } } @@ -515,53 +521,53 @@ void DngDecoder::handleMetadata(const TiffIFD* raw) { raw->getEntry(TiffTag::LINEARIZATIONTABLE)->count > 0) { const TiffEntry* lintable = raw->getEntry(TiffTag::LINEARIZATIONTABLE); auto table = lintable->getU16Array(lintable->count); - RawImageCurveGuard curveHandler(&mRaw, table, uncorrectedRawValues); + RawImageCurveGuard curveHandler(frame.get(), table, uncorrectedRawValues); if (!uncorrectedRawValues) - mRaw->sixteenBitLookup(); + frame->sixteenBitLookup(); } - if (mRaw->getDataType() == RawImageType::UINT16) { + if (frame->getDataType() == RawImageType::UINT16) { // Default white level is (2 ** BitsPerSample) - 1 - mRaw->whitePoint = (1UL << bps) - 1UL; - } else if (mRaw->getDataType() == RawImageType::F32) { + frame->whitePoint = (1UL << bps) - 1UL; + } else if (frame->getDataType() == RawImageType::F32) { // Default white level is 1.0f. But we can't represent that here. - mRaw->whitePoint = 65535; + frame->whitePoint = 65535; } if (raw->hasEntry(TiffTag::WHITELEVEL)) { const TiffEntry* whitelevel = raw->getEntry(TiffTag::WHITELEVEL); if (whitelevel->isInt()) - mRaw->whitePoint = whitelevel->getU32(); + frame->whitePoint = whitelevel->getU32(); } // Set black - setBlack(raw); + setBlack(raw, frame); // Apply opcodes to lossy DNG if (compression == 0x884c && !uncorrectedRawValues && raw->hasEntry(TiffTag::OPCODELIST2)) { // We must apply black/white scaling - mRaw->scaleBlackWhite(); + frame->scaleBlackWhite(); // Apply stage 2 codes try { - DngOpcodes codes(mRaw, raw->getEntry(TiffTag::OPCODELIST2)); - codes.applyOpCodes(mRaw); + DngOpcodes codes(frame.get(), raw->getEntry(TiffTag::OPCODELIST2)); + codes.applyOpCodes(frame.get()); } catch (const RawDecoderException& e) { // We push back errors from the opcode parser, since the image may still // be usable - mRaw->setError(e.what()); + frame->setError(e.what()); } - mRaw->blackAreas.clear(); - mRaw->blackLevel = 0; - mRaw->blackLevelSeparate[0] = mRaw->blackLevelSeparate[1] = - mRaw->blackLevelSeparate[2] = mRaw->blackLevelSeparate[3] = 0; - mRaw->whitePoint = 65535; + frame->blackAreas.clear(); + frame->blackLevel = 0; + frame->blackLevelSeparate[0] = frame->blackLevelSeparate[1] = + frame->blackLevelSeparate[2] = frame->blackLevelSeparate[3] = 0; + frame->whitePoint = 65535; } } void DngDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { if (mRootIFD->hasEntryRecursive(TiffTag::ISOSPEEDRATINGS)) - mRaw->metadata.isoSpeed = + mRaw.metadata.isoSpeed = mRootIFD->getEntryRecursive(TiffTag::ISOSPEEDRATINGS)->getU32(); TiffID id; @@ -569,33 +575,33 @@ void DngDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { try { id = mRootIFD->getID(); } catch (const RawspeedException& e) { - mRaw->setError(e.what()); + mRaw.get(0)->setError(e.what()); // not all dngs have MAKE/MODEL entries, // will be dealt with by using UNIQUECAMERAMODEL below } // Set the make and model - mRaw->metadata.make = id.make; - mRaw->metadata.model = id.model; + mRaw.metadata.make = id.make; + mRaw.metadata.model = id.model; const Camera* cam = meta->getCamera(id.make, id.model, "dng"); - if (!cam) //Also look for non-DNG cameras in case it's a converted file + if (!cam) // Also look for non-DNG cameras in case it's a converted file cam = meta->getCamera(id.make, id.model, ""); if (!cam) // Worst case scenario, look for any such camera. cam = meta->getCamera(id.make, id.model); if (cam) { - mRaw->metadata.canonical_make = cam->canonical_make; - mRaw->metadata.canonical_model = cam->canonical_model; - mRaw->metadata.canonical_alias = cam->canonical_alias; - mRaw->metadata.canonical_id = cam->canonical_id; + mRaw.metadata.canonical_make = cam->canonical_make; + mRaw.metadata.canonical_model = cam->canonical_model; + mRaw.metadata.canonical_alias = cam->canonical_alias; + mRaw.metadata.canonical_id = cam->canonical_id; } else { - mRaw->metadata.canonical_make = id.make; - mRaw->metadata.canonical_model = mRaw->metadata.canonical_alias = id.model; + mRaw.metadata.canonical_make = id.make; + mRaw.metadata.canonical_model = mRaw.metadata.canonical_alias = id.model; if (mRootIFD->hasEntryRecursive(TiffTag::UNIQUECAMERAMODEL)) { - mRaw->metadata.canonical_id = + mRaw.metadata.canonical_id = mRootIFD->getEntryRecursive(TiffTag::UNIQUECAMERAMODEL)->getString(); } else { - mRaw->metadata.canonical_id = id.make + " " + id.model; + mRaw.metadata.canonical_id = id.make + " " + id.model; } } @@ -606,21 +612,21 @@ void DngDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { if (as_shot_neutral->count == 3) { for (uint32_t i = 0; i < 3; i++) { float c = as_shot_neutral->getFloat(i); - mRaw->metadata.wbCoeffs[i] = (c > 0.0F) ? (1.0F / c) : 0.0F; + mRaw.metadata.wbCoeffs[i] = (c > 0.0F) ? (1.0F / c) : 0.0F; } } } else if (mRootIFD->hasEntryRecursive(TiffTag::ASSHOTWHITEXY)) { const TiffEntry* as_shot_white_xy = mRootIFD->getEntryRecursive(TiffTag::ASSHOTWHITEXY); if (as_shot_white_xy->count == 2) { - mRaw->metadata.wbCoeffs[0] = as_shot_white_xy->getFloat(0); - mRaw->metadata.wbCoeffs[1] = as_shot_white_xy->getFloat(1); - mRaw->metadata.wbCoeffs[2] = - 1 - mRaw->metadata.wbCoeffs[0] - mRaw->metadata.wbCoeffs[1]; + mRaw.metadata.wbCoeffs[0] = as_shot_white_xy->getFloat(0); + mRaw.metadata.wbCoeffs[1] = as_shot_white_xy->getFloat(1); + mRaw.metadata.wbCoeffs[2] = + 1 - mRaw.metadata.wbCoeffs[0] - mRaw.metadata.wbCoeffs[1]; const std::array d65_white = {{0.950456, 1, 1.088754}}; for (uint32_t i = 0; i < 3; i++) - mRaw->metadata.wbCoeffs[i] /= d65_white[i]; + mRaw.metadata.wbCoeffs[i] /= d65_white[i]; } } @@ -632,16 +638,16 @@ void DngDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { const TiffEntry* mat = mRootIFD->getEntryRecursive(TiffTag::COLORMATRIX2); const auto srat_vals = mat->getSRationalArray(mat->count); bool Success = true; - mRaw->metadata.colorMatrix.reserve(mat->count); + mRaw.metadata.colorMatrix.reserve(mat->count); for (const auto& val : srat_vals) { // FIXME: introduce proper rational type. Success &= val.second == 10'000; if (!Success) break; - mRaw->metadata.colorMatrix.emplace_back(val.first); + mRaw.metadata.colorMatrix.emplace_back(val.first); } if (!Success) - mRaw->metadata.colorMatrix.clear(); + mRaw.metadata.colorMatrix.clear(); } } } @@ -668,7 +674,8 @@ void DngDecoder::checkSupportInternal(const CameraMetaData* meta) { } /* Decodes DNG masked areas into blackareas in the image */ -bool DngDecoder::decodeMaskedAreas(const TiffIFD* raw) const { +bool DngDecoder::decodeMaskedAreas(const TiffIFD* raw, + const RawImage::frame_ptr_t &frame) { const TiffEntry* masked = raw->getEntry(TiffTag::MASKEDAREAS); if (masked->type != TiffDataType::SHORT && masked->type != TiffDataType::LONG) @@ -679,11 +686,11 @@ bool DngDecoder::decodeMaskedAreas(const TiffIFD* raw) const { return false; /* Since we may both have short or int, copy it to int array. */ - auto rects = masked->getU32Array(nrects*4); + auto rects = masked->getU32Array(nrects * 4); - const iRectangle2D fullImage(0, 0, mRaw->getUncroppedDim().x, - mRaw->getUncroppedDim().y); - const iPoint2D top = mRaw->getCropOffset(); + const iRectangle2D fullImage(0, 0, frame->getUncroppedDim().x, + frame->getUncroppedDim().y); + const iPoint2D top = frame->getCropOffset(); for (uint32_t i = 0; i < nrects; i++) { iPoint2D topleft(rects[i * 4UL + 1UL], rects[i * 4UL]); @@ -694,22 +701,25 @@ bool DngDecoder::decodeMaskedAreas(const TiffIFD* raw) const { (topleft < bottomright))) ThrowRDE("Bad masked area."); - // Is this a horizontal box, only add it if it covers the active width of the image - if (topleft.x <= top.x && bottomright.x >= (mRaw->dim.x + top.x)) { - mRaw->blackAreas.emplace_back(topleft.y, bottomright.y - topleft.y, - false); + // Is this a horizontal box, only add it if it covers the active width of + // the image + if (topleft.x <= top.x && bottomright.x >= (frame->dim.x + top.x)) { + frame->blackAreas.emplace_back(topleft.y, bottomright.y - topleft.y, + false); } // Is it a vertical box, only add it if it covers the active height of the // image - else if (topleft.y <= top.y && bottomright.y >= (mRaw->dim.y + top.y)) { - mRaw->blackAreas.emplace_back(topleft.x, bottomright.x - topleft.x, true); + else if (topleft.y <= top.y && bottomright.y >= (frame->dim.y + top.y)) { + frame->blackAreas.emplace_back(topleft.x, bottomright.x - topleft.x, + true); } } - return !mRaw->blackAreas.empty(); + return !frame->blackAreas.empty(); } -bool DngDecoder::decodeBlackLevels(const TiffIFD* raw) const { - iPoint2D blackdim(1,1); +bool DngDecoder::decodeBlackLevels(const TiffIFD* raw, + const RawImage::frame_ptr_t &frame) { + iPoint2D blackdim(1, 1); if (raw->hasEntry(TiffTag::BLACKLEVELREPEATDIM)) { const TiffEntry* bleveldim = raw->getEntry(TiffTag::BLACKLEVELREPEATDIM); if (bleveldim->count != 2) @@ -723,14 +733,14 @@ bool DngDecoder::decodeBlackLevels(const TiffIFD* raw) const { if (!raw->hasEntry(TiffTag::BLACKLEVEL)) return true; - if (mRaw->getCpp() != 1) + if (frame->getCpp() != 1) return false; const TiffEntry* black_entry = raw->getEntry(TiffTag::BLACKLEVEL); if (black_entry->count < blackdim.area()) ThrowRDE("BLACKLEVEL entry is too small"); - using BlackType = decltype(mRaw->blackLevelSeparate)::value_type; + using BlackType = decltype(mRaw.get(0)->blackLevelSeparate)::value_type; if (blackdim.x < 2 || blackdim.y < 2) { // We so not have enough to fill all individually, read a single and copy it @@ -742,7 +752,7 @@ bool DngDecoder::decodeBlackLevels(const TiffIFD* raw) const { for (int y = 0; y < 2; y++) { for (int x = 0; x < 2; x++) - mRaw->blackLevelSeparate[y*2+x] = value; + frame->blackLevelSeparate[y * 2 + x] = value; } } else { for (int y = 0; y < 2; y++) { @@ -753,7 +763,7 @@ bool DngDecoder::decodeBlackLevels(const TiffIFD* raw) const { value > std::numeric_limits::max()) ThrowRDE("Error decoding black level"); - mRaw->blackLevelSeparate[y * 2 + x] = value; + frame->blackLevelSeparate[y * 2 + x] = value; } } } @@ -762,21 +772,21 @@ bool DngDecoder::decodeBlackLevels(const TiffIFD* raw) const { if (raw->hasEntry(TiffTag::BLACKLEVELDELTAV)) { const TiffEntry* blackleveldeltav = raw->getEntry(TiffTag::BLACKLEVELDELTAV); - if (static_cast(blackleveldeltav->count) < mRaw->dim.y) + if (static_cast(blackleveldeltav->count) < frame->dim.y) ThrowRDE("BLACKLEVELDELTAV array is too small"); std::array black_sum = {{}}; - for (int i = 0; i < mRaw->dim.y; i++) - black_sum[i&1] += blackleveldeltav->getFloat(i); + for (int i = 0; i < frame->dim.y; i++) + black_sum[i & 1] += blackleveldeltav->getFloat(i); for (int i = 0; i < 4; i++) { const float value = - black_sum[i >> 1] / static_cast(mRaw->dim.y) * 2.0F; + black_sum[i >> 1] / static_cast(frame->dim.y) * 2.0F; if (value < std::numeric_limits::min() || value > std::numeric_limits::max()) ThrowRDE("Error decoding black level"); - if (__builtin_sadd_overflow(mRaw->blackLevelSeparate[i], value, - &mRaw->blackLevelSeparate[i])) + if (__builtin_sadd_overflow(frame->blackLevelSeparate[i], value, + &frame->blackLevelSeparate[i])) ThrowRDE("Integer overflow when calculating black level"); } } @@ -784,36 +794,36 @@ bool DngDecoder::decodeBlackLevels(const TiffIFD* raw) const { if (raw->hasEntry(TiffTag::BLACKLEVELDELTAH)) { const TiffEntry* blackleveldeltah = raw->getEntry(TiffTag::BLACKLEVELDELTAH); - if (static_cast(blackleveldeltah->count) < mRaw->dim.x) + if (static_cast(blackleveldeltah->count) < frame->dim.x) ThrowRDE("BLACKLEVELDELTAH array is too small"); std::array black_sum = {{}}; - for (int i = 0; i < mRaw->dim.x; i++) - black_sum[i&1] += blackleveldeltah->getFloat(i); + for (int i = 0; i < frame->dim.x; i++) + black_sum[i & 1] += blackleveldeltah->getFloat(i); for (int i = 0; i < 4; i++) { const float value = - black_sum[i & 1] / static_cast(mRaw->dim.x) * 2.0F; + black_sum[i & 1] / static_cast(frame->dim.x) * 2.0F; if (value < std::numeric_limits::min() || value > std::numeric_limits::max()) ThrowRDE("Error decoding black level"); - if (__builtin_sadd_overflow(mRaw->blackLevelSeparate[i], value, - &mRaw->blackLevelSeparate[i])) + if (__builtin_sadd_overflow(frame->blackLevelSeparate[i], value, + &frame->blackLevelSeparate[i])) ThrowRDE("Integer overflow when calculating black level"); } } return true; } -void DngDecoder::setBlack(const TiffIFD* raw) const { +void DngDecoder::setBlack(const TiffIFD* raw, const RawImage::frame_ptr_t &frame) { - if (raw->hasEntry(TiffTag::MASKEDAREAS) && decodeMaskedAreas(raw)) + if (raw->hasEntry(TiffTag::MASKEDAREAS) && decodeMaskedAreas(raw, frame)) return; // Black defaults to 0 - mRaw->blackLevelSeparate.fill(0); + frame->blackLevelSeparate.fill(0); if (raw->hasEntry(TiffTag::BLACKLEVEL)) - decodeBlackLevels(raw); + decodeBlackLevels(raw, frame); } } // namespace rawspeed diff --git a/src/librawspeed/decoders/DngDecoder.h b/src/librawspeed/decoders/DngDecoder.h index 5810f7c5d..5fa5ae5d3 100644 --- a/src/librawspeed/decoders/DngDecoder.h +++ b/src/librawspeed/decoders/DngDecoder.h @@ -34,14 +34,13 @@ class Buffer; struct DngTilingDescription; -class DngDecoder final : public AbstractTiffDecoder -{ +class DngDecoder final : public AbstractTiffDecoder { public: static bool isAppropriateDecoder(const TiffRootIFD* rootIFD, const Buffer& file); DngDecoder(TiffRootIFDOwner&& rootIFD, const Buffer& file); - RawImage decodeRawInternal() override; + void decodeRawInternal() override; void decodeMetaDataInternal(const CameraMetaData* meta) override; void checkSupportInternal(const CameraMetaData* meta) override; @@ -49,16 +48,18 @@ class DngDecoder final : public AbstractTiffDecoder [[nodiscard]] int getDecoderVersion() const override { return 0; } bool mFixLjpeg; static void dropUnsuportedChunks(std::vector* data); - void parseCFA(const TiffIFD* raw) const; - DngTilingDescription getTilingDescription(const TiffIFD* raw) const; - void decodeData(const TiffIFD* raw, uint32_t sample_format) const; - void handleMetadata(const TiffIFD* raw); - bool decodeMaskedAreas(const TiffIFD* raw) const; - bool decodeBlackLevels(const TiffIFD* raw) const; - void setBlack(const TiffIFD* raw) const; - - int bps = -1; - int compression = -1; + static void parseCFA(const TiffIFD* raw, const RawImage::frame_ptr_t &frame); + static DngTilingDescription getTilingDescription(const TiffIFD* raw, + const RawImage::frame_ptr_t &frame); + void decodeData(const TiffIFD* raw, uint32_t sample_format, int compression, + int bps, const RawImage::frame_ptr_t &frame); + void handleMetadata(const TiffIFD* raw, int compression, int bps, + const RawImage::frame_ptr_t &frame); + static bool decodeMaskedAreas(const TiffIFD* raw, + const RawImage::frame_ptr_t &frame); + static bool decodeBlackLevels(const TiffIFD* raw, + const RawImage::frame_ptr_t &frame); + static void setBlack(const TiffIFD* raw, const RawImage::frame_ptr_t &frame); }; } // namespace rawspeed diff --git a/src/librawspeed/decoders/ErfDecoder.cpp b/src/librawspeed/decoders/ErfDecoder.cpp index eac5085c8..a0897af03 100644 --- a/src/librawspeed/decoders/ErfDecoder.cpp +++ b/src/librawspeed/decoders/ErfDecoder.cpp @@ -51,16 +51,14 @@ void ErfDecoder::checkImageDimensions() { ThrowRDE("Unexpected image dimensions found: (%u; %u)", width, height); } -RawImage ErfDecoder::decodeRawInternal() { +void ErfDecoder::decodeRawInternal() { SimpleTiffDecoder::prepareForRawDecoding(); UncompressedDecompressor u( ByteStream(DataBuffer(mFile.getSubView(off, c2), Endianness::little)), - mRaw); + mRaw.get(0).get()); u.decode12BitRaw(width, height); - - return mRaw; } void ErfDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { @@ -70,10 +68,10 @@ void ErfDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { const TiffEntry* wb = mRootIFD->getEntryRecursive(TiffTag::EPSONWB); if (wb->count == 256) { // Magic values taken directly from dcraw - mRaw->metadata.wbCoeffs[0] = static_cast(wb->getU16(24)) * 508.0F * + mRaw.metadata.wbCoeffs[0] = static_cast(wb->getU16(24)) * 508.0F * 1.078F / static_cast(0x10000); - mRaw->metadata.wbCoeffs[1] = 1.0F; - mRaw->metadata.wbCoeffs[2] = static_cast(wb->getU16(25)) * 382.0F * + mRaw.metadata.wbCoeffs[1] = 1.0F; + mRaw.metadata.wbCoeffs[2] = static_cast(wb->getU16(25)) * 382.0F * 1.173F / static_cast(0x10000); } } diff --git a/src/librawspeed/decoders/ErfDecoder.h b/src/librawspeed/decoders/ErfDecoder.h index 55ed81e52..6b99cdfa0 100644 --- a/src/librawspeed/decoders/ErfDecoder.h +++ b/src/librawspeed/decoders/ErfDecoder.h @@ -41,7 +41,7 @@ class ErfDecoder final : public SimpleTiffDecoder { ErfDecoder(TiffRootIFDOwner&& root, const Buffer& file) : SimpleTiffDecoder(std::move(root), file) {} - RawImage decodeRawInternal() override; + void decodeRawInternal() override; void decodeMetaDataInternal(const CameraMetaData* meta) override; private: diff --git a/src/librawspeed/decoders/IiqDecoder.cpp b/src/librawspeed/decoders/IiqDecoder.cpp index d0fcbee1b..6d4a66e65 100644 --- a/src/librawspeed/decoders/IiqDecoder.cpp +++ b/src/librawspeed/decoders/IiqDecoder.cpp @@ -111,7 +111,7 @@ IiqDecoder::computeSripes(const Buffer& raw_data, return slices; } -RawImage IiqDecoder::decodeRawInternal() { +void IiqDecoder::decodeRawInternal() { const Buffer buf(mFile.getSubView(8)); const DataBuffer db(buf, Endianness::little); ByteStream bs(db); @@ -207,19 +207,17 @@ RawImage IiqDecoder::decodeRawInternal() { std::vector strips( computeSripes(raw_data, std::move(offsets), height)); - mRaw->dim = iPoint2D(width, height); + mRaw.get(0)->dim = iPoint2D(width, height); - PhaseOneDecompressor p(mRaw, std::move(strips)); - mRaw->createData(); + PhaseOneDecompressor p(mRaw.get(0).get(), std::move(strips)); + mRaw.get(0)->createData(); p.decompress(); if (correction_meta_data.getSize() != 0 && iiq) CorrectPhaseOneC(correction_meta_data, split_row, split_col); for (int i = 0; i < 3; i++) - mRaw->metadata.wbCoeffs[i] = wb.getFloat(); - - return mRaw; + mRaw.metadata.wbCoeffs[i] = wb.getFloat(); } void IiqDecoder::CorrectPhaseOneC(ByteStream meta_data, uint32_t split_row, @@ -313,7 +311,9 @@ void IiqDecoder::CorrectQuadrantMultipliersCombined(ByteStream data, for (int quadRow = 0; quadRow < 2; quadRow++) { for (int quadCol = 0; quadCol < 2; quadCol++) { - const Array2DRef img(mRaw->getU16DataAsUncroppedArray2DRef()); + auto *rawU16 = dynamic_cast(mRaw.get(0).get()); + assert(rawU16); + const Array2DRef img(rawU16->getU16DataAsUncroppedArray2DRef()); const Spline<> s(control_points[quadRow][quadCol]); const std::vector curve = s.calculateCurve(); @@ -345,18 +345,18 @@ void IiqDecoder::checkSupportInternal(const CameraMetaData* meta) { checkCameraSupported(meta, mRootIFD->getID(), ""); auto id = mRootIFD->getID(); - const Camera* cam = meta->getCamera(id.make, id.model, mRaw->metadata.mode); + const Camera* cam = meta->getCamera(id.make, id.model, mRaw.metadata.mode); if (!cam) ThrowRDE("Couldn't find camera %s %s", id.make.c_str(), id.model.c_str()); - mRaw->cfa = cam->cfa; + mRaw.get(0)->cfa = cam->cfa; } void IiqDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { setMetaData(meta, "", 0); if (black_level) - mRaw->blackLevel = black_level; + mRaw.get(0)->blackLevel = black_level; } void IiqDecoder::correctSensorDefects(ByteStream data) const { @@ -366,7 +366,7 @@ void IiqDecoder::correctSensorDefects(ByteStream data) const { const uint16_t type = data.getU16(); data.skipBytes(2); // Ignore unknown/unused bits. - if (col >= mRaw->dim.x) // Value for col is outside the raw image. + if (col >= mRaw.get(0)->dim.x) // Value for col is outside the raw image. continue; switch (type) { case 131: // bad column @@ -383,16 +383,18 @@ void IiqDecoder::correctSensorDefects(ByteStream data) const { } void IiqDecoder::handleBadPixel(const uint16_t col, const uint16_t row) const { - MutexLocker guard(&mRaw->mBadPixelMutex); - mRaw->mBadPixelPositions.insert(mRaw->mBadPixelPositions.end(), + MutexLocker guard(&mRaw.get(0)->mBadPixelMutex); + mRaw.get(0)->mBadPixelPositions.insert(mRaw.get(0)->mBadPixelPositions.end(), (static_cast(row) << 16) + col); } void IiqDecoder::correctBadColumn(const uint16_t col) const { - const Array2DRef img(mRaw->getU16DataAsUncroppedArray2DRef()); + auto *rawU16 = dynamic_cast(mRaw.get(0).get()); + assert(rawU16); + const Array2DRef img(rawU16->getU16DataAsUncroppedArray2DRef()); - for (int row = 2; row < mRaw->dim.y - 2; row++) { - if (mRaw->cfa.getColorAt(col, row) == CFAColor::GREEN) { + for (int row = 2; row < mRaw.get(0)->dim.y - 2; row++) { + if (mRaw.get(0)->cfa.getColorAt(col, row) == CFAColor::GREEN) { /* Do green pixels. Let's pretend we are in "G" pixel, in the middle: * G=G * BGB diff --git a/src/librawspeed/decoders/IiqDecoder.h b/src/librawspeed/decoders/IiqDecoder.h index f6c777e30..1e9def738 100644 --- a/src/librawspeed/decoders/IiqDecoder.h +++ b/src/librawspeed/decoders/IiqDecoder.h @@ -56,7 +56,7 @@ class IiqDecoder final : public AbstractTiffDecoder { IiqDecoder(TiffRootIFDOwner&& rootIFD, const Buffer& file) : AbstractTiffDecoder(std::move(rootIFD), file) {} - RawImage decodeRawInternal() override; + void decodeRawInternal() override; void checkSupportInternal(const CameraMetaData* meta) override; void decodeMetaDataInternal(const CameraMetaData* meta) override; diff --git a/src/librawspeed/decoders/KdcDecoder.cpp b/src/librawspeed/decoders/KdcDecoder.cpp index b6f847b17..5bf0ca0fe 100644 --- a/src/librawspeed/decoders/KdcDecoder.cpp +++ b/src/librawspeed/decoders/KdcDecoder.cpp @@ -69,7 +69,7 @@ Buffer KdcDecoder::getInputBuffer() const { if (off > mFile.getSize()) ThrowRDE("offset is out of bounds"); - const auto area = mRaw->dim.area(); + const auto area = mRaw.get(0)->dim.area(); if (area > std::numeric_limits::max() / 12) // round down ThrowRDE("Image dimensions are way too large, potential for overflow"); @@ -81,7 +81,7 @@ Buffer KdcDecoder::getInputBuffer() const { return mFile.getSubView(off, bytes); } -RawImage KdcDecoder::decodeRawInternal() { +void KdcDecoder::decodeRawInternal() { if (!mRootIFD->hasEntryRecursive(TiffTag::COMPRESSION)) ThrowRDE("Couldn't find compression setting"); @@ -110,18 +110,16 @@ RawImage KdcDecoder::decodeRawInternal() { uint32_t width = ew->getU32(); uint32_t height = eh->getU32(); - mRaw->dim = iPoint2D(width, height); + mRaw.get(0)->dim = iPoint2D(width, height); const Buffer inputBuffer = KdcDecoder::getInputBuffer(); - mRaw->createData(); + mRaw.get(0)->createData(); UncompressedDecompressor u( - ByteStream(DataBuffer(inputBuffer, Endianness::little)), mRaw); + ByteStream(DataBuffer(inputBuffer, Endianness::little)), mRaw.get(0).get()); u.decode12BitRaw(width, height); - - return mRaw; } void KdcDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { @@ -140,13 +138,13 @@ void KdcDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { if (kodakifd.hasEntryRecursive(TiffTag::KODAK_KDC_WB)) { const TiffEntry* wb = kodakifd.getEntryRecursive(TiffTag::KODAK_KDC_WB); if (wb->count == 3) { - mRaw->metadata.wbCoeffs[0] = wb->getFloat(0); - mRaw->metadata.wbCoeffs[1] = wb->getFloat(1); - mRaw->metadata.wbCoeffs[2] = wb->getFloat(2); + mRaw.metadata.wbCoeffs[0] = wb->getFloat(0); + mRaw.metadata.wbCoeffs[1] = wb->getFloat(1); + mRaw.metadata.wbCoeffs[2] = wb->getFloat(2); } } } catch (const TiffParserException& e) { - mRaw->setError(e.what()); + mRaw.get(0)->setError(e.what()); } } @@ -154,12 +152,12 @@ void KdcDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { if (mRootIFD->hasEntryRecursive(TiffTag::KODAKWB)) { const TiffEntry* wb = mRootIFD->getEntryRecursive(TiffTag::KODAKWB); if (wb->count == 734 || wb->count == 1502) { - mRaw->metadata.wbCoeffs[0] = + mRaw.metadata.wbCoeffs[0] = static_cast(((static_cast(wb->getByte(148))) << 8) | wb->getByte(149)) / 256.0F; - mRaw->metadata.wbCoeffs[1] = 1.0F; - mRaw->metadata.wbCoeffs[2] = + mRaw.metadata.wbCoeffs[1] = 1.0F; + mRaw.metadata.wbCoeffs[2] = static_cast(((static_cast(wb->getByte(150))) << 8) | wb->getByte(151)) / 256.0F; diff --git a/src/librawspeed/decoders/KdcDecoder.h b/src/librawspeed/decoders/KdcDecoder.h index 25795080f..608428e7a 100644 --- a/src/librawspeed/decoders/KdcDecoder.h +++ b/src/librawspeed/decoders/KdcDecoder.h @@ -41,7 +41,7 @@ class KdcDecoder final : public AbstractTiffDecoder KdcDecoder(TiffRootIFDOwner&& root, const Buffer& file) : AbstractTiffDecoder(std::move(root), file) {} - RawImage decodeRawInternal() override; + void decodeRawInternal() override; void decodeMetaDataInternal(const CameraMetaData* meta) override; private: diff --git a/src/librawspeed/decoders/MefDecoder.cpp b/src/librawspeed/decoders/MefDecoder.cpp index 6b56ff41a..ad49c1fe8 100644 --- a/src/librawspeed/decoders/MefDecoder.cpp +++ b/src/librawspeed/decoders/MefDecoder.cpp @@ -44,15 +44,13 @@ void MefDecoder::checkImageDimensions() { ThrowRDE("Unexpected image dimensions found: (%u; %u)", width, height); } -RawImage MefDecoder::decodeRawInternal() { +void MefDecoder::decodeRawInternal() { SimpleTiffDecoder::prepareForRawDecoding(); UncompressedDecompressor u( - ByteStream(DataBuffer(mFile.getSubView(off), Endianness::little)), mRaw); + ByteStream(DataBuffer(mFile.getSubView(off), Endianness::little)), mRaw.get(0).get()); u.decode12BitRaw(width, height); - - return mRaw; } void MefDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { diff --git a/src/librawspeed/decoders/MefDecoder.h b/src/librawspeed/decoders/MefDecoder.h index 5587824a2..19a3bc0ab 100644 --- a/src/librawspeed/decoders/MefDecoder.h +++ b/src/librawspeed/decoders/MefDecoder.h @@ -40,7 +40,7 @@ class MefDecoder final : public SimpleTiffDecoder { MefDecoder(TiffRootIFDOwner&& root, const Buffer& file) : SimpleTiffDecoder(std::move(root), file) {} - RawImage decodeRawInternal() override; + void decodeRawInternal() override; void decodeMetaDataInternal(const CameraMetaData* meta) override; private: diff --git a/src/librawspeed/decoders/MosDecoder.cpp b/src/librawspeed/decoders/MosDecoder.cpp index ec2b822be..7058b7e62 100644 --- a/src/librawspeed/decoders/MosDecoder.cpp +++ b/src/librawspeed/decoders/MosDecoder.cpp @@ -95,10 +95,10 @@ std::string MosDecoder::getXMPTag(std::string_view xmp, std::string_view tag) { return std::string(xmp.substr(start + startlen, end - start - startlen)); } -RawImage MosDecoder::decodeRawInternal() { +void MosDecoder::decodeRawInternal() { uint32_t off = 0; - const TiffIFD *raw = nullptr; + const TiffIFD* raw = nullptr; if (mRootIFD->hasEntryRecursive(TiffTag::TILEOFFSETS)) { raw = mRootIFD->getIFDWithTag(TiffTag::TILEOFFSETS); @@ -115,14 +115,14 @@ RawImage MosDecoder::decodeRawInternal() { if (width == 0 || height == 0 || width > 10328 || height > 7760) ThrowRDE("Unexpected image dimensions found: (%u; %u)", width, height); - mRaw->dim = iPoint2D(width, height); - mRaw->createData(); + mRaw.get(0)->dim = iPoint2D(width, height); + mRaw.get(0)->createData(); const ByteStream bs(DataBuffer(mFile.getSubView(off), Endianness::little)); if (bs.getRemainSize() == 0) ThrowRDE("Input buffer is empty"); - UncompressedDecompressor u(bs, mRaw); + UncompressedDecompressor u(bs, mRaw.get(0).get()); if (int compression = raw->getEntry(TiffTag::COMPRESSION)->getU32(); 1 == compression) { @@ -139,8 +139,6 @@ RawImage MosDecoder::decodeRawInternal() { // l.startDecoder(off, mFile.getSize()-off, 0, 0); } else ThrowRDE("Unsupported compression: %d", compression); - - return mRaw; } void MosDecoder::checkSupportInternal(const CameraMetaData* meta) { @@ -171,9 +169,9 @@ void MosDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { iss >> tmp[0] >> tmp[1] >> tmp[2] >> tmp[3]; if (!iss.fail() && tmp[0] > 0 && tmp[1] > 0 && tmp[2] > 0 && tmp[3] > 0) { - mRaw->metadata.wbCoeffs[0] = static_cast(tmp[0]) / tmp[1]; - mRaw->metadata.wbCoeffs[1] = static_cast(tmp[0]) / tmp[2]; - mRaw->metadata.wbCoeffs[2] = static_cast(tmp[0]) / tmp[3]; + mRaw.metadata.wbCoeffs[0] = static_cast(tmp[0]) / tmp[1]; + mRaw.metadata.wbCoeffs[1] = static_cast(tmp[0]) / tmp[2]; + mRaw.metadata.wbCoeffs[2] = static_cast(tmp[0]) / tmp[3]; } break; } diff --git a/src/librawspeed/decoders/MosDecoder.h b/src/librawspeed/decoders/MosDecoder.h index f4851611f..240d79c5b 100644 --- a/src/librawspeed/decoders/MosDecoder.h +++ b/src/librawspeed/decoders/MosDecoder.h @@ -38,7 +38,7 @@ class MosDecoder final : public AbstractTiffDecoder const Buffer& file); MosDecoder(TiffRootIFDOwner&& rootIFD, const Buffer& file); - RawImage decodeRawInternal() override; + void decodeRawInternal() override; void checkSupportInternal(const CameraMetaData* meta) override; void decodeMetaDataInternal(const CameraMetaData* meta) override; diff --git a/src/librawspeed/decoders/MrwDecoder.cpp b/src/librawspeed/decoders/MrwDecoder.cpp index 47c11ba42..f55388938 100644 --- a/src/librawspeed/decoders/MrwDecoder.cpp +++ b/src/librawspeed/decoders/MrwDecoder.cpp @@ -151,20 +151,18 @@ void MrwDecoder::parseHeader() { imageData = db.getSubView(bs.getPosition(), imageBits / 8); } -RawImage MrwDecoder::decodeRawInternal() { - mRaw->dim = iPoint2D(raw_width, raw_height); - mRaw->createData(); +void MrwDecoder::decodeRawInternal() { + mRaw.get(0)->dim = iPoint2D(raw_width, raw_height); + mRaw.get(0)->createData(); DataBuffer db(imageData, Endianness::big); ByteStream bs(db); - UncompressedDecompressor u(bs, mRaw); + UncompressedDecompressor u(bs, mRaw.get(0).get()); if (packed) u.decode12BitRaw(raw_width, raw_height); else u.decodeRawUnpacked<12, Endianness::big>(raw_width, raw_height); - - return mRaw; } void MrwDecoder::checkSupportInternal(const CameraMetaData* meta) { @@ -186,13 +184,13 @@ void MrwDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { setMetaData(meta, id.make, id.model, "", iso); if (hints.has("swapped_wb")) { - mRaw->metadata.wbCoeffs[0] = wb_coeffs[2]; - mRaw->metadata.wbCoeffs[1] = wb_coeffs[0]; - mRaw->metadata.wbCoeffs[2] = wb_coeffs[1]; + mRaw.metadata.wbCoeffs[0] = wb_coeffs[2]; + mRaw.metadata.wbCoeffs[1] = wb_coeffs[0]; + mRaw.metadata.wbCoeffs[2] = wb_coeffs[1]; } else { - mRaw->metadata.wbCoeffs[0] = wb_coeffs[0]; - mRaw->metadata.wbCoeffs[1] = wb_coeffs[1]; - mRaw->metadata.wbCoeffs[2] = wb_coeffs[3]; + mRaw.metadata.wbCoeffs[0] = wb_coeffs[0]; + mRaw.metadata.wbCoeffs[1] = wb_coeffs[1]; + mRaw.metadata.wbCoeffs[2] = wb_coeffs[3]; } } diff --git a/src/librawspeed/decoders/MrwDecoder.h b/src/librawspeed/decoders/MrwDecoder.h index 015151f1a..511cb810e 100644 --- a/src/librawspeed/decoders/MrwDecoder.h +++ b/src/librawspeed/decoders/MrwDecoder.h @@ -45,7 +45,7 @@ class MrwDecoder final : public RawDecoder { public: explicit MrwDecoder(const Buffer& file); - RawImage decodeRawInternal() override; + void decodeRawInternal() override; void checkSupportInternal(const CameraMetaData* meta) override; void decodeMetaDataInternal(const CameraMetaData* meta) override; static int isMRW(const Buffer& input); diff --git a/src/librawspeed/decoders/NakedDecoder.cpp b/src/librawspeed/decoders/NakedDecoder.cpp index e6b04b99f..f67926942 100644 --- a/src/librawspeed/decoders/NakedDecoder.cpp +++ b/src/librawspeed/decoders/NakedDecoder.cpp @@ -85,20 +85,18 @@ void NakedDecoder::parseHints() { } } -RawImage NakedDecoder::decodeRawInternal() { +void NakedDecoder::decodeRawInternal() { parseHints(); - mRaw->dim = iPoint2D(width, height); - mRaw->createData(); + mRaw.get(0)->dim = iPoint2D(width, height); + mRaw.get(0)->createData(); UncompressedDecompressor u( ByteStream(DataBuffer(mFile.getSubView(offset), Endianness::little)), - mRaw); + mRaw.get(0).get()); iPoint2D pos(0, 0); - u.readUncompressedRaw(mRaw->dim, pos, width * bits / 8, bits, bo); - - return mRaw; + u.readUncompressedRaw(mRaw.get(0)->dim, pos, width * bits / 8, bits, bo); } void NakedDecoder::checkSupportInternal(const CameraMetaData* meta) { diff --git a/src/librawspeed/decoders/NakedDecoder.h b/src/librawspeed/decoders/NakedDecoder.h index d85978cda..21ef3b20d 100644 --- a/src/librawspeed/decoders/NakedDecoder.h +++ b/src/librawspeed/decoders/NakedDecoder.h @@ -49,7 +49,7 @@ class NakedDecoder final : public RawDecoder { public: NakedDecoder(const Buffer& file, const Camera* c); - RawImage decodeRawInternal() override; + void decodeRawInternal() override; void checkSupportInternal(const CameraMetaData* meta) override; void decodeMetaDataInternal(const CameraMetaData* meta) override; diff --git a/src/librawspeed/decoders/NefDecoder.cpp b/src/librawspeed/decoders/NefDecoder.cpp index c0d14be7a..a7a6d0854 100644 --- a/src/librawspeed/decoders/NefDecoder.cpp +++ b/src/librawspeed/decoders/NefDecoder.cpp @@ -63,7 +63,7 @@ bool NefDecoder::isAppropriateDecoder(const TiffRootIFD* rootIFD, return make == "NIKON CORPORATION" || make == "NIKON"; } -RawImage NefDecoder::decodeRawInternal() { +void NefDecoder::decodeRawInternal() { const auto* raw = mRootIFD->getIFDWithTag(TiffTag::CFAPATTERN); auto compression = raw->getEntry(TiffTag::COMPRESSION)->getU32(); @@ -76,19 +76,19 @@ RawImage NefDecoder::decodeRawInternal() { ThrowRDE("Image data outside of file."); if (!D100IsCompressed(offsets->getU32())) { DecodeD100Uncompressed(); - return mRaw; + return; } } if (compression == 1 || (hints.has("force_uncompressed")) || NEFIsUncompressed(raw)) { DecodeUncompressed(); - return mRaw; + return; } if (NEFIsUncompressedRGB(raw)) { DecodeSNefUncompressed(); - return mRaw; + return; } if (offsets->count != 1) { @@ -109,7 +109,7 @@ RawImage NefDecoder::decodeRawInternal() { uint32_t height = raw->getEntry(TiffTag::IMAGELENGTH)->getU32(); uint32_t bitPerPixel = raw->getEntry(TiffTag::BITSPERSAMPLE)->getU32(); - mRaw->dim = iPoint2D(width, height); + mRaw.get(0)->dim = iPoint2D(width, height); raw = mRootIFD->getIFDWithTag(static_cast(0x8c)); @@ -124,11 +124,9 @@ RawImage NefDecoder::decodeRawInternal() { DataBuffer(mFile.getSubView(offsets->getU32(), counts->getU32()), Endianness::little)); - NikonDecompressor n(mRaw, meta->getData(), bitPerPixel); - mRaw->createData(); + NikonDecompressor n(mRaw.get(0).get(), meta->getData(), bitPerPixel); + mRaw.get(0)->createData(); n.decompress(rawData, uncorrectedRawValues); - - return mRaw; } /* @@ -211,7 +209,7 @@ void NefDecoder::DecodeUncompressed() const { uint32_t height = raw->getEntry(TiffTag::IMAGELENGTH)->getU32(); uint32_t bitPerPixel = raw->getEntry(TiffTag::BITSPERSAMPLE)->getU32(); - mRaw->dim = iPoint2D(width, height); + mRaw.get(0)->dim = iPoint2D(width, height); if (width == 0 || height == 0 || width > 8288 || height > 5520) ThrowRDE("Unexpected image dimensions found: (%u; %u)", width, height); @@ -222,10 +220,10 @@ void NefDecoder::DecodeUncompressed() const { counts->count, offsets->count); } - if (yPerSlice == 0 || yPerSlice > static_cast(mRaw->dim.y) || - roundUpDivision(mRaw->dim.y, yPerSlice) != counts->count) { + if (yPerSlice == 0 || yPerSlice > static_cast(mRaw.get(0)->dim.y) || + roundUpDivision(mRaw.get(0)->dim.y, yPerSlice) != counts->count) { ThrowRDE("Invalid y per slice %u or strip count %u (height = %u)", - yPerSlice, counts->count, mRaw->dim.y); + yPerSlice, counts->count, mRaw.get(0)->dim.y); } vector slices; @@ -259,7 +257,7 @@ void NefDecoder::DecodeUncompressed() const { assert(height == offY); assert(slices.size() == counts->count); - mRaw->createData(); + mRaw.get(0)->createData(); if (bitPerPixel == 14 && width*slices[0].h*2 == slices[0].count) bitPerPixel = 16; // D3 & D810 @@ -284,14 +282,14 @@ void NefDecoder::DecodeUncompressed() const { iPoint2D pos(0, offY); if (hints.has("coolpixmangled")) { - UncompressedDecompressor u(in, mRaw); + UncompressedDecompressor u(in, mRaw.get(0).get()); u.readUncompressedRaw(size, pos, width * bitPerPixel / 8, 12, BitOrder::MSB32); } else { if (hints.has("coolpixsplit")) readCoolpixSplitRaw(in, size, pos, width * bitPerPixel / 8); else { - UncompressedDecompressor u(in, mRaw); + UncompressedDecompressor u(in, mRaw.get(0).get()); if (in.getSize() % size.y != 0) ThrowRDE("Inconsistent row size"); const auto inputPitchBytes = in.getSize() / size.y; @@ -307,7 +305,9 @@ void NefDecoder::DecodeUncompressed() const { void NefDecoder::readCoolpixSplitRaw(ByteStream input, const iPoint2D& size, const iPoint2D& offset, int inputPitch) const { - const Array2DRef img(mRaw->getU16DataAsUncroppedArray2DRef()); + auto *rawU16 = dynamic_cast(mRaw.get(0).get()); + assert(rawU16); + const Array2DRef img(rawU16->getU16DataAsUncroppedArray2DRef()); if (size.y % 2 != 0) ThrowRDE("Odd number of rows"); @@ -321,9 +321,9 @@ void NefDecoder::readCoolpixSplitRaw(ByteStream input, const iPoint2D& size, // know where the first input bit for first odd row is, the input slice width // must be a multiple of 8 pixels. - if (offset.x > mRaw->dim.x || offset.y > mRaw->dim.y) + if (offset.x > mRaw.get(0)->dim.x || offset.y > mRaw.get(0)->dim.y) ThrowRDE("All pixels outside of image"); - if (offset.x + size.x > mRaw->dim.x || offset.y + size.y > mRaw->dim.y) + if (offset.x + size.x > mRaw.get(0)->dim.x || offset.y + size.y > mRaw.get(0)->dim.y) ThrowRDE("Output is partailly out of image"); // The input bytes are laid out in the memory in the following way: @@ -350,8 +350,8 @@ void NefDecoder::DecodeD100Uncompressed() const { uint32_t width = 3040; uint32_t height = 2024; - mRaw->dim = iPoint2D(width, height); - mRaw->createData(); + mRaw.get(0)->dim = iPoint2D(width, height); + mRaw.get(0)->createData(); if (ByteStream bs(DataBuffer(mFile.getSubView(offset), Endianness::little)); bs.getRemainSize() == 0) @@ -359,12 +359,12 @@ void NefDecoder::DecodeD100Uncompressed() const { UncompressedDecompressor u( ByteStream(DataBuffer(mFile.getSubView(offset), Endianness::little)), - mRaw); + mRaw.get(0).get()); u.decode12BitRaw(width, height); } -void NefDecoder::DecodeSNefUncompressed() const { +void NefDecoder::DecodeSNefUncompressed() { const auto* raw = getIFDWithLargestImage(TiffTag::CFAPATTERN); uint32_t offset = raw->getEntry(TiffTag::STRIPOFFSETS)->getU32(); uint32_t width = raw->getEntry(TiffTag::IMAGEWIDTH)->getU32(); @@ -374,10 +374,10 @@ void NefDecoder::DecodeSNefUncompressed() const { height > 2456) ThrowRDE("Unexpected image dimensions found: (%u; %u)", width, height); - mRaw->dim = iPoint2D(width, height); - mRaw->setCpp(3); - mRaw->isCFA = false; - mRaw->createData(); + mRaw.get(0)->dim = iPoint2D(width, height); + mRaw.get(0)->setCpp(3); + mRaw.get(0)->isCFA = false; + mRaw.get(0)->createData(); ByteStream in(DataBuffer(mFile.getSubView(offset), Endianness::little)); DecodeNikonSNef(in); @@ -472,11 +472,11 @@ const std::array NefDecoder::keymap = { void NefDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { int iso = 0; - mRaw->cfa.setCFA(iPoint2D(2, 2), CFAColor::RED, CFAColor::GREEN, + mRaw.get(0)->cfa.setCFA(iPoint2D(2, 2), CFAColor::RED, CFAColor::GREEN, CFAColor::GREEN, CFAColor::BLUE); - int white = mRaw->whitePoint; - int black = mRaw->blackLevel; + int white = mRaw.get(0)->whitePoint; + int black = mRaw.get(0)->blackLevel; if (mRootIFD->hasEntryRecursive(TiffTag::ISOSPEEDRATINGS)) iso = mRootIFD->getEntryRecursive(TiffTag::ISOSPEEDRATINGS)->getU32(); @@ -486,11 +486,11 @@ void NefDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { if (mRootIFD->hasEntryRecursive(static_cast(12))) { const TiffEntry* wb = mRootIFD->getEntryRecursive(static_cast(12)); if (wb->count == 4) { - mRaw->metadata.wbCoeffs[0] = wb->getFloat(0); - mRaw->metadata.wbCoeffs[1] = wb->getFloat(2); - mRaw->metadata.wbCoeffs[2] = wb->getFloat(1); - if (mRaw->metadata.wbCoeffs[1] <= 0.0F) - mRaw->metadata.wbCoeffs[1] = 1.0F; + mRaw.metadata.wbCoeffs[0] = wb->getFloat(0); + mRaw.metadata.wbCoeffs[1] = wb->getFloat(2); + mRaw.metadata.wbCoeffs[2] = wb->getFloat(1); + if (mRaw.metadata.wbCoeffs[1] <= 0.0F) + mRaw.metadata.wbCoeffs[1] = 1.0F; } } else if (mRootIFD->hasEntryRecursive(static_cast(0x0097))) { const TiffEntry* wb = @@ -506,14 +506,14 @@ void NefDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { if (version == 0x100 && wb->count >= 80 && wb->type == TiffDataType::UNDEFINED) { - mRaw->metadata.wbCoeffs[0] = static_cast(wb->getU16(36)); - mRaw->metadata.wbCoeffs[2] = static_cast(wb->getU16(37)); - mRaw->metadata.wbCoeffs[1] = static_cast(wb->getU16(38)); + mRaw.metadata.wbCoeffs[0] = static_cast(wb->getU16(36)); + mRaw.metadata.wbCoeffs[2] = static_cast(wb->getU16(37)); + mRaw.metadata.wbCoeffs[1] = static_cast(wb->getU16(38)); } else if (version == 0x103 && wb->count >= 26 && wb->type == TiffDataType::UNDEFINED) { - mRaw->metadata.wbCoeffs[0] = static_cast(wb->getU16(10)); - mRaw->metadata.wbCoeffs[1] = static_cast(wb->getU16(11)); - mRaw->metadata.wbCoeffs[2] = static_cast(wb->getU16(12)); + mRaw.metadata.wbCoeffs[0] = static_cast(wb->getU16(10)); + mRaw.metadata.wbCoeffs[1] = static_cast(wb->getU16(11)); + mRaw.metadata.wbCoeffs[2] = static_cast(wb->getU16(12)); } else if (((version == 0x204 && wb->count >= 564) || (version == 0x205 && wb->count >= 284)) && mRootIFD->hasEntryRecursive(static_cast(0x001d)) && @@ -555,11 +555,11 @@ void NefDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { // Finally set the WB coeffs uint32_t off = (version == 0x204) ? 6 : 14; - mRaw->metadata.wbCoeffs[0] = + mRaw.metadata.wbCoeffs[0] = static_cast(getU16BE(buf.data() + off + 0)); - mRaw->metadata.wbCoeffs[1] = + mRaw.metadata.wbCoeffs[1] = static_cast(getU16BE(buf.data() + off + 2)); - mRaw->metadata.wbCoeffs[2] = + mRaw.metadata.wbCoeffs[2] = static_cast(getU16BE(buf.data() + off + 6)); } } @@ -570,9 +570,9 @@ void NefDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { if (wb->count == 2560 && wb->type == TiffDataType::UNDEFINED) { bs.skipBytes(1248); bs.setByteOrder(Endianness::big); - mRaw->metadata.wbCoeffs[0] = static_cast(bs.getU16()) / 256.0; - mRaw->metadata.wbCoeffs[1] = 1.0F; - mRaw->metadata.wbCoeffs[2] = static_cast(bs.getU16()) / 256.0; + mRaw.metadata.wbCoeffs[0] = static_cast(bs.getU16()) / 256.0; + mRaw.metadata.wbCoeffs[1] = 1.0F; + mRaw.metadata.wbCoeffs[2] = static_cast(bs.getU16()) / 256.0; } else if (bs.hasPatternAt("NRW ", 4, 0)) { uint32_t offset = 0; if (!bs.hasPatternAt("0100", 4, 4) && wb->count > 72) @@ -583,17 +583,17 @@ void NefDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { if (offset) { bs.skipBytes(offset); bs.setByteOrder(Endianness::little); - mRaw->metadata.wbCoeffs[0] = 4.0 * bs.getU32(); - mRaw->metadata.wbCoeffs[1] = bs.getU32(); - mRaw->metadata.wbCoeffs[1] += bs.getU32(); - mRaw->metadata.wbCoeffs[2] = 4.0 * bs.getU32(); + mRaw.metadata.wbCoeffs[0] = 4.0 * bs.getU32(); + mRaw.metadata.wbCoeffs[1] = bs.getU32(); + mRaw.metadata.wbCoeffs[1] += bs.getU32(); + mRaw.metadata.wbCoeffs[2] = 4.0 * bs.getU32(); } } } if (hints.has("nikon_wb_adjustment")) { - mRaw->metadata.wbCoeffs[0] *= 256/527.0; - mRaw->metadata.wbCoeffs[2] *= 256/317.0; + mRaw.metadata.wbCoeffs[0] *= 256/527.0; + mRaw.metadata.wbCoeffs[2] *= 256/317.0; } auto id = mRootIFD->getID(); @@ -608,9 +608,9 @@ void NefDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { } if (white != 65536) - mRaw->whitePoint = white; + mRaw.get(0)->whitePoint = white; if (black != -1) - mRaw->blackLevel = black; + mRaw.get(0)->blackLevel = black; } @@ -618,9 +618,9 @@ void NefDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { // We un-apply the whitebalance, so output matches lossless. // Note that values are scaled. See comment below on details. // OPTME: It would be trivial to run this multithreaded. -void NefDecoder::DecodeNikonSNef(const ByteStream& input) const { - if (mRaw->dim.x < 6) - ThrowIOE("got a %u wide sNEF, aborting", mRaw->dim.x); +void NefDecoder::DecodeNikonSNef(const ByteStream& input) { + if (mRaw.get(0)->dim.x < 6) + ThrowIOE("got a %u wide sNEF, aborting", mRaw.get(0)->dim.x); // We need to read the applied whitebalance, since we should return // data before whitebalance, so we "unapply" it. @@ -640,9 +640,9 @@ void NefDecoder::DecodeNikonSNef(const ByteStream& input) const { wb_r < lower_limit || wb_b < lower_limit || wb_r > 10.0F || wb_b > 10.0F) ThrowRDE("Whitebalance has bad values (%f, %f)", wb_r, wb_b); - mRaw->metadata.wbCoeffs[0] = wb_r; - mRaw->metadata.wbCoeffs[1] = 1.0F; - mRaw->metadata.wbCoeffs[2] = wb_b; + mRaw.metadata.wbCoeffs[0] = wb_r; + mRaw.metadata.wbCoeffs[1] = 1.0F; + mRaw.metadata.wbCoeffs[2] = wb_b; auto inv_wb_r = static_cast(1024.0 / wb_r); auto inv_wb_b = static_cast(1024.0 / wb_b); @@ -656,12 +656,14 @@ void NefDecoder::DecodeNikonSNef(const ByteStream& input) const { curve.resize(4095); - RawImageCurveGuard curveHandler(&mRaw, curve, false); + RawImageCurveGuard curveHandler(mRaw.get(0).get(), curve, false); uint16_t tmp; auto* tmpch = reinterpret_cast(&tmp); - const Array2DRef out(mRaw->getU16DataAsUncroppedArray2DRef()); + auto *rawU16 = dynamic_cast(mRaw.get(0).get()); + assert(rawU16); + const Array2DRef out(rawU16->getU16DataAsUncroppedArray2DRef()); const uint8_t* in = input.peekData(out.width * out.height); for (int row = 0; row < out.height; row++) { @@ -696,27 +698,27 @@ void NefDecoder::DecodeNikonSNef(const ByteStream& input) const { cb2 -= 2048; cr2 -= 2048; - mRaw->setWithLookUp(clampBits(static_cast(y1 + 1.370705 * cr), 12), + mRaw.get(0)->setWithLookUp(clampBits(static_cast(y1 + 1.370705 * cr), 12), tmpch, &random); out(row, col) = clampBits((inv_wb_r * tmp + (1 << 9)) >> 10, 15); - mRaw->setWithLookUp( + mRaw.get(0)->setWithLookUp( clampBits(static_cast(y1 - 0.337633 * cb - 0.698001 * cr), 12), reinterpret_cast(&out(row, col + 1)), &random); - mRaw->setWithLookUp(clampBits(static_cast(y1 + 1.732446 * cb), 12), + mRaw.get(0)->setWithLookUp(clampBits(static_cast(y1 + 1.732446 * cb), 12), tmpch, &random); out(row, col + 2) = clampBits((inv_wb_b * tmp + (1 << 9)) >> 10, 15); - mRaw->setWithLookUp(clampBits(static_cast(y2 + 1.370705 * cr2), 12), + mRaw.get(0)->setWithLookUp(clampBits(static_cast(y2 + 1.370705 * cr2), 12), tmpch, &random); out(row, col + 3) = clampBits((inv_wb_r * tmp + (1 << 9)) >> 10, 15); - mRaw->setWithLookUp( + mRaw.get(0)->setWithLookUp( clampBits(static_cast(y2 - 0.337633 * cb2 - 0.698001 * cr2), 12), reinterpret_cast(&out(row, col + 4)), &random); - mRaw->setWithLookUp(clampBits(static_cast(y2 + 1.732446 * cb2), 12), + mRaw.get(0)->setWithLookUp(clampBits(static_cast(y2 + 1.732446 * cb2), 12), tmpch, &random); out(row, col + 5) = clampBits((inv_wb_b * tmp + (1 << 9)) >> 10, 15); } diff --git a/src/librawspeed/decoders/NefDecoder.h b/src/librawspeed/decoders/NefDecoder.h index 726b6ef70..470d6ef90 100644 --- a/src/librawspeed/decoders/NefDecoder.h +++ b/src/librawspeed/decoders/NefDecoder.h @@ -45,7 +45,7 @@ class NefDecoder final : public AbstractTiffDecoder NefDecoder(TiffRootIFDOwner&& root, const Buffer& file) : AbstractTiffDecoder(std::move(root), file) {} - RawImage decodeRawInternal() override; + void decodeRawInternal() override; void decodeMetaDataInternal(const CameraMetaData* meta) override; void checkSupportInternal(const CameraMetaData* meta) override; @@ -58,10 +58,10 @@ class NefDecoder final : public AbstractTiffDecoder static bool NEFIsUncompressedRGB(const TiffIFD* raw); void DecodeUncompressed() const; void DecodeD100Uncompressed() const; - void DecodeSNefUncompressed() const; + void DecodeSNefUncompressed(); void readCoolpixSplitRaw(ByteStream input, const iPoint2D& size, const iPoint2D& offset, int inputPitch) const; - void DecodeNikonSNef(const ByteStream& input) const; + void DecodeNikonSNef(const ByteStream& input); [[nodiscard]] std::string getMode() const; [[nodiscard]] std::string getExtendedMode(const std::string& mode) const; static std::vector gammaCurve(double pwr, double ts, int mode, diff --git a/src/librawspeed/decoders/OrfDecoder.cpp b/src/librawspeed/decoders/OrfDecoder.cpp index 853178de8..0d661f034 100644 --- a/src/librawspeed/decoders/OrfDecoder.cpp +++ b/src/librawspeed/decoders/OrfDecoder.cpp @@ -99,7 +99,7 @@ ByteStream OrfDecoder::handleSlices() const { return input.getStream(size); } -RawImage OrfDecoder::decodeRawInternal() { +void OrfDecoder::decodeRawInternal() { const auto* raw = mRootIFD->getIFDWithTag(TiffTag::STRIPOFFSETS); if (int compression = raw->getEntry(TiffTag::COMPRESSION)->getU32(); @@ -112,33 +112,31 @@ RawImage OrfDecoder::decodeRawInternal() { if (!width || !height || width % 2 != 0 || width > 10400 || height > 7796) ThrowRDE("Unexpected image dimensions found: (%u; %u)", width, height); - mRaw->dim = iPoint2D(width, height); + mRaw.get(0)->dim = iPoint2D(width, height); ByteStream input(handleSlices()); if (decodeUncompressed(input, width, height, input.getSize())) - return mRaw; + return; if (raw->getEntry(TiffTag::STRIPOFFSETS)->count != 1) ThrowRDE("%u stripes, and not uncompressed. Unsupported.", raw->getEntry(TiffTag::STRIPOFFSETS)->count); - OlympusDecompressor o(mRaw); - mRaw->createData(); + OlympusDecompressor o(mRaw.get(0).get()); + mRaw.get(0)->createData(); o.decompress(std::move(input)); - - return mRaw; } bool OrfDecoder::decodeUncompressed(const ByteStream& s, uint32_t w, uint32_t h, uint32_t size) const { - UncompressedDecompressor u(s, mRaw); + UncompressedDecompressor u(s, mRaw.get(0).get()); // FIXME: most of this logic should be in UncompressedDecompressor, // one way or another. if (size == h * ((w * 12 / 8) + ((w + 2) / 10))) { // 12-bit packed 'with control' raw - mRaw->createData(); + mRaw.get(0)->createData(); u.decode12BitRaw(w, h); return true; } @@ -146,13 +144,13 @@ bool OrfDecoder::decodeUncompressed(const ByteStream& s, uint32_t w, uint32_t h, if (size == w * h * 12 / 8) { // We're in a 12-bit packed raw iPoint2D dimensions(w, h); iPoint2D pos(0, 0); - mRaw->createData(); + mRaw.get(0)->createData(); u.readUncompressedRaw(dimensions, pos, w * 12 / 8, 12, BitOrder::MSB32); return true; } if (size == w * h * 2) { // We're in an unpacked raw - mRaw->createData(); + mRaw.get(0)->createData(); // FIXME: seems fishy if (s.getByteOrder() == getHostEndianness()) u.decodeRawUnpacked<12, Endianness::little>(w, h); @@ -163,7 +161,7 @@ bool OrfDecoder::decodeUncompressed(const ByteStream& s, uint32_t w, uint32_t h, if (size > w * h * 3 / 2) { // We're in one of those weird interlaced packed raws - mRaw->createData(); + mRaw.get(0)->createData(); u.decode12BitRaw(w, h); return true; } @@ -186,7 +184,7 @@ void OrfDecoder::parseCFA() const { if (cfaSize != iPoint2D{2, 2}) ThrowRDE("Bad CFA size: (%i, %i)", cfaSize.x, cfaSize.y); - mRaw->cfa.setSize(cfaSize); + mRaw.get(0)->cfa.setSize(cfaSize); auto int2enum = [](uint8_t i) { switch (i) { @@ -205,7 +203,7 @@ void OrfDecoder::parseCFA() const { for (int x = 0; x < cfaSize.x; x++) { uint8_t c1 = CFA->getByte(4 + x + y * cfaSize.x); CFAColor c2 = int2enum(c1); - mRaw->cfa.setColorAt(iPoint2D(x, y), c2); + mRaw.get(0)->cfa.setColorAt(iPoint2D(x, y), c2); } } } @@ -222,10 +220,10 @@ void OrfDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { if (mRootIFD->hasEntryRecursive(TiffTag::OLYMPUSREDMULTIPLIER) && mRootIFD->hasEntryRecursive(TiffTag::OLYMPUSBLUEMULTIPLIER)) { - mRaw->metadata.wbCoeffs[0] = static_cast( + mRaw.metadata.wbCoeffs[0] = static_cast( mRootIFD->getEntryRecursive(TiffTag::OLYMPUSREDMULTIPLIER)->getU16()); - mRaw->metadata.wbCoeffs[1] = 256.0F; - mRaw->metadata.wbCoeffs[2] = static_cast( + mRaw.metadata.wbCoeffs[1] = 256.0F; + mRaw.metadata.wbCoeffs[2] = static_cast( mRootIFD->getEntryRecursive(TiffTag::OLYMPUSBLUEMULTIPLIER)->getU16()); } else if (mRootIFD->hasEntryRecursive(TiffTag::OLYMPUSIMAGEPROCESSING)) { // Newer cameras process the Image Processing SubIFD in the makernote @@ -242,9 +240,9 @@ void OrfDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { const TiffEntry* wb = image_processing.getEntry(static_cast(0x0100)); if (wb->count == 2 || wb->count == 4) { - mRaw->metadata.wbCoeffs[0] = wb->getFloat(0); - mRaw->metadata.wbCoeffs[1] = 256.0F; - mRaw->metadata.wbCoeffs[2] = wb->getFloat(1); + mRaw.metadata.wbCoeffs[0] = wb->getFloat(0); + mRaw.metadata.wbCoeffs[1] = 256.0F; + mRaw.metadata.wbCoeffs[2] = wb->getFloat(1); } } @@ -255,7 +253,7 @@ void OrfDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { // Order is assumed to be RGGB if (blackEntry->count == 4) { for (int i = 0; i < 4; i++) { - auto c = mRaw->cfa.getColorAt(i & 1, i >> 1); + auto c = mRaw.get(0)->cfa.getColorAt(i & 1, i >> 1); int j; switch (c) { case CFAColor::RED: @@ -271,11 +269,11 @@ void OrfDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { ThrowRDE("Unexpected CFA color: %u", static_cast(c)); } - mRaw->blackLevelSeparate[i] = blackEntry->getU16(j); + mRaw.get(0)->blackLevelSeparate[i] = blackEntry->getU16(j); } // Adjust whitelevel based on the read black (we assume the dynamic // range is the same) - mRaw->whitePoint -= (mRaw->blackLevel - mRaw->blackLevelSeparate[0]); + mRaw.get(0)->whitePoint -= (mRaw.get(0)->blackLevel - mRaw.get(0)->blackLevelSeparate[0]); } } } diff --git a/src/librawspeed/decoders/OrfDecoder.h b/src/librawspeed/decoders/OrfDecoder.h index 79cba69da..694cb21d2 100644 --- a/src/librawspeed/decoders/OrfDecoder.h +++ b/src/librawspeed/decoders/OrfDecoder.h @@ -43,7 +43,7 @@ class OrfDecoder final : public AbstractTiffDecoder OrfDecoder(TiffRootIFDOwner&& root, const Buffer& file) : AbstractTiffDecoder(std::move(root), file) {} - RawImage decodeRawInternal() override; + void decodeRawInternal() override; void decodeMetaDataInternal(const CameraMetaData* meta) override; private: diff --git a/src/librawspeed/decoders/PefDecoder.cpp b/src/librawspeed/decoders/PefDecoder.cpp index f25b5c564..4a8c17040 100644 --- a/src/librawspeed/decoders/PefDecoder.cpp +++ b/src/librawspeed/decoders/PefDecoder.cpp @@ -49,14 +49,14 @@ bool PefDecoder::isAppropriateDecoder(const TiffRootIFD* rootIFD, make == "RICOH IMAGING COMPANY, LTD." || make == "PENTAX"; } -RawImage PefDecoder::decodeRawInternal() { +void PefDecoder::decodeRawInternal() { const auto* raw = mRootIFD->getIFDWithTag(TiffTag::STRIPOFFSETS); int compression = raw->getEntry(TiffTag::COMPRESSION)->getU32(); if (1 == compression || compression == 32773) { decodeUncompressed(raw, BitOrder::MSB); - return mRaw; + return; } if (65535 != compression) @@ -80,7 +80,7 @@ RawImage PefDecoder::decodeRawInternal() { uint32_t width = raw->getEntry(TiffTag::IMAGEWIDTH)->getU32(); uint32_t height = raw->getEntry(TiffTag::IMAGELENGTH)->getU32(); - mRaw->dim = iPoint2D(width, height); + mRaw.get(0)->dim = iPoint2D(width, height); std::optional metaData; if (getRootIFD()->hasEntryRecursive(static_cast(0x220))) { @@ -93,16 +93,14 @@ RawImage PefDecoder::decodeRawInternal() { metaData = t->getData(); } - PentaxDecompressor p(mRaw, metaData); - mRaw->createData(); + PentaxDecompressor p(mRaw.get(0).get(), metaData); + mRaw.get(0)->createData(); p.decompress(bs); - - return mRaw; } void PefDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { int iso = 0; - mRaw->cfa.setCFA(iPoint2D(2, 2), CFAColor::RED, CFAColor::GREEN, + mRaw.get(0)->cfa.setCFA(iPoint2D(2, 2), CFAColor::RED, CFAColor::GREEN, CFAColor::GREEN, CFAColor::BLUE); if (mRootIFD->hasEntryRecursive(TiffTag::ISOSPEEDRATINGS)) @@ -116,7 +114,7 @@ void PefDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { mRootIFD->getEntryRecursive(static_cast(0x200)); if (black->count == 4) { for (int i = 0; i < 4; i++) - mRaw->blackLevelSeparate[i] = black->getU32(i); + mRaw.get(0)->blackLevelSeparate[i] = black->getU32(i); } } @@ -125,9 +123,9 @@ void PefDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { const TiffEntry* wb = mRootIFD->getEntryRecursive(static_cast(0x0201)); if (wb->count == 4) { - mRaw->metadata.wbCoeffs[0] = wb->getU32(0); - mRaw->metadata.wbCoeffs[1] = wb->getU32(1); - mRaw->metadata.wbCoeffs[2] = wb->getU32(3); + mRaw.metadata.wbCoeffs[0] = wb->getU32(0); + mRaw.metadata.wbCoeffs[1] = wb->getU32(1); + mRaw.metadata.wbCoeffs[2] = wb->getU32(3); } } } diff --git a/src/librawspeed/decoders/PefDecoder.h b/src/librawspeed/decoders/PefDecoder.h index 808e6be8f..f7765e442 100644 --- a/src/librawspeed/decoders/PefDecoder.h +++ b/src/librawspeed/decoders/PefDecoder.h @@ -38,7 +38,7 @@ class PefDecoder final : public AbstractTiffDecoder PefDecoder(TiffRootIFDOwner&& root, const Buffer& file) : AbstractTiffDecoder(std::move(root), file) {} - RawImage decodeRawInternal() override; + void decodeRawInternal() override; void decodeMetaDataInternal(const CameraMetaData* meta) override; private: diff --git a/src/librawspeed/decoders/RafDecoder.cpp b/src/librawspeed/decoders/RafDecoder.cpp index f1c2550aa..b04b1655c 100644 --- a/src/librawspeed/decoders/RafDecoder.cpp +++ b/src/librawspeed/decoders/RafDecoder.cpp @@ -64,7 +64,7 @@ bool RafDecoder::isAppropriateDecoder(const TiffRootIFD* rootIFD, return make == "FUJIFILM"; } -RawImage RafDecoder::decodeRawInternal() { +void RafDecoder::decodeRawInternal() { const auto* raw = mRootIFD->getIFDWithTag(TiffTag::FUJI_STRIPOFFSETS); uint32_t height = 0; uint32_t width = 0; @@ -97,17 +97,17 @@ RawImage RafDecoder::decodeRawInternal() { input = input.getSubStream(offsets->getU32(), counts->getU32()); if (isCompressed()) { - mRaw->metadata.mode = "compressed"; + mRaw.metadata.mode = "compressed"; - mRaw->dim = iPoint2D(width, height); + mRaw.get(0)->dim = iPoint2D(width, height); - FujiDecompressor f(mRaw, input); + FujiDecompressor f(mRaw.get(0).get(), input); - mRaw->createData(); + mRaw.get(0)->createData(); f.decompress(); - return mRaw; + return; } // x-trans sensors report 14bpp, but data isn't packed @@ -121,24 +121,15 @@ RawImage RafDecoder::decodeRawInternal() { assert(!isCompressed()); - if (8UL * counts->getU32() >= 2UL * 16UL * width * height) { + if ((8UL * counts->getU32() >= 2UL * 16UL * width * height) + || (8UL * counts->getU32() >= 16UL * width * height)) { bps = 16; - double_width = true; - } else if (8UL * counts->getU32() >= 2UL * 14UL * width * height) { + } else if ((8UL * counts->getU32() >= 2UL * 14UL * width * height) + || (8UL * counts->getU32() >= 14UL * width * height)) { bps = 14; - double_width = true; - } else if (8UL * counts->getU32() >= 2UL * 12UL * width * height) { + } else if ((8UL * counts->getU32() >= 2UL * 12UL * width * height) + || (8UL * counts->getU32() >= 12UL * width * height)) { bps = 12; - double_width = true; - } else if (8UL * counts->getU32() >= 16UL * width * height) { - bps = 16; - double_width = false; - } else if (8UL * counts->getU32() >= 14UL * width * height) { - bps = 14; - double_width = false; - } else if (8UL * counts->getU32() >= 12UL * width * height) { - bps = 12; - double_width = false; } else { ThrowRDE("Can not detect bitdepth. StripByteCounts = %u, width = %u, " "height = %u", @@ -148,10 +139,10 @@ RawImage RafDecoder::decodeRawInternal() { double_width = hints.has("double_width_unpacked"); const uint32_t real_width = double_width ? 2U * width : width; - mRaw->dim = iPoint2D(real_width, height); - mRaw->createData(); + mRaw.get(0)->dim = iPoint2D(real_width, height); + mRaw.get(0)->createData(); - UncompressedDecompressor u(input, mRaw); + UncompressedDecompressor u(input, mRaw.get(0).get()); if (double_width) { u.decodeRawUnpacked<16, Endianness::little>(width * 2, height); @@ -162,15 +153,13 @@ RawImage RafDecoder::decodeRawInternal() { } else { iPoint2D pos(0, 0); if (hints.has("jpeg32_bitorder")) { - u.readUncompressedRaw(mRaw->dim, pos, width * bps / 8, bps, + u.readUncompressedRaw(mRaw.get(0)->dim, pos, width * bps / 8, bps, BitOrder::MSB32); } else { - u.readUncompressedRaw(mRaw->dim, pos, width * bps / 8, bps, + u.readUncompressedRaw(mRaw.get(0)->dim, pos, width * bps / 8, bps, BitOrder::LSB); } } - - return mRaw; } void RafDecoder::checkSupportInternal(const CameraMetaData* meta) { @@ -178,19 +167,19 @@ void RafDecoder::checkSupportInternal(const CameraMetaData* meta) { ThrowRDE("Unknown camera. Will not guess."); if (isCompressed()) { - mRaw->metadata.mode = "compressed"; + mRaw.metadata.mode = "compressed"; auto id = mRootIFD->getID(); - const Camera* cam = meta->getCamera(id.make, id.model, mRaw->metadata.mode); + const Camera* cam = meta->getCamera(id.make, id.model, mRaw.metadata.mode); if (!cam) ThrowRDE("Couldn't find camera %s %s", id.make.c_str(), id.model.c_str()); - mRaw->cfa = cam->cfa; + mRaw.get(0)->cfa = cam->cfa; } } void RafDecoder::applyCorrections(const Camera* cam) { - iPoint2D new_size(mRaw->dim); + iPoint2D new_size(mRaw.get(0)->dim); iPoint2D crop_offset(0, 0); if (applyCrop) { @@ -199,11 +188,11 @@ void RafDecoder::applyCorrections(const Camera* cam) { bool double_width = hints.has("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; + new_size.x = mRaw.get(0)->dim.x / (double_width ? 2 : 1) - cam->cropPos.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.get(0)->dim.y - cam->cropPos.y + new_size.y; } bool rotate = hints.has("fuji_rotate"); @@ -224,12 +213,14 @@ void RafDecoder::applyCorrections(const Camera* cam) { } iPoint2D final_size(rotatedsize, rotatedsize-1); - RawImage rotated = RawImage::create(final_size, RawImageType::UINT16, 1); + auto rotated = + std::make_shared(final_size, 1); rotated->clearArea(iRectangle2D(iPoint2D(0,0), rotated->dim)); - rotated->metadata = mRaw->metadata; - rotated->metadata.fujiRotationPos = rotationPos; + mRaw.metadata.fujiRotationPos = rotationPos; - auto srcImg = mRaw->getU16DataAsUncroppedArray2DRef(); + auto *rawU16 = dynamic_cast(mRaw.get(0).get()); + assert(rawU16); + auto srcImg = rawU16->getU16DataAsUncroppedArray2DRef(); auto dstImg = rotated->getU16DataAsUncroppedArray2DRef(); for (int y = 0; y < new_size.y; y++) { @@ -249,9 +240,10 @@ void RafDecoder::applyCorrections(const Camera* cam) { ThrowRDE("Trying to write out of bounds"); } } - mRaw = rotated; + mRaw.clear(); + mRaw.appendFrame(rotated); } else if (applyCrop) { - mRaw->subFrame(iRectangle2D(crop_offset, new_size)); + mRaw.get(0)->subFrame(iRectangle2D(crop_offset, new_size)); } } @@ -259,12 +251,12 @@ void RafDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { int iso = 0; if (mRootIFD->hasEntryRecursive(TiffTag::ISOSPEEDRATINGS)) iso = mRootIFD->getEntryRecursive(TiffTag::ISOSPEEDRATINGS)->getU32(); - mRaw->metadata.isoSpeed = iso; + mRaw.metadata.isoSpeed = iso; // This is where we'd normally call setMetaData but since we may still need // to rotate the image for SuperCCD cameras we do everything ourselves auto id = mRootIFD->getID(); - const Camera* cam = meta->getCamera(id.make, id.model, mRaw->metadata.mode); + const Camera* cam = meta->getCamera(id.make, id.model, mRaw.metadata.mode); if (!cam) ThrowRDE("Couldn't find camera"); @@ -273,7 +265,7 @@ void RafDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { applyCorrections(cam); const CameraSensorInfo *sensor = cam->getSensorInfo(iso); - mRaw->blackLevel = sensor->mBlackLevel; + mRaw.get(0)->blackLevel = sensor->mBlackLevel; // at least the (bayer sensor) X100 comes with a tag like this: if (mRootIFD->hasEntryRecursive(TiffTag::FUJI_BLACKLEVEL)) { @@ -282,48 +274,48 @@ void RafDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { if (sep_black->count == 4) { for(int k=0;k<4;k++) - mRaw->blackLevelSeparate[k] = sep_black->getU32(k); + mRaw.get(0)->blackLevelSeparate[k] = sep_black->getU32(k); } else if (sep_black->count == 36) { - for (int& k : mRaw->blackLevelSeparate) + for (int& k : mRaw.get(0)->blackLevelSeparate) k = 0; for (int y = 0; y < 6; y++) { for (int x = 0; x < 6; x++) - mRaw->blackLevelSeparate[2 * (y % 2) + (x % 2)] += + mRaw.get(0)->blackLevelSeparate[2 * (y % 2) + (x % 2)] += sep_black->getU32(6 * y + x); } - for (int& k : mRaw->blackLevelSeparate) + for (int& k : mRaw.get(0)->blackLevelSeparate) k /= 9; } } - mRaw->whitePoint = sensor->mWhiteLevel; - mRaw->blackAreas = cam->blackAreas; - mRaw->cfa = cam->cfa; + mRaw.get(0)->whitePoint = sensor->mWhiteLevel; + mRaw.get(0)->blackAreas = cam->blackAreas; + mRaw.get(0)->cfa = cam->cfa; if (!cam->color_matrix.empty()) - mRaw->metadata.colorMatrix = cam->color_matrix; - mRaw->metadata.canonical_make = cam->canonical_make; - mRaw->metadata.canonical_model = cam->canonical_model; - mRaw->metadata.canonical_alias = cam->canonical_alias; - mRaw->metadata.canonical_id = cam->canonical_id; - mRaw->metadata.make = id.make; - mRaw->metadata.model = id.model; + mRaw.metadata.colorMatrix = cam->color_matrix; + mRaw.metadata.canonical_make = cam->canonical_make; + mRaw.metadata.canonical_model = cam->canonical_model; + mRaw.metadata.canonical_alias = cam->canonical_alias; + mRaw.metadata.canonical_id = cam->canonical_id; + mRaw.metadata.make = id.make; + mRaw.metadata.model = id.model; if (mRootIFD->hasEntryRecursive(TiffTag::FUJI_WB_GRBLEVELS)) { const TiffEntry* wb = mRootIFD->getEntryRecursive(TiffTag::FUJI_WB_GRBLEVELS); if (wb->count == 3) { - mRaw->metadata.wbCoeffs[0] = wb->getFloat(1); - mRaw->metadata.wbCoeffs[1] = wb->getFloat(0); - mRaw->metadata.wbCoeffs[2] = wb->getFloat(2); + mRaw.metadata.wbCoeffs[0] = wb->getFloat(1); + mRaw.metadata.wbCoeffs[1] = wb->getFloat(0); + mRaw.metadata.wbCoeffs[2] = wb->getFloat(2); } } else if (mRootIFD->hasEntryRecursive(TiffTag::FUJIOLDWB)) { const TiffEntry* wb = mRootIFD->getEntryRecursive(TiffTag::FUJIOLDWB); if (wb->count == 8) { - mRaw->metadata.wbCoeffs[0] = wb->getFloat(1); - mRaw->metadata.wbCoeffs[1] = wb->getFloat(0); - mRaw->metadata.wbCoeffs[2] = wb->getFloat(3); + mRaw.metadata.wbCoeffs[0] = wb->getFloat(1); + mRaw.metadata.wbCoeffs[1] = wb->getFloat(0); + mRaw.metadata.wbCoeffs[2] = wb->getFloat(3); } } } diff --git a/src/librawspeed/decoders/RafDecoder.h b/src/librawspeed/decoders/RafDecoder.h index ad75ff54a..b41d89a9e 100644 --- a/src/librawspeed/decoders/RafDecoder.h +++ b/src/librawspeed/decoders/RafDecoder.h @@ -41,7 +41,7 @@ class RafDecoder final : public AbstractTiffDecoder RafDecoder(TiffRootIFDOwner&& root, const Buffer& file) : AbstractTiffDecoder(std::move(root), file) {} - RawImage decodeRawInternal() override; + void decodeRawInternal() override; void applyCorrections(const Camera* cam); void decodeMetaDataInternal(const CameraMetaData* meta) override; void checkSupportInternal(const CameraMetaData* meta) override; diff --git a/src/librawspeed/decoders/RawDecoder.cpp b/src/librawspeed/decoders/RawDecoder.cpp index 095ebdd2a..029db0437 100644 --- a/src/librawspeed/decoders/RawDecoder.cpp +++ b/src/librawspeed/decoders/RawDecoder.cpp @@ -49,9 +49,9 @@ using std::vector; namespace rawspeed { RawDecoder::RawDecoder(const Buffer& file) - : mRaw(RawImage::create()), failOnUnknown(false), - interpolateBadPixels(true), applyStage1DngOpcodes(true), applyCrop(true), - uncorrectedRawValues(false), fujiRotate(true), mFile(file) {} + : failOnUnknown(false), interpolateBadPixels(true), + applyStage1DngOpcodes(true), applyCrop(true), uncorrectedRawValues(false), + fujiRotate(true), mFile(file) {mRaw.appendFrame(std::make_shared());} void RawDecoder::decodeUncompressed(const TiffIFD* rawIFD, BitOrder order) const { @@ -65,7 +65,7 @@ void RawDecoder::decodeUncompressed(const TiffIFD* rawIFD, if (width == 0 || height == 0 || width > 5632 || height > 3720) ThrowRDE("Unexpected image dimensions found: (%u; %u)", width, height); - mRaw->dim = iPoint2D(width, height); + mRaw.get(0)->dim = iPoint2D(width, height); if (counts->count != offsets->count) { ThrowRDE("Byte count number does not match strip size: " @@ -73,10 +73,10 @@ void RawDecoder::decodeUncompressed(const TiffIFD* rawIFD, counts->count, offsets->count); } - if (yPerSlice == 0 || yPerSlice > static_cast(mRaw->dim.y) || - roundUpDivision(mRaw->dim.y, yPerSlice) != counts->count) { + if (yPerSlice == 0 || yPerSlice > static_cast(mRaw.get(0)->dim.y) || + roundUpDivision(mRaw.get(0)->dim.y, yPerSlice) != counts->count) { ThrowRDE("Invalid y per slice %u or strip count %u (height = %u)", - yPerSlice, counts->count, mRaw->dim.y); + yPerSlice, counts->count, mRaw.get(0)->dim.y); } switch (bitPerPixel) { @@ -118,17 +118,17 @@ void RawDecoder::decodeUncompressed(const TiffIFD* rawIFD, assert(height <= offY); assert(slices.size() == counts->count); - mRaw->createData(); + mRaw.get(0)->createData(); // Default white level is (2 ** BitsPerSample) - 1 - mRaw->whitePoint = (1UL << bitPerPixel) - 1UL; + mRaw.get(0)->whitePoint = (1UL << bitPerPixel) - 1UL; offY = 0; for (const RawSlice& slice : slices) { UncompressedDecompressor u( ByteStream(DataBuffer(mFile.getSubView(slice.offset, slice.count), Endianness::little)), - mRaw); + mRaw.get(0).get()); iPoint2D size(width, slice.h); iPoint2D pos(0, offY); bitPerPixel = (static_cast(slice.count) * 8U) / (slice.h * width); @@ -160,8 +160,8 @@ bool RawDecoder::checkCameraSupported(const CameraMetaData* meta, const std::string& make, const std::string& model, const std::string& mode) { - mRaw->metadata.make = make; - mRaw->metadata.model = model; + mRaw.metadata.make = make; + mRaw.metadata.model = model; const Camera* cam = meta->getCamera(make, model, mode); if (!cam) { askForSamples(meta, make, model, mode); @@ -198,7 +198,7 @@ bool RawDecoder::checkCameraSupported(const CameraMetaData* meta, void RawDecoder::setMetaData(const CameraMetaData* meta, const std::string& make, const std::string& model, const std::string& mode, int iso_speed) { - mRaw->metadata.isoSpeed = iso_speed; + mRaw.metadata.isoSpeed = iso_speed; const Camera* cam = meta->getCamera(make, model, mode); if (!cam) { askForSamples(meta, make, model, mode); @@ -212,45 +212,45 @@ void RawDecoder::setMetaData(const CameraMetaData* meta, // Only override CFA with the data from cameras.xml if it actually contained // the CFA. if (cam->cfa.getSize().area() > 0) - mRaw->cfa = cam->cfa; + mRaw.get(0)->cfa = cam->cfa; if (!cam->color_matrix.empty()) - mRaw->metadata.colorMatrix = cam->color_matrix; + mRaw.metadata.colorMatrix = cam->color_matrix; - mRaw->metadata.canonical_make = cam->canonical_make; - mRaw->metadata.canonical_model = cam->canonical_model; - mRaw->metadata.canonical_alias = cam->canonical_alias; - mRaw->metadata.canonical_id = cam->canonical_id; - mRaw->metadata.make = make; - mRaw->metadata.model = model; - mRaw->metadata.mode = mode; + mRaw.metadata.canonical_make = cam->canonical_make; + mRaw.metadata.canonical_model = cam->canonical_model; + mRaw.metadata.canonical_alias = cam->canonical_alias; + mRaw.metadata.canonical_id = cam->canonical_id; + mRaw.metadata.make = make; + mRaw.metadata.model = model; + mRaw.metadata.mode = mode; if (applyCrop) { iPoint2D new_size = cam->cropSize; // If crop size is negative, use relative cropping if (new_size.x <= 0) - new_size.x = mRaw->dim.x - cam->cropPos.x + new_size.x; + new_size.x = mRaw.get(0)->dim.x - cam->cropPos.x + new_size.x; if (new_size.y <= 0) - new_size.y = mRaw->dim.y - cam->cropPos.y + new_size.y; + new_size.y = mRaw.get(0)->dim.y - cam->cropPos.y + new_size.y; - mRaw->subFrame(iRectangle2D(cam->cropPos, new_size)); + mRaw.get(0)->subFrame(iRectangle2D(cam->cropPos, new_size)); } const CameraSensorInfo *sensor = cam->getSensorInfo(iso_speed); - mRaw->blackLevel = sensor->mBlackLevel; - mRaw->whitePoint = sensor->mWhiteLevel; - mRaw->blackAreas = cam->blackAreas; - if (mRaw->blackAreas.empty() && !sensor->mBlackLevelSeparate.empty()) { - auto cfaArea = mRaw->cfa.getSize().area(); - if (mRaw->isCFA && cfaArea <= sensor->mBlackLevelSeparate.size()) { + mRaw.get(0)->blackLevel = sensor->mBlackLevel; + mRaw.get(0)->whitePoint = sensor->mWhiteLevel; + mRaw.get(0)->blackAreas = cam->blackAreas; + if (mRaw.get(0)->blackAreas.empty() && !sensor->mBlackLevelSeparate.empty()) { + auto cfaArea = mRaw.get(0)->cfa.getSize().area(); + if (mRaw.get(0)->isCFA && cfaArea <= sensor->mBlackLevelSeparate.size()) { for (auto i = 0UL; i < cfaArea; i++) { - mRaw->blackLevelSeparate[i] = sensor->mBlackLevelSeparate[i]; + mRaw.get(0)->blackLevelSeparate[i] = sensor->mBlackLevelSeparate[i]; } - } else if (!mRaw->isCFA && mRaw->getCpp() <= sensor->mBlackLevelSeparate.size()) { - for (uint32_t i = 0; i < mRaw->getCpp(); i++) { - mRaw->blackLevelSeparate[i] = sensor->mBlackLevelSeparate[i]; + } else if (!mRaw.get(0)->isCFA && mRaw.get(0)->getCpp() <= sensor->mBlackLevelSeparate.size()) { + for (uint32_t i = 0; i < mRaw.get(0)->getCpp(); i++) { + mRaw.get(0)->blackLevelSeparate[i] = sensor->mBlackLevelSeparate[i]; } } } @@ -263,29 +263,31 @@ void RawDecoder::setMetaData(const CameraMetaData* meta, if (!cfa_black.empty()) { vector v = splitString(cfa_black, ','); if (v.size() != 4) { - mRaw->setError("Expected 4 values '10,20,30,20' as values for " + mRaw.get(0)->setError("Expected 4 values '10,20,30,20' as values for " "override_cfa_black hint."); } else { for (int i = 0; i < 4; i++) { - mRaw->blackLevelSeparate[i] = stoi(v[i]); + mRaw.get(0)->blackLevelSeparate[i] = stoi(v[i]); } } } } -rawspeed::RawImage RawDecoder::decodeRaw() { +void RawDecoder::decodeRaw() { try { - RawImage raw = decodeRawInternal(); - raw->checkMemIsInitialized(); - - raw->metadata.pixelAspectRatio = - hints.get("pixel_aspect_ratio", raw->metadata.pixelAspectRatio); - if (interpolateBadPixels) { - raw->fixBadPixels(); + decodeRawInternal(); + /// TODO paralelize? + for (const auto &raw : mRaw) { raw->checkMemIsInitialized(); + + if (interpolateBadPixels) { + raw->fixBadPixels(); + raw->checkMemIsInitialized(); + } } + mRaw.metadata.pixelAspectRatio = + hints.get("pixel_aspect_ratio", mRaw.metadata.pixelAspectRatio); - return raw; } catch (const TiffParserException& e) { ThrowRDE("%s", e.what()); } catch (const FileIOException& e) { diff --git a/src/librawspeed/decoders/RawDecoder.h b/src/librawspeed/decoders/RawDecoder.h index dd9fb2139..a5435e674 100644 --- a/src/librawspeed/decoders/RawDecoder.h +++ b/src/librawspeed/decoders/RawDecoder.h @@ -55,7 +55,7 @@ class RawDecoder /* Attempt to decode the image */ /* A RawDecoderException will be thrown if the image cannot be decoded, */ /* and there will not be any data in the mRaw image. */ - RawImage decodeRaw(); + void decodeRaw(); /* This will apply metadata information from the camera database, */ /* such as crop, black+white level, etc. */ @@ -118,7 +118,7 @@ class RawDecoder /* A RawDecoderException will be thrown if the image cannot be decoded, */ /* and there will not be any data in the mRaw image. */ /* This function must be overridden by actual decoders. */ - virtual RawImage decodeRawInternal() = 0; + virtual void decodeRawInternal() = 0; virtual void decodeMetaDataInternal(const CameraMetaData* meta) = 0; virtual void checkSupportInternal(const CameraMetaData* meta) = 0; diff --git a/src/librawspeed/decoders/Rw2Decoder.cpp b/src/librawspeed/decoders/Rw2Decoder.cpp index b608de133..98a865e58 100644 --- a/src/librawspeed/decoders/Rw2Decoder.cpp +++ b/src/librawspeed/decoders/Rw2Decoder.cpp @@ -57,13 +57,13 @@ bool Rw2Decoder::isAppropriateDecoder(const TiffRootIFD* rootIFD, return make == "Panasonic" || make == "LEICA" || make == "LEICA CAMERA AG"; } -RawImage Rw2Decoder::decodeRawInternal() { +void Rw2Decoder::decodeRawInternal() { const TiffIFD* raw = nullptr; bool isOldPanasonic = !mRootIFD->hasEntryRecursive(TiffTag::PANASONIC_STRIPOFFSET); - if (! isOldPanasonic) + if (!isOldPanasonic) raw = mRootIFD->getIFDWithTag(TiffTag::PANASONIC_STRIPOFFSET); else raw = mRootIFD->getIFDWithTag(TiffTag::STRIPOFFSETS); @@ -84,33 +84,33 @@ RawImage Rw2Decoder::decodeRawInternal() { if (!mFile.isValid(offset)) ThrowRDE("Invalid image data offset, cannot decode."); - mRaw->dim = iPoint2D(width, height); + mRaw.get(0)->dim = iPoint2D(width, height); uint32_t size = mFile.getSize() - offset; UncompressedDecompressor u( ByteStream(DataBuffer(mFile.getSubView(offset), Endianness::little)), - mRaw); + mRaw.get(0).get()); - if (size >= width*height*2) { + if (size >= width * height * 2) { // It's completely unpacked little-endian - mRaw->createData(); + mRaw.get(0)->createData(); u.decodeRawUnpacked<12, Endianness::little>(width, height); - } else if (size >= width*height*3/2) { + } else if (size >= width * height * 3 / 2) { // It's a packed format - mRaw->createData(); + mRaw.get(0)->createData(); u.decode12BitRaw(width, height); } else { uint32_t section_split_offset = 0; PanasonicV4Decompressor p( - mRaw, + mRaw.get(0).get(), ByteStream(DataBuffer(mFile.getSubView(offset), Endianness::little)), hints.has("zero_is_not_bad"), section_split_offset); - mRaw->createData(); + mRaw.get(0)->createData(); p.decompress(); } } else { - mRaw->dim = iPoint2D(width, height); + mRaw.get(0)->dim = iPoint2D(width, height); const TiffEntry* offsets = raw->getEntry(TiffTag::PANASONIC_STRIPOFFSET); @@ -130,30 +130,28 @@ RawImage Rw2Decoder::decodeRawInternal() { raw->getEntry(TiffTag::PANASONIC_RAWFORMAT)->getU16()) { case 4: { uint32_t section_split_offset = 0x1FF8; - PanasonicV4Decompressor p(mRaw, bs, hints.has("zero_is_not_bad"), + PanasonicV4Decompressor p(mRaw.get(0).get(), bs, hints.has("zero_is_not_bad"), section_split_offset); - mRaw->createData(); + mRaw.get(0)->createData(); p.decompress(); - return mRaw; + return; } case 5: { - PanasonicV5Decompressor v5(mRaw, bs, bitsPerSample); - mRaw->createData(); + PanasonicV5Decompressor v5(mRaw.get(0).get(), bs, bitsPerSample); + mRaw.get(0)->createData(); v5.decompress(); - return mRaw; + return; } case 6: { - PanasonicV6Decompressor v6(mRaw, bs); - mRaw->createData(); + PanasonicV6Decompressor v6(mRaw.get(0).get(), bs); + mRaw.get(0)->createData(); v6.decompress(); - return mRaw; + return; } default: ThrowRDE("Version %i is unsupported", version); } } - - return mRaw; } void Rw2Decoder::checkSupportInternal(const CameraMetaData* meta) { @@ -175,19 +173,19 @@ void Rw2Decoder::parseCFA() const { switch (auto i = CFA->getU16()) { case 1: - mRaw->cfa.setCFA(iPoint2D(2, 2), CFAColor::RED, CFAColor::GREEN, + mRaw.get(0)->cfa.setCFA(iPoint2D(2, 2), CFAColor::RED, CFAColor::GREEN, CFAColor::GREEN, CFAColor::BLUE); break; case 2: - mRaw->cfa.setCFA(iPoint2D(2, 2), CFAColor::GREEN, CFAColor::RED, + mRaw.get(0)->cfa.setCFA(iPoint2D(2, 2), CFAColor::GREEN, CFAColor::RED, CFAColor::BLUE, CFAColor::GREEN); break; case 3: - mRaw->cfa.setCFA(iPoint2D(2, 2), CFAColor::GREEN, CFAColor::BLUE, + mRaw.get(0)->cfa.setCFA(iPoint2D(2, 2), CFAColor::GREEN, CFAColor::BLUE, CFAColor::RED, CFAColor::GREEN); break; case 4: - mRaw->cfa.setCFA(iPoint2D(2, 2), CFAColor::BLUE, CFAColor::GREEN, + mRaw.get(0)->cfa.setCFA(iPoint2D(2, 2), CFAColor::BLUE, CFAColor::GREEN, CFAColor::GREEN, CFAColor::RED); break; default: @@ -207,7 +205,7 @@ void Rw2Decoder::decodeMetaDataInternal(const CameraMetaData* meta) { if (this->checkCameraSupported(meta, id, mode)) { setMetaData(meta, id, mode, iso); } else { - mRaw->metadata.mode = mode; + mRaw.metadata.mode = mode; writeLog(DEBUG_PRIO::EXTRA, "Mode not found in DB: %s", mode.c_str()); setMetaData(meta, id, "", iso); } @@ -249,16 +247,16 @@ void Rw2Decoder::decodeMetaDataInternal(const CameraMetaData* meta) { for(int i = 0; i < 2; i++) { for(int j = 0; j < 2; j++) { const int k = i + 2 * j; - const CFAColor c = mRaw->cfa.getColorAt(i, j); + const CFAColor c = mRaw.get(0)->cfa.getColorAt(i, j); switch (c) { case CFAColor::RED: - mRaw->blackLevelSeparate[k] = blackRed; + mRaw.get(0)->blackLevelSeparate[k] = blackRed; break; case CFAColor::GREEN: - mRaw->blackLevelSeparate[k] = blackGreen; + mRaw.get(0)->blackLevelSeparate[k] = blackGreen; break; case CFAColor::BLUE: - mRaw->blackLevelSeparate[k] = blackBlue; + mRaw.get(0)->blackLevelSeparate[k] = blackBlue; break; default: ThrowRDE("Unexpected CFA color %s.", @@ -272,18 +270,18 @@ void Rw2Decoder::decodeMetaDataInternal(const CameraMetaData* meta) { if (raw->hasEntry(static_cast(0x0024)) && raw->hasEntry(static_cast(0x0025)) && raw->hasEntry(static_cast(0x0026))) { - mRaw->metadata.wbCoeffs[0] = static_cast( + mRaw.metadata.wbCoeffs[0] = static_cast( raw->getEntry(static_cast(0x0024))->getU16()); - mRaw->metadata.wbCoeffs[1] = static_cast( + mRaw.metadata.wbCoeffs[1] = static_cast( raw->getEntry(static_cast(0x0025))->getU16()); - mRaw->metadata.wbCoeffs[2] = static_cast( + mRaw.metadata.wbCoeffs[2] = static_cast( raw->getEntry(static_cast(0x0026))->getU16()); } else if (raw->hasEntry(static_cast(0x0011)) && raw->hasEntry(static_cast(0x0012))) { - mRaw->metadata.wbCoeffs[0] = static_cast( + mRaw.metadata.wbCoeffs[0] = static_cast( raw->getEntry(static_cast(0x0011))->getU16()); - mRaw->metadata.wbCoeffs[1] = 256.0F; - mRaw->metadata.wbCoeffs[2] = static_cast( + mRaw.metadata.wbCoeffs[1] = 256.0F; + mRaw.metadata.wbCoeffs[2] = static_cast( raw->getEntry(static_cast(0x0012))->getU16()); } } @@ -291,10 +289,10 @@ void Rw2Decoder::decodeMetaDataInternal(const CameraMetaData* meta) { std::string Rw2Decoder::guessMode() const { float ratio = 3.0F / 2.0F; // Default - if (!mRaw->isAllocated()) + if (!mRaw.get(0)->isAllocated()) return ""; - ratio = static_cast(mRaw->dim.x) / static_cast(mRaw->dim.y); + ratio = static_cast(mRaw.get(0)->dim.x) / static_cast(mRaw.get(0)->dim.y); float min_diff = fabs(ratio - 16.0F / 9.0F); std::string closest_match = "16:9"; diff --git a/src/librawspeed/decoders/Rw2Decoder.h b/src/librawspeed/decoders/Rw2Decoder.h index 77dcd4cd8..25c50b052 100644 --- a/src/librawspeed/decoders/Rw2Decoder.h +++ b/src/librawspeed/decoders/Rw2Decoder.h @@ -40,7 +40,7 @@ class Rw2Decoder final : public AbstractTiffDecoder Rw2Decoder(TiffRootIFDOwner&& root, const Buffer& file) : AbstractTiffDecoder(std::move(root), file) {} - RawImage decodeRawInternal() override; + void decodeRawInternal() override; void decodeMetaDataInternal(const CameraMetaData* meta) override; void checkSupportInternal(const CameraMetaData* meta) override; diff --git a/src/librawspeed/decoders/SimpleTiffDecoder.cpp b/src/librawspeed/decoders/SimpleTiffDecoder.cpp index de6f699a3..890fc6734 100644 --- a/src/librawspeed/decoders/SimpleTiffDecoder.cpp +++ b/src/librawspeed/decoders/SimpleTiffDecoder.cpp @@ -49,8 +49,8 @@ void SimpleTiffDecoder::prepareForRawDecoding() { checkImageDimensions(); - mRaw->dim = iPoint2D(width, height); - mRaw->createData(); + mRaw.get(0)->dim = iPoint2D(width, height); + mRaw.get(0)->createData(); } } // namespace rawspeed diff --git a/src/librawspeed/decoders/SrwDecoder.cpp b/src/librawspeed/decoders/SrwDecoder.cpp index f63a423cd..c4da8f53d 100644 --- a/src/librawspeed/decoders/SrwDecoder.cpp +++ b/src/librawspeed/decoders/SrwDecoder.cpp @@ -53,7 +53,7 @@ bool SrwDecoder::isAppropriateDecoder(const TiffRootIFD* rootIFD, return make == "SAMSUNG"; } -RawImage SrwDecoder::decodeRawInternal() { +void SrwDecoder::decodeRawInternal() { const auto* raw = mRootIFD->getIFDWithTag(TiffTag::STRIPOFFSETS); int compression = raw->getEntry(TiffTag::COMPRESSION)->getU32(); @@ -62,7 +62,8 @@ RawImage SrwDecoder::decodeRawInternal() { if (12 != bits && 14 != bits) ThrowRDE("Unsupported bits per sample"); - if (32769 != compression && 32770 != compression && 32772 != compression && 32773 != compression) + if (32769 != compression && 32770 != compression && 32772 != compression && + 32773 != compression) ThrowRDE("Unsupported compression"); if (uint32_t nslices = raw->getEntry(TiffTag::STRIPOFFSETS)->count; @@ -74,15 +75,14 @@ RawImage SrwDecoder::decodeRawInternal() { 32769 == compression || wrongComp) { bool bit_order = hints.get("msb_override", wrongComp ? bits == 12 : false); this->decodeUncompressed(raw, bit_order ? BitOrder::MSB : BitOrder::LSB); - return mRaw; + return; } const uint32_t width = raw->getEntry(TiffTag::IMAGEWIDTH)->getU32(); const uint32_t height = raw->getEntry(TiffTag::IMAGELENGTH)->getU32(); - mRaw->dim = iPoint2D(width, height); + mRaw.get(0)->dim = iPoint2D(width, height); - if (32770 == compression) - { + if (32770 == compression) { const TiffEntry* sliceOffsets = raw->getEntry(static_cast(40976)); if (sliceOffsets->type != TiffDataType::LONG || sliceOffsets->count != 1) ThrowRDE("Entry 40976 is corrupt"); @@ -96,43 +96,41 @@ RawImage SrwDecoder::decodeRawInternal() { Buffer rbuf(mFile.getSubView(offset, count)); ByteStream bsr(DataBuffer(rbuf, Endianness::little)); - SamsungV0Decompressor s0(mRaw, bso, bsr); + SamsungV0Decompressor s0(mRaw.get(0).get(), bso, bsr); - mRaw->createData(); + mRaw.get(0)->createData(); s0.decompress(); - return mRaw; + return; } - if (32772 == compression) - { + if (32772 == compression) { uint32_t offset = raw->getEntry(TiffTag::STRIPOFFSETS)->getU32(); uint32_t count = raw->getEntry(TiffTag::STRIPBYTECOUNTS)->getU32(); const ByteStream bs( DataBuffer(mFile.getSubView(offset, count), Endianness::little)); - SamsungV1Decompressor s1(mRaw, bs, bits); + SamsungV1Decompressor s1(mRaw.get(0).get(), bs, bits); - mRaw->createData(); + mRaw.get(0)->createData(); s1.decompress(); - return mRaw; + return; } - if (32773 == compression) - { + if (32773 == compression) { uint32_t offset = raw->getEntry(TiffTag::STRIPOFFSETS)->getU32(); uint32_t count = raw->getEntry(TiffTag::STRIPBYTECOUNTS)->getU32(); const ByteStream bs( DataBuffer(mFile.getSubView(offset, count), Endianness::little)); - SamsungV2Decompressor s2(mRaw, bs, bits); + SamsungV2Decompressor s2(mRaw.get(0).get(), bs, bits); - mRaw->createData(); + mRaw.get(0)->createData(); s2.decompress(); - return mRaw; + return; } ThrowRDE("Unsupported compression"); } @@ -177,9 +175,9 @@ void SrwDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { const TiffEntry* wb_black = mRootIFD->getEntryRecursive(TiffTag::SAMSUNG_WB_RGGBLEVELSBLACK); if (wb_levels->count == 4 && wb_black->count == 4) { - mRaw->metadata.wbCoeffs[0] = wb_levels->getFloat(0) - wb_black->getFloat(0); - mRaw->metadata.wbCoeffs[1] = wb_levels->getFloat(1) - wb_black->getFloat(1); - mRaw->metadata.wbCoeffs[2] = wb_levels->getFloat(3) - wb_black->getFloat(3); + mRaw.metadata.wbCoeffs[0] = wb_levels->getFloat(0) - wb_black->getFloat(0); + mRaw.metadata.wbCoeffs[1] = wb_levels->getFloat(1) - wb_black->getFloat(1); + mRaw.metadata.wbCoeffs[2] = wb_levels->getFloat(3) - wb_black->getFloat(3); } } } diff --git a/src/librawspeed/decoders/SrwDecoder.h b/src/librawspeed/decoders/SrwDecoder.h index f17a19793..e77907873 100644 --- a/src/librawspeed/decoders/SrwDecoder.h +++ b/src/librawspeed/decoders/SrwDecoder.h @@ -39,7 +39,7 @@ class SrwDecoder final : public AbstractTiffDecoder SrwDecoder(TiffRootIFDOwner&& root, const Buffer& file) : AbstractTiffDecoder(std::move(root), file) {} - RawImage decodeRawInternal() override; + void decodeRawInternal() override; void decodeMetaDataInternal(const CameraMetaData* meta) override; void checkSupportInternal(const CameraMetaData* meta) override; diff --git a/src/librawspeed/decoders/ThreefrDecoder.cpp b/src/librawspeed/decoders/ThreefrDecoder.cpp index 13eeb5ad0..209360fe6 100644 --- a/src/librawspeed/decoders/ThreefrDecoder.cpp +++ b/src/librawspeed/decoders/ThreefrDecoder.cpp @@ -50,7 +50,7 @@ bool ThreefrDecoder::isAppropriateDecoder(const TiffRootIFD* rootIFD, return make == "Hasselblad"; } -RawImage ThreefrDecoder::decodeRawInternal() { +void ThreefrDecoder::decodeRawInternal() { const auto* raw = mRootIFD->getIFDWithTag(TiffTag::STRIPOFFSETS, 1); uint32_t width = raw->getEntry(TiffTag::IMAGEWIDTH)->getU32(); uint32_t height = raw->getEntry(TiffTag::IMAGELENGTH)->getU32(); @@ -59,19 +59,17 @@ RawImage ThreefrDecoder::decodeRawInternal() { const ByteStream bs(DataBuffer(mFile.getSubView(off), Endianness::little)); - mRaw->dim = iPoint2D(width, height); + mRaw.get(0)->dim = iPoint2D(width, height); - HasselbladDecompressor l(bs, mRaw); - mRaw->createData(); + HasselbladDecompressor l(bs, mRaw.get(0).get()); + mRaw.get(0)->createData(); int pixelBaseOffset = hints.get("pixelBaseOffset", 0); l.decode(pixelBaseOffset); - - return mRaw; } void ThreefrDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { - mRaw->cfa.setCFA(iPoint2D(2, 2), CFAColor::RED, CFAColor::GREEN, + mRaw.get(0)->cfa.setCFA(iPoint2D(2, 2), CFAColor::RED, CFAColor::GREEN, CFAColor::GREEN, CFAColor::BLUE); setMetaData(meta, "", 0); @@ -79,13 +77,13 @@ void ThreefrDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { if (mRootIFD->hasEntryRecursive(TiffTag::BLACKLEVEL)) { const TiffEntry* bl = mRootIFD->getEntryRecursive(TiffTag::BLACKLEVEL); if (bl->count == 1) - mRaw->blackLevel = bl->getFloat(); + mRaw.get(0)->blackLevel = bl->getFloat(); } if (mRootIFD->hasEntryRecursive(TiffTag::WHITELEVEL)) { const TiffEntry* wl = mRootIFD->getEntryRecursive(TiffTag::WHITELEVEL); if (wl->count == 1) - mRaw->whitePoint = wl->getFloat(); + mRaw.get(0)->whitePoint = wl->getFloat(); } // Fetch the white balance @@ -97,7 +95,7 @@ void ThreefrDecoder::decodeMetaDataInternal(const CameraMetaData* meta) { if (div == 0.0F) ThrowRDE("Can not decode WB, multiplier is zero/"); - mRaw->metadata.wbCoeffs[i] = 1.0F / div; + mRaw.metadata.wbCoeffs[i] = 1.0F / div; } } } diff --git a/src/librawspeed/decoders/ThreefrDecoder.h b/src/librawspeed/decoders/ThreefrDecoder.h index 1b45c9a56..6035d0570 100644 --- a/src/librawspeed/decoders/ThreefrDecoder.h +++ b/src/librawspeed/decoders/ThreefrDecoder.h @@ -39,7 +39,7 @@ class ThreefrDecoder final : public AbstractTiffDecoder ThreefrDecoder(TiffRootIFDOwner&& root, const Buffer& file) : AbstractTiffDecoder(std::move(root), file) {} - RawImage decodeRawInternal() override; + void decodeRawInternal() override; void decodeMetaDataInternal(const CameraMetaData* meta) override; private: diff --git a/src/librawspeed/decompressors/AbstractDngDecompressor.h b/src/librawspeed/decompressors/AbstractDngDecompressor.h index 2a54521d0..3cf9fa596 100644 --- a/src/librawspeed/decompressors/AbstractDngDecompressor.h +++ b/src/librawspeed/decompressors/AbstractDngDecompressor.h @@ -122,14 +122,14 @@ struct DngSliceElement final { }; class AbstractDngDecompressor final : public AbstractDecompressor { - RawImage mRaw; + RawImageData* mRaw; template void decompressThread() const noexcept; void decompressThread() const noexcept; public: - AbstractDngDecompressor(const RawImage& img, const DngTilingDescription& dsc_, + AbstractDngDecompressor(RawImageData* img, const DngTilingDescription& dsc_, int compression_, bool mFixLjpeg_, uint32_t mBps_, uint32_t mPredictor_) : mRaw(img), dsc(dsc_), compression(compression_), mFixLjpeg(mFixLjpeg_), diff --git a/src/librawspeed/decompressors/AbstractLJpegDecompressor.cpp b/src/librawspeed/decompressors/AbstractLJpegDecompressor.cpp index 398099111..a1a913816 100644 --- a/src/librawspeed/decompressors/AbstractLJpegDecompressor.cpp +++ b/src/librawspeed/decompressors/AbstractLJpegDecompressor.cpp @@ -36,7 +36,7 @@ namespace rawspeed { AbstractLJpegDecompressor::AbstractLJpegDecompressor(ByteStream bs, - const RawImage& img) + RawImageData *img) : input(std::move(bs)), mRaw(img) { input.setByteOrder(Endianness::big); @@ -158,8 +158,8 @@ void AbstractLJpegDecompressor::parseSOF(ByteStream sofInput, SOFInfo* sof) { } if (static_cast(sof->compInfo[0].superH) != - mRaw->metadata.subsampling.x || - static_cast(sof->compInfo[0].superV) != mRaw->metadata.subsampling.y) + mRaw->subsampling.x || + static_cast(sof->compInfo[0].superV) != mRaw->subsampling.y) ThrowRDE("LJpeg's subsampling does not match image's subsampling."); sof->initialized = true; diff --git a/src/librawspeed/decompressors/AbstractLJpegDecompressor.h b/src/librawspeed/decompressors/AbstractLJpegDecompressor.h index 0f9ad2d87..ca5bfa983 100644 --- a/src/librawspeed/decompressors/AbstractLJpegDecompressor.h +++ b/src/librawspeed/decompressors/AbstractLJpegDecompressor.h @@ -155,7 +155,7 @@ class AbstractLJpegDecompressor : public AbstractDecompressor { std::array huff{{}}; // 4 pointers into the store public: - AbstractLJpegDecompressor(ByteStream bs, const RawImage& img); + AbstractLJpegDecompressor(ByteStream bs, RawImageData* img); virtual ~AbstractLJpegDecompressor() = default; @@ -201,7 +201,7 @@ class AbstractLJpegDecompressor : public AbstractDecompressor { virtual void decodeScan() = 0; ByteStream input; - RawImage mRaw; + RawImageData* mRaw; SOFInfo frame; uint32_t predictorMode = 0; diff --git a/src/librawspeed/decompressors/AbstractSamsungDecompressor.h b/src/librawspeed/decompressors/AbstractSamsungDecompressor.h index 653e1be56..cec011a80 100644 --- a/src/librawspeed/decompressors/AbstractSamsungDecompressor.h +++ b/src/librawspeed/decompressors/AbstractSamsungDecompressor.h @@ -27,10 +27,10 @@ namespace rawspeed { class AbstractSamsungDecompressor : public AbstractDecompressor { protected: - RawImage mRaw; + RawImageData* mRaw; public: - explicit AbstractSamsungDecompressor(const RawImage& raw) : mRaw(raw) {} + explicit AbstractSamsungDecompressor(RawImageData* raw) : mRaw(raw) {} }; } // namespace rawspeed diff --git a/src/librawspeed/decompressors/Cr2Decompressor.cpp b/src/librawspeed/decompressors/Cr2Decompressor.cpp index 19e875b3c..ccd862121 100644 --- a/src/librawspeed/decompressors/Cr2Decompressor.cpp +++ b/src/librawspeed/decompressors/Cr2Decompressor.cpp @@ -35,7 +35,7 @@ namespace rawspeed { class ByteStream; -Cr2Decompressor::Cr2Decompressor(const ByteStream& bs, const RawImage& img) +Cr2Decompressor::Cr2Decompressor(const ByteStream& bs, RawImageData *img) : AbstractLJpegDecompressor(bs, img) { if (mRaw->getDataType() != RawImageType::UINT16) ThrowRDE("Unexpected data type"); @@ -131,7 +131,9 @@ void Cr2Decompressor::decode(const Cr2Slicing& slicing_) { template void Cr2Decompressor::decodeN_X_Y() { - const Array2DRef out(mRaw->getU16DataAsUncroppedArray2DRef()); + auto *rawU16 = dynamic_cast(mRaw); + assert(rawU16); + const Array2DRef out(rawU16->getU16DataAsUncroppedArray2DRef()); // To understand the CR2 slice handling and sampling factor behavior, see // https://github.com/lclevy/libcraw2/blob/master/docs/cr2_lossless.pdf?raw=true diff --git a/src/librawspeed/decompressors/Cr2Decompressor.h b/src/librawspeed/decompressors/Cr2Decompressor.h index 2dff5af22..64cf17f31 100644 --- a/src/librawspeed/decompressors/Cr2Decompressor.h +++ b/src/librawspeed/decompressors/Cr2Decompressor.h @@ -29,7 +29,6 @@ namespace rawspeed { class ByteStream; -class RawImage; class Cr2Slicing { int numSlices = 0; @@ -77,7 +76,7 @@ class Cr2Decompressor final : public AbstractLJpegDecompressor template void decodeN_X_Y(); public: - Cr2Decompressor(const ByteStream& bs, const RawImage& img); + Cr2Decompressor(const ByteStream& bs, RawImageData* img); void decode(const Cr2Slicing& slicing); }; diff --git a/src/librawspeed/decompressors/CrwDecompressor.cpp b/src/librawspeed/decompressors/CrwDecompressor.cpp index b558ac392..1f4c8075c 100644 --- a/src/librawspeed/decompressors/CrwDecompressor.cpp +++ b/src/librawspeed/decompressors/CrwDecompressor.cpp @@ -38,7 +38,7 @@ using std::array; namespace rawspeed { -CrwDecompressor::CrwDecompressor(const RawImage& img, uint32_t dec_table, +CrwDecompressor::CrwDecompressor(RawImageData* img, uint32_t dec_table, bool lowbits_, ByteStream rawData) : mRaw(img), lowbits(lowbits_) { if (mRaw->getCpp() != 1 || mRaw->getDataType() != RawImageType::UINT16 || @@ -204,7 +204,9 @@ inline void CrwDecompressor::decodeBlock(std::array* diffBuf, // FIXME: this function is horrible. void CrwDecompressor::decompress() { - const Array2DRef out(mRaw->getU16DataAsUncroppedArray2DRef()); + auto *rawU16 = dynamic_cast(mRaw); + assert(rawU16); + const Array2DRef out(rawU16->getU16DataAsUncroppedArray2DRef()); assert(out.width > 0); assert(out.width % 4 == 0); assert(out.height > 0); diff --git a/src/librawspeed/decompressors/CrwDecompressor.h b/src/librawspeed/decompressors/CrwDecompressor.h index 7ffcd7371..9d1b0aaf6 100644 --- a/src/librawspeed/decompressors/CrwDecompressor.h +++ b/src/librawspeed/decompressors/CrwDecompressor.h @@ -35,7 +35,7 @@ namespace rawspeed { class CrwDecompressor final : public AbstractDecompressor { using crw_hts = std::array; - RawImage mRaw; + RawImageData* mRaw; crw_hts mHuff; const bool lowbits; @@ -43,7 +43,7 @@ class CrwDecompressor final : public AbstractDecompressor { ByteStream rawInput; public: - CrwDecompressor(const RawImage& img, uint32_t dec_table_, bool lowbits_, + CrwDecompressor(RawImageData *img, uint32_t dec_table_, bool lowbits_, ByteStream rawData); void decompress(); diff --git a/src/librawspeed/decompressors/DeflateDecompressor.h b/src/librawspeed/decompressors/DeflateDecompressor.h index fb835935e..962d3b0a9 100644 --- a/src/librawspeed/decompressors/DeflateDecompressor.h +++ b/src/librawspeed/decompressors/DeflateDecompressor.h @@ -36,12 +36,12 @@ class iPoint2D; class DeflateDecompressor final : public AbstractDecompressor { ByteStream input; - RawImage mRaw; + RawImageData* mRaw; int predictor; int bps; public: - DeflateDecompressor(ByteStream bs, const RawImage& img, int predictor_, + DeflateDecompressor(ByteStream bs, RawImageData* img, int predictor_, int bps_) : input(std::move(bs)), mRaw(img), predictor(predictor_), bps(bps_) {} diff --git a/src/librawspeed/decompressors/FujiDecompressor.cpp b/src/librawspeed/decompressors/FujiDecompressor.cpp index b92a23cb6..ab0baa9ba 100644 --- a/src/librawspeed/decompressors/FujiDecompressor.cpp +++ b/src/librawspeed/decompressors/FujiDecompressor.cpp @@ -39,7 +39,7 @@ namespace rawspeed { -FujiDecompressor::FujiDecompressor(const RawImage& img, ByteStream input_) +FujiDecompressor::FujiDecompressor(RawImageData *img, ByteStream input_) : mRaw(img), input(std::move(input_)) { if (mRaw->getCpp() != 1 || mRaw->getDataType() != RawImageType::UINT16 || mRaw->getBpp() != sizeof(uint16_t)) @@ -178,7 +178,9 @@ template void FujiDecompressor::copy_line(fuji_compressed_block* info, const FujiStrip& strip, int cur_line, T&& idx) const { - const Array2DRef out(mRaw->getU16DataAsUncroppedArray2DRef()); + auto *rawU16 = dynamic_cast(mRaw); + assert(rawU16); + const Array2DRef out(rawU16->getU16DataAsUncroppedArray2DRef()); std::array lineBufB; std::array lineBufG; diff --git a/src/librawspeed/decompressors/FujiDecompressor.h b/src/librawspeed/decompressors/FujiDecompressor.h index 1cc30191a..506168f10 100644 --- a/src/librawspeed/decompressors/FujiDecompressor.h +++ b/src/librawspeed/decompressors/FujiDecompressor.h @@ -35,7 +35,7 @@ namespace rawspeed { class FujiDecompressor final : public AbstractDecompressor { - RawImage mRaw; + RawImageData* mRaw; void decompressThread() const noexcept; @@ -110,7 +110,7 @@ class FujiDecompressor final : public AbstractDecompressor { [[nodiscard]] int offsetX() const { return h.block_size * n; } }; - FujiDecompressor(const RawImage& img, ByteStream input); + FujiDecompressor(RawImageData* img, ByteStream input); void fuji_compressed_load_raw(); diff --git a/src/librawspeed/decompressors/HasselbladDecompressor.cpp b/src/librawspeed/decompressors/HasselbladDecompressor.cpp index 8b5e30bc0..e8e92be50 100644 --- a/src/librawspeed/decompressors/HasselbladDecompressor.cpp +++ b/src/librawspeed/decompressors/HasselbladDecompressor.cpp @@ -34,7 +34,7 @@ namespace rawspeed { HasselbladDecompressor::HasselbladDecompressor(const ByteStream& bs, - const RawImage& img) + RawImageData* img) : AbstractLJpegDecompressor(bs, img) { if (mRaw->getCpp() != 1 || mRaw->getDataType() != RawImageType::UINT16 || mRaw->getBpp() != sizeof(uint16_t)) @@ -67,7 +67,9 @@ void HasselbladDecompressor::decodeScan() { frame.w, frame.h, mRaw->dim.x, mRaw->dim.y); } - const Array2DRef out(mRaw->getU16DataAsUncroppedArray2DRef()); + auto *rawU16 = dynamic_cast(mRaw); + assert(rawU16); + const Array2DRef out(rawU16->getU16DataAsUncroppedArray2DRef()); assert(out.height > 0); assert(out.width > 0); diff --git a/src/librawspeed/decompressors/HasselbladDecompressor.h b/src/librawspeed/decompressors/HasselbladDecompressor.h index e259fe151..47f2802eb 100644 --- a/src/librawspeed/decompressors/HasselbladDecompressor.h +++ b/src/librawspeed/decompressors/HasselbladDecompressor.h @@ -27,7 +27,6 @@ namespace rawspeed { class ByteStream; -class RawImage; class HasselbladDecompressor final : public AbstractLJpegDecompressor { @@ -36,7 +35,7 @@ class HasselbladDecompressor final : public AbstractLJpegDecompressor void decodeScan() override; public: - HasselbladDecompressor(const ByteStream& bs, const RawImage& img); + HasselbladDecompressor(const ByteStream& bs, RawImageData *img); void decode(int pixelBaseOffset_); diff --git a/src/librawspeed/decompressors/JpegDecompressor.cpp b/src/librawspeed/decompressors/JpegDecompressor.cpp index 1b6fd4461..c5f490c4f 100644 --- a/src/librawspeed/decompressors/JpegDecompressor.cpp +++ b/src/librawspeed/decompressors/JpegDecompressor.cpp @@ -154,7 +154,9 @@ void JpegDecompressor::decode(uint32_t offX, int copy_w = min(mRaw->dim.x - offX, dinfo.output_width); int copy_h = min(mRaw->dim.y - offY, dinfo.output_height); - const Array2DRef out(mRaw->getU16DataAsUncroppedArray2DRef()); + auto *rawU16 = dynamic_cast(mRaw); + assert(rawU16); + const Array2DRef out(rawU16->getU16DataAsUncroppedArray2DRef()); for (int row = 0; row < copy_h; row++) { for (int col = 0; col < dinfo.output_components * copy_w; col++) out(row + offY, dinfo.output_components * offX + col) = tmp(row, col); diff --git a/src/librawspeed/decompressors/JpegDecompressor.h b/src/librawspeed/decompressors/JpegDecompressor.h index cd0362fee..1a6733aca 100644 --- a/src/librawspeed/decompressors/JpegDecompressor.h +++ b/src/librawspeed/decompressors/JpegDecompressor.h @@ -36,10 +36,10 @@ namespace rawspeed { class JpegDecompressor final : public AbstractDecompressor { struct JpegDecompressStruct; ByteStream input; - RawImage mRaw; + RawImageData* mRaw; public: - JpegDecompressor(ByteStream bs, const RawImage& img) + JpegDecompressor(ByteStream bs, RawImageData* img) : input(std::move(bs)), mRaw(img) { input.setByteOrder(Endianness::big); } diff --git a/src/librawspeed/decompressors/KodakDecompressor.cpp b/src/librawspeed/decompressors/KodakDecompressor.cpp index 34268ebdc..24b61890a 100644 --- a/src/librawspeed/decompressors/KodakDecompressor.cpp +++ b/src/librawspeed/decompressors/KodakDecompressor.cpp @@ -36,7 +36,7 @@ namespace rawspeed { -KodakDecompressor::KodakDecompressor(const RawImage& img, ByteStream bs, +KodakDecompressor::KodakDecompressor(RawImageData *img, ByteStream bs, int bps_, bool uncorrectedRawValues_) : mRaw(img), input(std::move(bs)), bps(bps_), uncorrectedRawValues(uncorrectedRawValues_) { @@ -110,7 +110,9 @@ KodakDecompressor::decodeSegment(const uint32_t bsize) { } void KodakDecompressor::decompress() { - const Array2DRef out(mRaw->getU16DataAsUncroppedArray2DRef()); + auto *rawU16 = dynamic_cast(mRaw); + assert(rawU16); + const Array2DRef out(rawU16->getU16DataAsUncroppedArray2DRef()); uint32_t random = 0; for (int row = 0; row < out.height; row++) { diff --git a/src/librawspeed/decompressors/KodakDecompressor.h b/src/librawspeed/decompressors/KodakDecompressor.h index 0e0db494e..6a01f9323 100644 --- a/src/librawspeed/decompressors/KodakDecompressor.h +++ b/src/librawspeed/decompressors/KodakDecompressor.h @@ -31,7 +31,7 @@ namespace rawspeed { class KodakDecompressor final : public AbstractDecompressor { - RawImage mRaw; + RawImageData* mRaw; ByteStream input; int bps; bool uncorrectedRawValues; @@ -42,7 +42,7 @@ class KodakDecompressor final : public AbstractDecompressor { segment decodeSegment(uint32_t bsize); public: - KodakDecompressor(const RawImage& img, ByteStream bs, int bps, + KodakDecompressor(RawImageData* img, ByteStream bs, int bps, bool uncorrectedRawValues_); void decompress(); diff --git a/src/librawspeed/decompressors/LJpegDecompressor.cpp b/src/librawspeed/decompressors/LJpegDecompressor.cpp index ee67989b9..b6916badb 100644 --- a/src/librawspeed/decompressors/LJpegDecompressor.cpp +++ b/src/librawspeed/decompressors/LJpegDecompressor.cpp @@ -33,7 +33,7 @@ using std::copy_n; namespace rawspeed { -LJpegDecompressor::LJpegDecompressor(const ByteStream& bs, const RawImage& img) +LJpegDecompressor::LJpegDecompressor(const ByteStream& bs, RawImageData* img) : AbstractLJpegDecompressor(bs, img) { if (mRaw->getDataType() != RawImageType::UINT16) ThrowRDE("Unexpected data type (%u)", @@ -167,7 +167,9 @@ template void LJpegDecompressor::decodeN() { assert(mRaw->dim.x >= N_COMP); assert((mRaw->getCpp() * (mRaw->dim.x - offX)) >= N_COMP); - const CroppedArray2DRef img(mRaw->getU16DataAsUncroppedArray2DRef(), + auto *rawU16 = dynamic_cast(mRaw); + assert(rawU16); + const CroppedArray2DRef img(rawU16->getU16DataAsUncroppedArray2DRef(), mRaw->getCpp() * offX, offY, mRaw->getCpp() * w, h); diff --git a/src/librawspeed/decompressors/LJpegDecompressor.h b/src/librawspeed/decompressors/LJpegDecompressor.h index 2dd7f2540..76333b26d 100644 --- a/src/librawspeed/decompressors/LJpegDecompressor.h +++ b/src/librawspeed/decompressors/LJpegDecompressor.h @@ -26,7 +26,6 @@ namespace rawspeed { class ByteStream; -class RawImage; // Decompresses Lossless JPEGs, with 2-4 components @@ -44,7 +43,7 @@ class LJpegDecompressor final : public AbstractLJpegDecompressor uint32_t trailingPixels = 0; public: - LJpegDecompressor(const ByteStream& bs, const RawImage& img); + LJpegDecompressor(const ByteStream& bs, RawImageData *img); void decode(uint32_t offsetX, uint32_t offsetY, uint32_t width, uint32_t height, bool fixDng16Bug_); diff --git a/src/librawspeed/decompressors/NikonDecompressor.cpp b/src/librawspeed/decompressors/NikonDecompressor.cpp index 95bf018f2..e1975ec28 100644 --- a/src/librawspeed/decompressors/NikonDecompressor.cpp +++ b/src/librawspeed/decompressors/NikonDecompressor.cpp @@ -441,7 +441,7 @@ Huffman NikonDecompressor::createHuffmanTable(uint32_t huffSelect) { return ht; } -NikonDecompressor::NikonDecompressor(const RawImage& raw, ByteStream metadata, +NikonDecompressor::NikonDecompressor(RawImageData *raw, ByteStream metadata, uint32_t bitsPS_) : mRaw(raw), bitsPS(bitsPS_) { if (mRaw->getCpp() != 1 || mRaw->getDataType() != RawImageType::UINT16 || @@ -490,10 +490,12 @@ template void NikonDecompressor::decompress(BitPumpMSB& bits, int start_y, int end_y) { auto ht = createHuffmanTable(huffSelect); - const Array2DRef out(mRaw->getU16DataAsUncroppedArray2DRef()); + auto *rawU16 = dynamic_cast(mRaw); + assert(rawU16); + const Array2DRef out(rawU16->getU16DataAsUncroppedArray2DRef()); - // allow gcc to devirtualize the calls below - auto* rawdata = reinterpret_cast(mRaw.get()); + auto* rawdata = dynamic_cast(mRaw); + assert(rawdata); assert(out.width % 2 == 0); assert(out.width >= 2); @@ -512,7 +514,7 @@ void NikonDecompressor::decompress(BitPumpMSB& bits, int start_y, int end_y) { void NikonDecompressor::decompress(const ByteStream& data, bool uncorrectedRawValues) { - RawImageCurveGuard curveHandler(&mRaw, curve, uncorrectedRawValues); + RawImageCurveGuard curveHandler(mRaw, curve, uncorrectedRawValues); BitPumpMSB bits(data); diff --git a/src/librawspeed/decompressors/NikonDecompressor.h b/src/librawspeed/decompressors/NikonDecompressor.h index 1a7095b40..6db175804 100644 --- a/src/librawspeed/decompressors/NikonDecompressor.h +++ b/src/librawspeed/decompressors/NikonDecompressor.h @@ -34,7 +34,7 @@ class ByteStream; namespace rawspeed { class NikonDecompressor final : public AbstractDecompressor { - RawImage mRaw; + RawImageData* mRaw; uint32_t bitsPS; uint32_t huffSelect = 0; @@ -47,7 +47,7 @@ class NikonDecompressor final : public AbstractDecompressor { uint32_t random; public: - NikonDecompressor(const RawImage& raw, ByteStream metadata, uint32_t bitsPS); + NikonDecompressor(RawImageData* raw, ByteStream metadata, uint32_t bitsPS); void decompress(const ByteStream& data, bool uncorrectedRawValues); diff --git a/src/librawspeed/decompressors/OlympusDecompressor.cpp b/src/librawspeed/decompressors/OlympusDecompressor.cpp index 4d7d713fd..a86c507b0 100644 --- a/src/librawspeed/decompressors/OlympusDecompressor.cpp +++ b/src/librawspeed/decompressors/OlympusDecompressor.cpp @@ -48,7 +48,7 @@ constexpr __attribute__((const)) bool SignBit(T x) { namespace rawspeed { -OlympusDecompressor::OlympusDecompressor(const RawImage& img) : mRaw(img) { +OlympusDecompressor::OlympusDecompressor(RawImageData *img) : mRaw(img) { if (mRaw->getCpp() != 1 || mRaw->getDataType() != RawImageType::UINT16 || mRaw->getBpp() != sizeof(uint16_t)) ThrowRDE("Unexpected component count / data type"); @@ -137,7 +137,9 @@ void OlympusDecompressor::decompressRow(BitPumpMSB& bits, int row) const { assert(mRaw->dim.x > 0); assert(mRaw->dim.x % 2 == 0); - const Array2DRef out(mRaw->getU16DataAsUncroppedArray2DRef()); + auto *rawU16 = dynamic_cast(mRaw); + assert(rawU16); + const Array2DRef out(rawU16->getU16DataAsUncroppedArray2DRef()); std::array, 2> acarry{{}}; diff --git a/src/librawspeed/decompressors/OlympusDecompressor.h b/src/librawspeed/decompressors/OlympusDecompressor.h index 3c3e8615e..f6661efde 100644 --- a/src/librawspeed/decompressors/OlympusDecompressor.h +++ b/src/librawspeed/decompressors/OlympusDecompressor.h @@ -36,7 +36,7 @@ class ByteStream; template class Array2DRef; class OlympusDecompressor final : public AbstractDecompressor { - RawImage mRaw; + RawImageData* mRaw; // A table to quickly look up "high" value const SimpleLUT bittable{ @@ -56,7 +56,7 @@ class OlympusDecompressor final : public AbstractDecompressor { void decompressRow(BitPumpMSB& bits, int row) const; public: - explicit OlympusDecompressor(const RawImage& img); + explicit OlympusDecompressor(RawImageData* img); void decompress(ByteStream input) const; }; diff --git a/src/librawspeed/decompressors/PanasonicV4Decompressor.cpp b/src/librawspeed/decompressors/PanasonicV4Decompressor.cpp index 4c7dd05e6..bf42ccdad 100644 --- a/src/librawspeed/decompressors/PanasonicV4Decompressor.cpp +++ b/src/librawspeed/decompressors/PanasonicV4Decompressor.cpp @@ -41,7 +41,7 @@ namespace rawspeed { -PanasonicV4Decompressor::PanasonicV4Decompressor(const RawImage& img, +PanasonicV4Decompressor::PanasonicV4Decompressor(RawImageData* img, const ByteStream& input_, bool zero_is_not_bad, uint32_t section_split_offset_) @@ -166,7 +166,9 @@ class PanasonicV4Decompressor::ProxyStream { inline void PanasonicV4Decompressor::processPixelPacket( ProxyStream& bits, int row, int col, std::vector* zero_pos) const noexcept { - const Array2DRef out(mRaw->getU16DataAsUncroppedArray2DRef()); + auto *rawU16 = dynamic_cast(mRaw); + assert(rawU16); + const Array2DRef out(rawU16->getU16DataAsUncroppedArray2DRef()); int sh = 0; diff --git a/src/librawspeed/decompressors/PanasonicV4Decompressor.h b/src/librawspeed/decompressors/PanasonicV4Decompressor.h index fb6b24b75..68af6afca 100644 --- a/src/librawspeed/decompressors/PanasonicV4Decompressor.h +++ b/src/librawspeed/decompressors/PanasonicV4Decompressor.h @@ -43,7 +43,7 @@ class PanasonicV4Decompressor final : public AbstractDecompressor { class ProxyStream; - RawImage mRaw; + RawImageData* mRaw; ByteStream input; bool zero_is_bad; @@ -83,7 +83,7 @@ class PanasonicV4Decompressor final : public AbstractDecompressor { void decompressThread() const noexcept; public: - PanasonicV4Decompressor(const RawImage& img, const ByteStream& input_, + PanasonicV4Decompressor(RawImageData* img, const ByteStream& input_, bool zero_is_not_bad, uint32_t section_split_offset_); void decompress() const noexcept; diff --git a/src/librawspeed/decompressors/PanasonicV5Decompressor.cpp b/src/librawspeed/decompressors/PanasonicV5Decompressor.cpp index 6a7f936c8..a20db0108 100644 --- a/src/librawspeed/decompressors/PanasonicV5Decompressor.cpp +++ b/src/librawspeed/decompressors/PanasonicV5Decompressor.cpp @@ -59,7 +59,7 @@ constexpr PanasonicV5Decompressor::PacketDsc PanasonicV5Decompressor::FourteenBitPacket = PanasonicV5Decompressor::PacketDsc(/*bps=*/14); -PanasonicV5Decompressor::PanasonicV5Decompressor(const RawImage& img, +PanasonicV5Decompressor::PanasonicV5Decompressor(RawImageData *img, const ByteStream& input_, uint32_t bps_) : mRaw(img), bps(bps_) { @@ -181,7 +181,9 @@ inline void PanasonicV5Decompressor::processPixelPacket(BitPumpLSB& bs, int row, static_assert(dsc.pixelsPerPacket > 0, "dsc should be compile-time const"); static_assert(dsc.bps > 0 && dsc.bps <= 16); - const Array2DRef out(mRaw->getU16DataAsUncroppedArray2DRef()); + auto *rawU16 = dynamic_cast(mRaw); + assert(rawU16); + const Array2DRef out(rawU16->getU16DataAsUncroppedArray2DRef()); assert(bs.getFillLevel() == 0); diff --git a/src/librawspeed/decompressors/PanasonicV5Decompressor.h b/src/librawspeed/decompressors/PanasonicV5Decompressor.h index 77fcd07eb..842a51d3c 100644 --- a/src/librawspeed/decompressors/PanasonicV5Decompressor.h +++ b/src/librawspeed/decompressors/PanasonicV5Decompressor.h @@ -63,7 +63,7 @@ class PanasonicV5Decompressor final : public AbstractDecompressor { // Takes care of unsplitting&swapping back the block at sectionSplitOffset. class ProxyStream; - RawImage mRaw; + RawImageData* mRaw; // The full input buffer, containing all the blocks. ByteStream input; @@ -98,7 +98,7 @@ class PanasonicV5Decompressor final : public AbstractDecompressor { template void decompressInternal() const noexcept; public: - PanasonicV5Decompressor(const RawImage& img, const ByteStream& input_, + PanasonicV5Decompressor(RawImageData* img, const ByteStream& input_, uint32_t bps_); void decompress() const noexcept; diff --git a/src/librawspeed/decompressors/PanasonicV6Decompressor.cpp b/src/librawspeed/decompressors/PanasonicV6Decompressor.cpp index 85f3ef3fd..57b5605b1 100644 --- a/src/librawspeed/decompressors/PanasonicV6Decompressor.cpp +++ b/src/librawspeed/decompressors/PanasonicV6Decompressor.cpp @@ -88,7 +88,7 @@ struct pana_cs6_page_decoder { }; } // namespace -PanasonicV6Decompressor::PanasonicV6Decompressor(const RawImage& img, +PanasonicV6Decompressor::PanasonicV6Decompressor(RawImageData *img, const ByteStream& input_) : mRaw(img) { if (mRaw->getCpp() != 1 || mRaw->getDataType() != RawImageType::UINT16 || @@ -118,7 +118,9 @@ inline void __attribute__((always_inline)) // NOLINTNEXTLINE(bugprone-exception-escape): no exceptions will be thrown. PanasonicV6Decompressor::decompressBlock(ByteStream& rowInput, int row, int col) const noexcept { - const Array2DRef out(mRaw->getU16DataAsUncroppedArray2DRef()); + auto *rawU16 = dynamic_cast(mRaw); + assert(rawU16); + const Array2DRef out(rawU16->getU16DataAsUncroppedArray2DRef()); pana_cs6_page_decoder page( rowInput.getStream(PanasonicV6Decompressor::BytesPerBlock)); diff --git a/src/librawspeed/decompressors/PanasonicV6Decompressor.h b/src/librawspeed/decompressors/PanasonicV6Decompressor.h index 3e9b2b730..54454e69e 100644 --- a/src/librawspeed/decompressors/PanasonicV6Decompressor.h +++ b/src/librawspeed/decompressors/PanasonicV6Decompressor.h @@ -27,7 +27,7 @@ namespace rawspeed { class PanasonicV6Decompressor final : public AbstractDecompressor { - RawImage mRaw; + RawImageData* mRaw; ByteStream input; @@ -42,7 +42,7 @@ class PanasonicV6Decompressor final : public AbstractDecompressor { void decompressRow(int row) const noexcept; public: - PanasonicV6Decompressor(const RawImage& img, const ByteStream& input_); + PanasonicV6Decompressor(RawImageData* img, const ByteStream& input_); void decompress() const; }; diff --git a/src/librawspeed/decompressors/PentaxDecompressor.cpp b/src/librawspeed/decompressors/PentaxDecompressor.cpp index 2c90384f6..57e9e9b44 100644 --- a/src/librawspeed/decompressors/PentaxDecompressor.cpp +++ b/src/librawspeed/decompressors/PentaxDecompressor.cpp @@ -42,7 +42,7 @@ const std::array, 2>, 1> {3, 4, 2, 5, 1, 6, 0, 7, 8, 9, 10, 11, 12}}}, }}; -PentaxDecompressor::PentaxDecompressor(const RawImage& img, +PentaxDecompressor::PentaxDecompressor(RawImageData *img, std::optional metaData) : mRaw(img), ht(SetupHuffmanTable(std::move(metaData))) { if (mRaw->getCpp() != 1 || mRaw->getDataType() != RawImageType::UINT16 || @@ -140,7 +140,9 @@ PentaxDecompressor::SetupHuffmanTable(std::optional metaData) { } void PentaxDecompressor::decompress(const ByteStream& data) const { - const Array2DRef out(mRaw->getU16DataAsUncroppedArray2DRef()); + auto *rawU16 = dynamic_cast(mRaw); + assert(rawU16); + const Array2DRef out(rawU16->getU16DataAsUncroppedArray2DRef()); assert(out.height > 0); assert(out.width > 0); diff --git a/src/librawspeed/decompressors/PentaxDecompressor.h b/src/librawspeed/decompressors/PentaxDecompressor.h index b4ea3ad01..650eda813 100644 --- a/src/librawspeed/decompressors/PentaxDecompressor.h +++ b/src/librawspeed/decompressors/PentaxDecompressor.h @@ -33,11 +33,11 @@ namespace rawspeed { class ByteStream; class PentaxDecompressor final : public AbstractDecompressor { - RawImage mRaw; + RawImageData* mRaw; const HuffmanTable ht; public: - PentaxDecompressor(const RawImage& img, std::optional metaData); + PentaxDecompressor(RawImageData* img, std::optional metaData); void decompress(const ByteStream& data) const; diff --git a/src/librawspeed/decompressors/PhaseOneDecompressor.cpp b/src/librawspeed/decompressors/PhaseOneDecompressor.cpp index bf769de8a..99b7c1356 100644 --- a/src/librawspeed/decompressors/PhaseOneDecompressor.cpp +++ b/src/librawspeed/decompressors/PhaseOneDecompressor.cpp @@ -40,7 +40,7 @@ namespace rawspeed { -PhaseOneDecompressor::PhaseOneDecompressor(const RawImage& img, +PhaseOneDecompressor::PhaseOneDecompressor(RawImageData *img, std::vector&& strips_) : mRaw(img), strips(std::move(strips_)) { if (mRaw->getDataType() != RawImageType::UINT16) @@ -83,7 +83,9 @@ void PhaseOneDecompressor::prepareStrips() { } void PhaseOneDecompressor::decompressStrip(const PhaseOneStrip& strip) const { - const Array2DRef out(mRaw->getU16DataAsUncroppedArray2DRef()); + auto *rawU16 = dynamic_cast(mRaw); + assert(rawU16); + const Array2DRef out(rawU16->getU16DataAsUncroppedArray2DRef()); assert(out.width > 0); assert(out.width % 2 == 0); diff --git a/src/librawspeed/decompressors/PhaseOneDecompressor.h b/src/librawspeed/decompressors/PhaseOneDecompressor.h index 177dc9123..97239a1d4 100644 --- a/src/librawspeed/decompressors/PhaseOneDecompressor.h +++ b/src/librawspeed/decompressors/PhaseOneDecompressor.h @@ -39,7 +39,7 @@ struct PhaseOneStrip { }; class PhaseOneDecompressor final : public AbstractDecompressor { - RawImage mRaw; + RawImageData* mRaw; std::vector strips; @@ -50,7 +50,7 @@ class PhaseOneDecompressor final : public AbstractDecompressor { void prepareStrips(); public: - PhaseOneDecompressor(const RawImage& img, + PhaseOneDecompressor(RawImageData* img, std::vector&& strips_); void decompress() const; diff --git a/src/librawspeed/decompressors/SamsungV0Decompressor.cpp b/src/librawspeed/decompressors/SamsungV0Decompressor.cpp index abbfba1e7..1cf203937 100644 --- a/src/librawspeed/decompressors/SamsungV0Decompressor.cpp +++ b/src/librawspeed/decompressors/SamsungV0Decompressor.cpp @@ -37,7 +37,7 @@ namespace rawspeed { -SamsungV0Decompressor::SamsungV0Decompressor(const RawImage& image, +SamsungV0Decompressor::SamsungV0Decompressor(RawImageData *image, const ByteStream& bso, const ByteStream& bsr) : AbstractSamsungDecompressor(image) { @@ -91,7 +91,9 @@ void SamsungV0Decompressor::decompress() const { decompressStrip(row, stripes[row]); // Swap red and blue pixels to get the final CFA pattern - const Array2DRef out(mRaw->getU16DataAsUncroppedArray2DRef()); + auto *rawU16 = dynamic_cast(mRaw); + assert(rawU16); + const Array2DRef out(rawU16->getU16DataAsUncroppedArray2DRef()); for (int row = 0; row < out.height - 1; row += 2) { for (int col = 0; col < out.width - 1; col += 2) std::swap(out(row, col + 1), out(row + 1, col)); @@ -106,7 +108,9 @@ int32_t SamsungV0Decompressor::calcAdj(BitPumpMSB32& bits, int nbits) { void SamsungV0Decompressor::decompressStrip(int row, const ByteStream& bs) const { - const Array2DRef out(mRaw->getU16DataAsUncroppedArray2DRef()); + auto *rawU16 = dynamic_cast(mRaw); + assert(rawU16); + const Array2DRef out(rawU16->getU16DataAsUncroppedArray2DRef()); assert(out.width > 0); BitPumpMSB32 bits(bs); diff --git a/src/librawspeed/decompressors/SamsungV0Decompressor.h b/src/librawspeed/decompressors/SamsungV0Decompressor.h index 202d5f9f3..16820f0a2 100644 --- a/src/librawspeed/decompressors/SamsungV0Decompressor.h +++ b/src/librawspeed/decompressors/SamsungV0Decompressor.h @@ -28,7 +28,6 @@ namespace rawspeed { -class RawImage; // Decoder for compressed srw files (NX300 and later) class SamsungV0Decompressor final : public AbstractSamsungDecompressor { @@ -41,7 +40,7 @@ class SamsungV0Decompressor final : public AbstractSamsungDecompressor { static int32_t calcAdj(BitPumpMSB32& bits, int b); public: - SamsungV0Decompressor(const RawImage& image, const ByteStream& bso, + SamsungV0Decompressor(RawImageData *image, const ByteStream& bso, const ByteStream& bsr); void decompress() const; diff --git a/src/librawspeed/decompressors/SamsungV1Decompressor.cpp b/src/librawspeed/decompressors/SamsungV1Decompressor.cpp index 5a44d82da..4af67da6d 100644 --- a/src/librawspeed/decompressors/SamsungV1Decompressor.cpp +++ b/src/librawspeed/decompressors/SamsungV1Decompressor.cpp @@ -40,7 +40,7 @@ struct SamsungV1Decompressor::encTableItem { uint8_t diffLen; }; -SamsungV1Decompressor::SamsungV1Decompressor(const RawImage& image, +SamsungV1Decompressor::SamsungV1Decompressor(RawImageData *image, const ByteStream& bs_, int bit) : AbstractSamsungDecompressor(image), bs(bs_) { if (mRaw->getCpp() != 1 || mRaw->getDataType() != RawImageType::UINT16 || @@ -115,7 +115,9 @@ void SamsungV1Decompressor::decompress() const { } } - const Array2DRef out(mRaw->getU16DataAsUncroppedArray2DRef()); + auto *rawU16 = dynamic_cast(mRaw); + assert(rawU16); + const Array2DRef out(rawU16->getU16DataAsUncroppedArray2DRef()); assert(out.width % 32 == 0 && "Should have even count of pixels per row."); assert(out.height % 2 == 0 && "Should have even row count."); BitPumpMSB pump(bs); diff --git a/src/librawspeed/decompressors/SamsungV1Decompressor.h b/src/librawspeed/decompressors/SamsungV1Decompressor.h index fca1a715d..e84f7ff2e 100644 --- a/src/librawspeed/decompressors/SamsungV1Decompressor.h +++ b/src/librawspeed/decompressors/SamsungV1Decompressor.h @@ -28,7 +28,6 @@ namespace rawspeed { class ByteStream; -class RawImage; // Decoder for compressed srw files (NX3000 and later) class SamsungV1Decompressor final : public AbstractSamsungDecompressor { @@ -41,7 +40,7 @@ class SamsungV1Decompressor final : public AbstractSamsungDecompressor { static constexpr int bits = 12; public: - SamsungV1Decompressor(const RawImage& image, const ByteStream& bs_, int bit); + SamsungV1Decompressor(RawImageData* image, const ByteStream& bs_, int bit); void decompress() const; }; diff --git a/src/librawspeed/decompressors/SamsungV2Decompressor.cpp b/src/librawspeed/decompressors/SamsungV2Decompressor.cpp index f4ce2e73b..943d4a0d1 100644 --- a/src/librawspeed/decompressors/SamsungV2Decompressor.cpp +++ b/src/librawspeed/decompressors/SamsungV2Decompressor.cpp @@ -78,7 +78,7 @@ SamsungV2Decompressor::getDiff(BitPumpMSB32& pump, uint32_t len) { return signExtend(pump.getBits(len), len); } -SamsungV2Decompressor::SamsungV2Decompressor(const RawImage& image, +SamsungV2Decompressor::SamsungV2Decompressor(RawImageData *image, const ByteStream& bs, unsigned bits) : AbstractSamsungDecompressor(image) { @@ -149,7 +149,9 @@ SamsungV2Decompressor::SamsungV2Decompressor(const RawImage& image, inline __attribute__((always_inline)) std::array SamsungV2Decompressor::prepareBaselineValues(BitPumpMSB32& pump, int row, int col) { - const Array2DRef img(mRaw->getU16DataAsUncroppedArray2DRef()); + auto *rawU16 = dynamic_cast(mRaw); + assert(rawU16); + const Array2DRef img(rawU16->getU16DataAsUncroppedArray2DRef()); std::array baseline; @@ -310,7 +312,9 @@ SamsungV2Decompressor::decodeDifferences(BitPumpMSB32& pump, int row) { inline __attribute__((always_inline)) void SamsungV2Decompressor::processBlock(BitPumpMSB32& pump, int row, int col) { - const Array2DRef out(mRaw->getU16DataAsUncroppedArray2DRef()); + auto *rawU16 = dynamic_cast(mRaw); + assert(rawU16); + const Array2DRef out(rawU16->getU16DataAsUncroppedArray2DRef()); const std::array baseline = prepareBaselineValues(pump, row, col); diff --git a/src/librawspeed/decompressors/SamsungV2Decompressor.h b/src/librawspeed/decompressors/SamsungV2Decompressor.h index c2c88c244..720fbdf2d 100644 --- a/src/librawspeed/decompressors/SamsungV2Decompressor.h +++ b/src/librawspeed/decompressors/SamsungV2Decompressor.h @@ -28,7 +28,6 @@ namespace rawspeed { -class RawImage; // Decoder for third generation compressed SRW files (NX1) class SamsungV2Decompressor final : public AbstractSamsungDecompressor { @@ -66,7 +65,7 @@ class SamsungV2Decompressor final : public AbstractSamsungDecompressor { void decompressRow(int row); public: - SamsungV2Decompressor(const RawImage& image, const ByteStream& bs, + SamsungV2Decompressor(RawImageData* image, const ByteStream& bs, unsigned bit); void decompress(); diff --git a/src/librawspeed/decompressors/SonyArw1Decompressor.cpp b/src/librawspeed/decompressors/SonyArw1Decompressor.cpp index c02be30f8..c1197bc6a 100644 --- a/src/librawspeed/decompressors/SonyArw1Decompressor.cpp +++ b/src/librawspeed/decompressors/SonyArw1Decompressor.cpp @@ -32,7 +32,7 @@ namespace rawspeed { -SonyArw1Decompressor::SonyArw1Decompressor(const RawImage& img) : mRaw(img) { +SonyArw1Decompressor::SonyArw1Decompressor(RawImageData *img) : mRaw(img) { if (mRaw->getCpp() != 1 || mRaw->getDataType() != RawImageType::UINT16 || mRaw->getBpp() != sizeof(uint16_t)) ThrowRDE("Unexpected component count / data type"); @@ -52,7 +52,9 @@ inline int SonyArw1Decompressor::getDiff(BitPumpMSB& bs, uint32_t len) { } void SonyArw1Decompressor::decompress(const ByteStream& input) const { - const Array2DRef out(mRaw->getU16DataAsUncroppedArray2DRef()); + auto *rawU16 = dynamic_cast(mRaw); + assert(rawU16); + const Array2DRef out(rawU16->getU16DataAsUncroppedArray2DRef()); assert(out.width > 0); assert(out.height > 0); assert(out.height % 2 == 0); diff --git a/src/librawspeed/decompressors/SonyArw1Decompressor.h b/src/librawspeed/decompressors/SonyArw1Decompressor.h index d39846171..84184891e 100644 --- a/src/librawspeed/decompressors/SonyArw1Decompressor.h +++ b/src/librawspeed/decompressors/SonyArw1Decompressor.h @@ -30,12 +30,12 @@ namespace rawspeed { class ByteStream; class SonyArw1Decompressor final : public AbstractDecompressor { - RawImage mRaw; + RawImageData* mRaw; inline static int getDiff(BitPumpMSB& bs, uint32_t len); public: - explicit SonyArw1Decompressor(const RawImage& img); + explicit SonyArw1Decompressor(RawImageData* img); void decompress(const ByteStream& input) const; }; diff --git a/src/librawspeed/decompressors/SonyArw2Decompressor.cpp b/src/librawspeed/decompressors/SonyArw2Decompressor.cpp index 400445675..a97af53df 100644 --- a/src/librawspeed/decompressors/SonyArw2Decompressor.cpp +++ b/src/librawspeed/decompressors/SonyArw2Decompressor.cpp @@ -35,7 +35,7 @@ namespace rawspeed { -SonyArw2Decompressor::SonyArw2Decompressor(const RawImage& img, +SonyArw2Decompressor::SonyArw2Decompressor(RawImageData *img, const ByteStream& input_) : mRaw(img) { if (mRaw->getCpp() != 1 || mRaw->getDataType() != RawImageType::UINT16 || @@ -52,7 +52,9 @@ SonyArw2Decompressor::SonyArw2Decompressor(const RawImage& img, } void SonyArw2Decompressor::decompressRow(int row) const { - const Array2DRef out(mRaw->getU16DataAsUncroppedArray2DRef()); + auto *rawU16 = dynamic_cast(mRaw); + assert(rawU16); + const Array2DRef out(rawU16->getU16DataAsUncroppedArray2DRef()); assert(out.width > 0); assert(out.width % 32 == 0); diff --git a/src/librawspeed/decompressors/SonyArw2Decompressor.h b/src/librawspeed/decompressors/SonyArw2Decompressor.h index 9e7d78974..856a12724 100644 --- a/src/librawspeed/decompressors/SonyArw2Decompressor.h +++ b/src/librawspeed/decompressors/SonyArw2Decompressor.h @@ -30,11 +30,11 @@ class SonyArw2Decompressor final : public AbstractDecompressor { void decompressRow(int row) const; void decompressThread() const noexcept; - RawImage mRaw; + RawImageData* mRaw; ByteStream input; public: - SonyArw2Decompressor(const RawImage& img, const ByteStream& input); + SonyArw2Decompressor(RawImageData* img, const ByteStream& input); void decompress() const; }; diff --git a/src/librawspeed/decompressors/UncompressedDecompressor.h b/src/librawspeed/decompressors/UncompressedDecompressor.h index cfcc8d112..cf7efc767 100644 --- a/src/librawspeed/decompressors/UncompressedDecompressor.h +++ b/src/librawspeed/decompressors/UncompressedDecompressor.h @@ -36,7 +36,7 @@ class iPoint2D; class UncompressedDecompressor final : public AbstractDecompressor { ByteStream input; - RawImage mRaw; + RawImageData* mRaw; // check buffer size, throw, or compute minimal height that can be decoded void sanityCheck(const uint32_t* h, int bytesPerLine) const; @@ -56,7 +56,7 @@ class UncompressedDecompressor final : public AbstractDecompressor { uint32_t skipBytes, uint32_t h, uint64_t y) const; public: - UncompressedDecompressor(ByteStream input_, const RawImage& img) + UncompressedDecompressor(ByteStream input_, RawImageData* img) : input(std::move(input_)), mRaw(img) {} /* Helper function for decoders, that will unpack uncompressed image data */ diff --git a/src/librawspeed/decompressors/VC5Decompressor.cpp b/src/librawspeed/decompressors/VC5Decompressor.cpp index c3351e270..e6cb13f15 100644 --- a/src/librawspeed/decompressors/VC5Decompressor.cpp +++ b/src/librawspeed/decompressors/VC5Decompressor.cpp @@ -372,7 +372,7 @@ void VC5Decompressor::Wavelet::ReconstructableBand::createDecodingTasks( createLowHighPassCombiningTask(exceptionThrow); } -VC5Decompressor::VC5Decompressor(ByteStream bs, const RawImage& img) +VC5Decompressor::VC5Decompressor(ByteStream bs, RawImageData* img) : mRaw(img), mBs(std::move(bs)) { if (!mRaw->dim.hasPositiveArea()) ThrowRDE("Bad image dimensions."); @@ -806,7 +806,9 @@ void VC5Decompressor::decode(unsigned int offsetX, unsigned int offsetY, } void VC5Decompressor::combineFinalLowpassBands() const noexcept { - const Array2DRef out(mRaw->getU16DataAsUncroppedArray2DRef()); + auto *rawU16 = dynamic_cast(mRaw); + assert(rawU16); + const Array2DRef out(rawU16->getU16DataAsUncroppedArray2DRef()); const int width = out.width / 2; const int height = out.height / 2; diff --git a/src/librawspeed/decompressors/VC5Decompressor.h b/src/librawspeed/decompressors/VC5Decompressor.h index 257ca96de..79ce6477c 100644 --- a/src/librawspeed/decompressors/VC5Decompressor.h +++ b/src/librawspeed/decompressors/VC5Decompressor.h @@ -87,7 +87,7 @@ inline VC5Tag operator-(VC5Tag tag) { } class VC5Decompressor final : public AbstractDecompressor { - RawImage mRaw; + RawImageData* mRaw; ByteStream mBs; static constexpr auto VC5_LOG_TABLE_BITWIDTH = 12; @@ -217,7 +217,7 @@ class VC5Decompressor final : public AbstractDecompressor { void parseVC5(); public: - VC5Decompressor(ByteStream bs, const RawImage& img); + VC5Decompressor(ByteStream bs, RawImageData *img); void decode(unsigned int offsetX, unsigned int offsetY, unsigned int width, unsigned int height); diff --git a/src/librawspeed/interpolators/Cr2sRawInterpolator.cpp b/src/librawspeed/interpolators/Cr2sRawInterpolator.cpp index 7598382ae..3b3ce41ec 100644 --- a/src/librawspeed/interpolators/Cr2sRawInterpolator.cpp +++ b/src/librawspeed/interpolators/Cr2sRawInterpolator.cpp @@ -93,7 +93,9 @@ struct Cr2sRawInterpolator::YCbCr final { }; template void Cr2sRawInterpolator::interpolate_422_row(int row) { - const Array2DRef out(mRaw->getU16DataAsUncroppedArray2DRef()); + auto *rawU16 = dynamic_cast(mRaw); + assert(rawU16); + const Array2DRef out(rawU16->getU16DataAsUncroppedArray2DRef()); constexpr int InputComponentsPerMCU = 4; constexpr int PixelsPerMCU = 2; @@ -176,7 +178,9 @@ template void Cr2sRawInterpolator::interpolate_422_row(int row) { } template void Cr2sRawInterpolator::interpolate_422() { - const Array2DRef out(mRaw->getU16DataAsUncroppedArray2DRef()); + auto *rawU16 = dynamic_cast(mRaw); + assert(rawU16); + const Array2DRef out(rawU16->getU16DataAsUncroppedArray2DRef()); assert(out.width > 0); assert(out.height > 0); @@ -187,7 +191,9 @@ template void Cr2sRawInterpolator::interpolate_422() { } template void Cr2sRawInterpolator::interpolate_420_row(int row) { - const Array2DRef out(mRaw->getU16DataAsUncroppedArray2DRef()); + auto *rawU16 = dynamic_cast(mRaw); + assert(rawU16); + const Array2DRef out(rawU16->getU16DataAsUncroppedArray2DRef()); constexpr int X_S_F = 2; constexpr int Y_S_F = 2; @@ -339,7 +345,9 @@ template void Cr2sRawInterpolator::interpolate_420_row(int row) { } template void Cr2sRawInterpolator::interpolate_420() { - const Array2DRef out(mRaw->getU16DataAsUncroppedArray2DRef()); + auto *rawU16 = dynamic_cast(mRaw); + assert(rawU16); + const Array2DRef out(rawU16->getU16DataAsUncroppedArray2DRef()); constexpr int X_S_F = 2; constexpr int Y_S_F = 2; @@ -500,7 +508,7 @@ inline void Cr2sRawInterpolator::YUV_TO_RGB<2>(const YCbCr& p, uint16_t* X) { void Cr2sRawInterpolator::interpolate(int version) { assert(version >= 0 && version <= 2); - const auto& subSampling = mRaw->metadata.subsampling; + const auto& subSampling = mRaw->subsampling; if (subSampling.y == 1 && subSampling.x == 2) { switch (version) { case 0: diff --git a/src/librawspeed/interpolators/Cr2sRawInterpolator.h b/src/librawspeed/interpolators/Cr2sRawInterpolator.h index 11fcd4f2a..0386c1003 100644 --- a/src/librawspeed/interpolators/Cr2sRawInterpolator.h +++ b/src/librawspeed/interpolators/Cr2sRawInterpolator.h @@ -26,10 +26,10 @@ namespace rawspeed { -class RawImage; +class RawImageData; class Cr2sRawInterpolator final { - const RawImage& mRaw; + RawImageData* mRaw; const Array2DRef input; std::array sraw_coeffs; @@ -38,7 +38,7 @@ class Cr2sRawInterpolator final { struct YCbCr; public: - Cr2sRawInterpolator(const RawImage& mRaw_, Array2DRef input_, + Cr2sRawInterpolator(RawImageData* mRaw_, Array2DRef input_, std::array sraw_coeffs_, int hue_) : mRaw(mRaw_), input(input_), sraw_coeffs(sraw_coeffs_), hue(hue_) {} diff --git a/src/librawspeed/tiff/CiffEntry.cpp b/src/librawspeed/tiff/CiffEntry.cpp index 40f1384df..04b6d3d54 100644 --- a/src/librawspeed/tiff/CiffEntry.cpp +++ b/src/librawspeed/tiff/CiffEntry.cpp @@ -56,8 +56,6 @@ CiffEntry::CiffEntry(NORangesSet* valueDatas, ThrowCPE("Two valueData's overlap. Raw corrupt!"); break; case 0x4000: - // Data is stored directly in entry - data_offset = dirEntry.getPosition(); // Maximum of 8 bytes of data (the size and offset fields) bytesize = 8; data = dirEntry.getStream(bytesize); diff --git a/src/librawspeed/tiff/TiffEntry.cpp b/src/librawspeed/tiff/TiffEntry.cpp index 1cff782d4..a8a59e504 100644 --- a/src/librawspeed/tiff/TiffEntry.cpp +++ b/src/librawspeed/tiff/TiffEntry.cpp @@ -54,14 +54,12 @@ TiffEntry::TiffEntry(TiffIFD* parent_, ByteStream& bs) ThrowTPE("integer overflow in size calculation."); uint32_t byte_size = count << datashifts[numType]; - uint32_t data_offset = UINT32_MAX; if (byte_size <= 4) { - data_offset = bs.getPosition(); data = bs.getSubStream(bs.getPosition(), byte_size); bs.skipBytes(4); } else { - data_offset = bs.getU32(); + uint32_t data_offset = bs.getU32(); if (type == TiffDataType::OFFSET || isIn(tag, {TiffTag::DNGPRIVATEDATA, TiffTag::MAKERNOTE, TiffTag::MAKERNOTE_ALT, TiffTag::FUJI_RAW_IFD, diff --git a/src/utilities/identify/rawspeed-identify.cpp b/src/utilities/identify/rawspeed-identify.cpp index 8bdb3d317..d58aef112 100644 --- a/src/utilities/identify/rawspeed-identify.cpp +++ b/src/utilities/identify/rawspeed-identify.cpp @@ -111,7 +111,6 @@ using rawspeed::Buffer; using rawspeed::CameraMetaData; using rawspeed::FileReader; using rawspeed::iPoint2D; -using rawspeed::RawImage; using rawspeed::RawParser; using rawspeed::RawspeedException; using rawspeed::identify::find_cameras_xml; @@ -178,113 +177,120 @@ int main(int argc, char* argv[]) { // NOLINT } d->applyCrop = false; - d->failOnUnknown = true; - RawImage r = d->mRaw; - const RawImage* const raw = &r; - + d->failOnUnknown = true; d->decodeMetaData(meta.get()); - fprintf(stdout, "make: %s\n", r->metadata.make.c_str()); - fprintf(stdout, "model: %s\n", r->metadata.model.c_str()); + fprintf(stdout, "make: %s\n", d->mRaw.metadata.make.c_str()); + fprintf(stdout, "model: %s\n", d->mRaw.metadata.model.c_str()); - fprintf(stdout, "canonical_make: %s\n", r->metadata.canonical_make.c_str()); + fprintf(stdout, "canonical_make: %s\n", + d->mRaw.metadata.canonical_make.c_str()); fprintf(stdout, "canonical_model: %s\n", - r->metadata.canonical_model.c_str()); + d->mRaw.metadata.canonical_model.c_str()); fprintf(stdout, "canonical_alias: %s\n", - r->metadata.canonical_alias.c_str()); + d->mRaw.metadata.canonical_alias.c_str()); d->checkSupport(meta.get()); d->decodeRaw(); d->decodeMetaData(meta.get()); - r = d->mRaw; - - const auto errors = r->getErrors(); - for (const auto& error : errors) - fprintf(stderr, "WARNING: [rawspeed] %s\n", error.c_str()); - - fprintf(stdout, "blackLevel: %d\n", r->blackLevel); - fprintf(stdout, "whitePoint: %d\n", r->whitePoint); - - fprintf(stdout, "blackLevelSeparate: %d %d %d %d\n", - r->blackLevelSeparate[0], r->blackLevelSeparate[1], - r->blackLevelSeparate[2], r->blackLevelSeparate[3]); - - fprintf(stdout, "wbCoeffs: %f %f %f %f\n", r->metadata.wbCoeffs[0], - r->metadata.wbCoeffs[1], r->metadata.wbCoeffs[2], - r->metadata.wbCoeffs[3]); - - fprintf(stdout, "isCFA: %d\n", r->isCFA); - uint32_t filters = r->cfa.getDcrawFilter(); - fprintf(stdout, "filters: %d (0x%x)\n", filters, filters); - const uint32_t bpp = r->getBpp(); - fprintf(stdout, "bpp: %d\n", bpp); - const uint32_t cpp = r->getCpp(); - fprintf(stdout, "cpp: %d\n", cpp); - fprintf(stdout, "dataType: %u\n", static_cast(r->getDataType())); - // dimensions of uncropped image - const iPoint2D dimUncropped = r->getUncroppedDim(); - fprintf(stdout, "dimUncropped: %dx%d\n", dimUncropped.x, dimUncropped.y); - - // dimensions of cropped image - iPoint2D dimCropped = r->dim; - fprintf(stdout, "dimCropped: %dx%d\n", dimCropped.x, dimCropped.y); - - // crop - Top,Left corner - iPoint2D cropTL = r->getCropOffset(); - fprintf(stdout, "cropOffset: %dx%d\n", cropTL.x, cropTL.y); - - fprintf(stdout, "fuji_rotation_pos: %d\n", r->metadata.fujiRotationPos); - fprintf(stdout, "pixel_aspect_ratio: %f\n", r->metadata.pixelAspectRatio); - - double sum = 0.0F; + fprintf(stdout, "wbCoeffs: %f %f %f %f\n", d->mRaw.metadata.wbCoeffs[0], + d->mRaw.metadata.wbCoeffs[1], d->mRaw.metadata.wbCoeffs[2], + d->mRaw.metadata.wbCoeffs[3]); + + fprintf(stdout, "fuji_rotation_pos: %d\n", + d->mRaw.metadata.fujiRotationPos); + fprintf(stdout, "pixel_aspect_ratio: %f\n", + d->mRaw.metadata.pixelAspectRatio); + + fprintf(stdout, "total frames: %lu\n", d->mRaw.size()); + + for (rawspeed::RawImage::storage_t::size_type i = 0; i < d->mRaw.size(); + ++i) { + fprintf(stdout, "\nframe %lu:\n", i); + auto frame = d->mRaw.get(i); + const auto errors = frame->getErrors(); + for (const auto& error : errors) + fprintf(stderr, "WARNING: [rawspeed] %s\n", error.c_str()); + + fprintf(stdout, "blackLevel: %d\n", frame->blackLevel); + fprintf(stdout, "whitePoint: %d\n", frame->whitePoint); + + fprintf(stdout, "blackLevelSeparate: %d %d %d %d\n", + frame->blackLevelSeparate[0], frame->blackLevelSeparate[1], + frame->blackLevelSeparate[2], frame->blackLevelSeparate[3]); + + fprintf(stdout, "isCFA: %d\n", frame->isCFA); + uint32_t filters = frame->cfa.getDcrawFilter(); + fprintf(stdout, "filters: %d (0x%x)\n", filters, filters); + const uint32_t bpp = frame->getBpp(); + fprintf(stdout, "bpp: %d\n", bpp); + const uint32_t cpp = frame->getCpp(); + fprintf(stdout, "cpp: %d\n", cpp); + fprintf(stdout, "dataType: %u\n", + static_cast(frame->getDataType())); + + // dimensions of uncropped image + const iPoint2D dimUncropped = frame->getUncroppedDim(); + fprintf(stdout, "dimUncropped: %dx%d\n", dimUncropped.x, dimUncropped.y); + + // dimensions of cropped image + iPoint2D dimCropped = frame->dim; + fprintf(stdout, "dimCropped: %dx%d\n", dimCropped.x, dimCropped.y); + + // crop - Top,Left corner + iPoint2D cropTL = frame->getCropOffset(); + fprintf(stdout, "cropOffset: %dx%d\n", cropTL.x, cropTL.y); + + double sum = 0.0F; #ifdef HAVE_OPENMP -#pragma omp parallel for default(none) firstprivate(dimUncropped, raw, bpp) schedule(static) reduction(+ : sum) +#pragma omp parallel for default(none) firstprivate(dimUncropped, frame, bpp) schedule(static) reduction(+ : sum) #endif - for (int y = 0; y < dimUncropped.y; ++y) { - const uint8_t* const data = (*raw)->getDataUncropped(0, y); + for (int y = 0; y < dimUncropped.y; ++y) { + const uint8_t* const data = frame->getDataUncropped(0, y); - for (unsigned x = 0; x < bpp * dimUncropped.x; ++x) - sum += static_cast(data[x]); - } - fprintf(stdout, "Image byte sum: %lf\n", sum); - fprintf(stdout, "Image byte avg: %lf\n", - sum / static_cast(dimUncropped.y * dimUncropped.x * bpp)); + for (unsigned x = 0; x < bpp * dimUncropped.x; ++x) + sum += static_cast(data[x]); + } + fprintf(stdout, "Image byte sum: %lf\n", sum); + fprintf(stdout, "Image byte avg: %lf\n", + sum / static_cast(dimUncropped.y * dimUncropped.x * bpp)); - if (r->getDataType() == rawspeed::RawImageType::F32) { - sum = 0.0F; + if (frame->getDataType() == rawspeed::RawImageType::F32) { + sum = 0.0F; #ifdef HAVE_OPENMP -#pragma omp parallel for default(none) firstprivate(dimUncropped, raw, cpp) schedule(static) reduction(+ : sum) +#pragma omp parallel for default(none) firstprivate(dimUncropped, frame, cpp) schedule(static) reduction(+ : sum) #endif - for (int y = 0; y < dimUncropped.y; ++y) { - const auto* const data = - reinterpret_cast((*raw)->getDataUncropped(0, y)); + for (int y = 0; y < dimUncropped.y; ++y) { + const auto* const data = + reinterpret_cast(frame->getDataUncropped(0, y)); - for (unsigned x = 0; x < cpp * dimUncropped.x; ++x) - sum += static_cast(data[x]); - } + for (unsigned x = 0; x < cpp * dimUncropped.x; ++x) + sum += static_cast(data[x]); + } - fprintf(stdout, "Image float sum: %lf\n", sum); - fprintf(stdout, "Image float avg: %lf\n", - sum / static_cast(dimUncropped.y * dimUncropped.x)); - } else if (r->getDataType() == rawspeed::RawImageType::UINT16) { - sum = 0.0F; + fprintf(stdout, "Image float sum: %lf\n", sum); + fprintf(stdout, "Image float avg: %lf\n", + sum / static_cast(dimUncropped.y * dimUncropped.x)); + } else if (frame->getDataType() == rawspeed::RawImageType::UINT16) { + sum = 0.0F; #ifdef HAVE_OPENMP -#pragma omp parallel for default(none) firstprivate(dimUncropped, raw, cpp) schedule(static) reduction(+ : sum) +#pragma omp parallel for default(none) firstprivate(dimUncropped, frame, cpp) schedule(static) reduction(+ : sum) #endif - for (int y = 0; y < dimUncropped.y; ++y) { - const auto* const data = - reinterpret_cast((*raw)->getDataUncropped(0, y)); + for (int y = 0; y < dimUncropped.y; ++y) { + const auto* const data = + reinterpret_cast(frame->getDataUncropped(0, y)); - for (unsigned x = 0; x < cpp * dimUncropped.x; ++x) - sum += static_cast(data[x]); - } + for (unsigned x = 0; x < cpp * dimUncropped.x; ++x) + sum += static_cast(data[x]); + } - fprintf(stdout, "Image uint16_t sum: %lf\n", sum); - fprintf(stdout, "Image uint16_t avg: %lf\n", - sum / static_cast(dimUncropped.y * dimUncropped.x)); + fprintf(stdout, "Image uint16_t sum: %lf\n", sum); + fprintf(stdout, "Image uint16_t avg: %lf\n", + sum / static_cast(dimUncropped.y * dimUncropped.x)); + } } } catch (const RawspeedException& e) { fprintf(stderr, "ERROR: [rawspeed] %s\n", e.what()); diff --git a/src/utilities/rstest/rstest.cpp b/src/utilities/rstest/rstest.cpp index 606bb7e5e..985d01819 100644 --- a/src/utilities/rstest/rstest.cpp +++ b/src/utilities/rstest/rstest.cpp @@ -51,7 +51,6 @@ using rawspeed::FileReader; using rawspeed::getU16BE; using rawspeed::getU32LE; using rawspeed::iPoint2D; -using rawspeed::RawImage; using rawspeed::RawParser; using rawspeed::RawspeedException; using rawspeed::roundUp; @@ -73,14 +72,14 @@ using std::internal; namespace rawspeed::rstest { -std::string img_hash(const rawspeed::RawImage& r); +std::string img_hash(rawspeed::RawImageData* r); -void writePPM(const rawspeed::RawImage& raw, const std::string& fn); -void writePFM(const rawspeed::RawImage& raw, const std::string& fn); +void writePPM(rawspeed::RawImageData* raw, const std::string& fn); +void writePFM(rawspeed::RawImageData* raw, const std::string& fn); -md5::md5_state imgDataHash(const rawspeed::RawImage& raw); +md5::md5_state imgDataHash(rawspeed::RawImageData* raw); -void writeImage(const rawspeed::RawImage& raw, const std::string& fn); +void writeImage(rawspeed::RawImageData* raw, const std::string& fn); struct options { bool create; @@ -114,7 +113,7 @@ struct Timer { // yes, this is not cool. but i see no way to compute the hash of the // full image, without duplicating image, and copying excluding padding -md5::md5_state imgDataHash(const RawImage& raw) { +md5::md5_state imgDataHash(RawImageData* raw) { md5::md5_state ret = md5::md5_init; const iPoint2D dimUncropped = raw->getUncroppedDim(); @@ -157,86 +156,88 @@ std::string img_hash(const RawImage& r, bool noSamples) { if (noSamples) APPEND(&oss, "camera support status is unknown due to lack of samples\n"); - APPEND(&oss, "make: %s\n", r->metadata.make.c_str()); - APPEND(&oss, "model: %s\n", r->metadata.model.c_str()); - APPEND(&oss, "mode: %s\n", r->metadata.mode.c_str()); - - APPEND(&oss, "canonical_make: %s\n", r->metadata.canonical_make.c_str()); - APPEND(&oss, "canonical_model: %s\n", r->metadata.canonical_model.c_str()); - APPEND(&oss, "canonical_alias: %s\n", r->metadata.canonical_alias.c_str()); - APPEND(&oss, "canonical_id: %s\n", r->metadata.canonical_id.c_str()); - - APPEND(&oss, "isoSpeed: %d\n", r->metadata.isoSpeed); - APPEND(&oss, "blackLevel: %d\n", r->blackLevel); - APPEND(&oss, "whitePoint: %d\n", r->whitePoint); - - APPEND(&oss, "blackLevelSeparate: %d %d %d %d\n", r->blackLevelSeparate[0], - r->blackLevelSeparate[1], r->blackLevelSeparate[2], - r->blackLevelSeparate[3]); - - APPEND(&oss, "wbCoeffs: %f %f %f %f\n", r->metadata.wbCoeffs[0], - r->metadata.wbCoeffs[1], r->metadata.wbCoeffs[2], - r->metadata.wbCoeffs[3]); - - APPEND(&oss, "colorMatrix:"); - if (r->metadata.colorMatrix.empty()) - APPEND(&oss, " (none)"); - else { - for (int e : r->metadata.colorMatrix) - APPEND(&oss, " %i", e); - } - APPEND(&oss, "\n"); - - APPEND(&oss, "isCFA: %d\n", r->isCFA); - APPEND(&oss, "cfa: %s\n", r->cfa.asString().c_str()); - APPEND(&oss, "filters: 0x%x\n", r->cfa.getDcrawFilter()); - APPEND(&oss, "bpp: %d\n", r->getBpp()); - APPEND(&oss, "cpp: %d\n", r->getCpp()); - APPEND(&oss, "dataType: %u\n", static_cast(r->getDataType())); - - const iPoint2D dimUncropped = r->getUncroppedDim(); - APPEND(&oss, "dimUncropped: %dx%d\n", dimUncropped.x, dimUncropped.y); - APPEND(&oss, "dimCropped: %dx%d\n", r->dim.x, r->dim.y); - const iPoint2D cropTL = r->getCropOffset(); - APPEND(&oss, "cropOffset: %dx%d\n", cropTL.x, cropTL.y); - - // NOTE: pitch is internal property, a function of dimUncropped.x, bpp and - // some additional padding overhead, to align each line length to be a - // multiple of (currently) 16 bytes. And maybe with some additional - // const offset. there is no point in showing it here, it may differ. - // APPEND(&oss, "pitch: %d\n", r->pitch); - - APPEND(&oss, "blackAreas: "); - for (auto ba : r->blackAreas) - APPEND(&oss, "%d:%dx%d, ", ba.isVertical, ba.offset, ba.size); - APPEND(&oss, "\n"); - - APPEND(&oss, "fuji_rotation_pos: %d\n", r->metadata.fujiRotationPos); - APPEND(&oss, "pixel_aspect_ratio: %f\n", r->metadata.pixelAspectRatio); - - APPEND(&oss, "badPixelPositions: "); - { - MutexLocker guard(&r->mBadPixelMutex); - for (uint32_t p : r->mBadPixelPositions) - APPEND(&oss, "%d, ", p); - } - - APPEND(&oss, "\n"); + APPEND(&oss, "make: %s\n", r.metadata.make.c_str()); + APPEND(&oss, "model: %s\n", r.metadata.model.c_str()); + APPEND(&oss, "mode: %s\n", r.metadata.mode.c_str()); + + APPEND(&oss, "canonical_make: %s\n", r.metadata.canonical_make.c_str()); + APPEND(&oss, "canonical_model: %s\n", r.metadata.canonical_model.c_str()); + APPEND(&oss, "canonical_alias: %s\n", r.metadata.canonical_alias.c_str()); + APPEND(&oss, "canonical_id: %s\n", r.metadata.canonical_id.c_str()); + + for (const auto &frame : r) { + + APPEND(&oss, "isoSpeed: %d\n", r.metadata.isoSpeed); + APPEND(&oss, "blackLevel: %d\n", frame->blackLevel); + APPEND(&oss, "whitePoint: %d\n", frame->whitePoint); + + APPEND(&oss, "blackLevelSeparate: %d %d %d %d\n", + frame->blackLevelSeparate[0], frame->blackLevelSeparate[1], + frame->blackLevelSeparate[2], frame->blackLevelSeparate[3]); + + APPEND(&oss, "wbCoeffs: %f %f %f %f\n", r.metadata.wbCoeffs[0], + r.metadata.wbCoeffs[1], r.metadata.wbCoeffs[2], + r.metadata.wbCoeffs[3]); + + APPEND(&oss, "colorMatrix:"); + if (r.metadata.colorMatrix.empty()) + APPEND(&oss, " (none)"); + else { + for (int e : r.metadata.colorMatrix) + APPEND(&oss, " %i", e); + } + APPEND(&oss, "\n"); + + APPEND(&oss, "isCFA: %d\n", frame->isCFA); + APPEND(&oss, "cfa: %s\n", frame->cfa.asString().c_str()); + APPEND(&oss, "filters: 0x%x\n", frame->cfa.getDcrawFilter()); + APPEND(&oss, "bpp: %d\n", frame->getBpp()); + APPEND(&oss, "cpp: %d\n", frame->getCpp()); + APPEND(&oss, "dataType: %u\n", static_cast(frame->getDataType())); + + const iPoint2D dimUncropped = frame->getUncroppedDim(); + APPEND(&oss, "dimUncropped: %dx%d\n", dimUncropped.x, dimUncropped.y); + APPEND(&oss, "dimCropped: %dx%d\n", frame->dim.x, frame->dim.y); + const iPoint2D cropTL = frame->getCropOffset(); + APPEND(&oss, "cropOffset: %dx%d\n", cropTL.x, cropTL.y); + + // NOTE: pitch is internal property, a function of dimUncropped.x, bpp and + // some additional padding overhead, to align each line length to be a + // multiple of (currently) 16 bytes. And maybe with some additional + // const offset. there is no point in showing it here, it may differ. + // APPEND(&oss, "pitch: %d\n", r->pitch); + + APPEND(&oss, "blackAreas: "); + for (auto ba : frame->blackAreas) + APPEND(&oss, "%d:%dx%d, ", ba.isVertical, ba.offset, ba.size); + APPEND(&oss, "\n"); + + APPEND(&oss, "fuji_rotation_pos: %d\n", r.metadata.fujiRotationPos); + APPEND(&oss, "pixel_aspect_ratio: %f\n", r.metadata.pixelAspectRatio); + + APPEND(&oss, "badPixelPositions: "); + { + MutexLocker guard(&frame->mBadPixelMutex); + for (uint32_t p : frame->mBadPixelPositions) + APPEND(&oss, "%d, ", p); + } - rawspeed::md5::md5_state hash_of_line_hashes = imgDataHash(r); - APPEND(&oss, "md5sum of per-line md5sums: %s\n", - rawspeed::md5::hash_to_string(hash_of_line_hashes).c_str()); + APPEND(&oss, "\n"); - const auto errors = r->getErrors(); - for (const std::string& e : errors) - APPEND(&oss, "WARNING: [rawspeed] %s\n", e.c_str()); + rawspeed::md5::md5_state hash_of_line_hashes = imgDataHash(frame.get()); + APPEND(&oss, "md5sum of per-line md5sums: %s\n", + rawspeed::md5::hash_to_string(hash_of_line_hashes).c_str()); + const auto errors = frame->getErrors(); + for (const std::string& e : errors) + APPEND(&oss, "WARNING: [rawspeed] %s\n", e.c_str()); + } return oss.str(); } using file_ptr = std::unique_ptr; -void writePPM(const RawImage& raw, const std::string& fn) { +void writePPM(RawImageData* raw, const std::string& fn) { file_ptr f(fopen((fn + ".ppm").c_str(), "wb"), &fclose); const iPoint2D dimUncropped = raw->getUncroppedDim(); @@ -260,7 +261,7 @@ void writePPM(const RawImage& raw, const std::string& fn) { } } -void writePFM(const RawImage& raw, const std::string& fn) { +void writePFM(RawImageData* raw, const std::string& fn) { file_ptr f(fopen((fn + ".pfm").c_str(), "wb"), &fclose); const iPoint2D dimUncropped = raw->getUncroppedDim(); @@ -311,7 +312,7 @@ void writePFM(const RawImage& raw, const std::string& fn) { } } -void writeImage(const RawImage& raw, const std::string& fn) { +void writeImage(RawImageData *raw, const std::string& fn) { switch (raw->getDataType()) { case RawImageType::UINT16: writePPM(raw, fn); @@ -369,8 +370,6 @@ size_t process(const std::string& filename, const CameraMetaData* metadata, decoder->decodeRaw(); decoder->decodeMetaData(metadata); - RawImage raw = decoder->mRaw; - // RawImage raw = decoder->decode(); auto time = t(); #if !defined(__has_feature) || !__has_feature(thread_sanitizer) @@ -385,12 +384,18 @@ size_t process(const std::string& filename, const CameraMetaData* metadata, if (o.create) { // write the hash. if force is set, then we are potentially overwriting here ofstream f(hashfile); - f << img_hash(raw, noSamples); - if (o.dump) - writeImage(raw, filename); + f << img_hash(decoder->mRaw, noSamples); + if (o.dump){ + for (rawspeed::RawImage::storage_t::size_type i = 0; + i < decoder->mRaw.size(); ++i) { + std::stringstream s; + s << filename << "." << i; + writeImage(decoder->mRaw.get(i).get(), s.str()); + } + } } else { // do generate the hash string regardless. - std::string h = img_hash(raw, noSamples); + std::string h = img_hash(decoder->mRaw, noSamples); // normally, here we would compare the old hash with the new one // but if the force is set, and the hash does not exist, do nothing. @@ -399,11 +404,17 @@ size_t process(const std::string& filename, const CameraMetaData* metadata, std::string truth((istreambuf_iterator(hf)), istreambuf_iterator()); - if (h != truth) { + if (h!= truth) { ofstream f(filename + ".hash.failed"); f << h; - if (o.dump) - writeImage(raw, filename + ".failed"); + if (o.dump){ + for (rawspeed::RawImage::storage_t::size_type i = 0; + i < decoder->mRaw.size(); ++i) { + std::stringstream s; + s << filename << "." << i << ".failed"; + writeImage(decoder->mRaw.get(i).get(), s.str()); + } + } throw RstestHashMismatch("hash/metadata mismatch", time); } } diff --git a/test/librawspeed/metadata/CameraSensorInfoTest.cpp b/test/librawspeed/metadata/CameraSensorInfoTest.cpp index 47c3b243d..607a792d8 100644 --- a/test/librawspeed/metadata/CameraSensorInfoTest.cpp +++ b/test/librawspeed/metadata/CameraSensorInfoTest.cpp @@ -269,7 +269,7 @@ class CameraSensorInfoTest : public ::testing::TestWithParam { std::rand(), // NOLINT do not need crypto-level randomness std::rand() // NOLINT do not need crypto-level randomness }) {} - virtual void SetUp() override { data = GetParam(); } + void SetUp() override { data = GetParam(); } IsoExpectationsT data; diff --git a/test/librawspeed/metadata/CameraTest.cpp b/test/librawspeed/metadata/CameraTest.cpp index 4f3747246..cd4a23b56 100644 --- a/test/librawspeed/metadata/CameraTest.cpp +++ b/test/librawspeed/metadata/CameraTest.cpp @@ -139,7 +139,7 @@ TEST(BoolHintTest, HintsBoolTrue) { class BoolHintTest : public ::testing::TestWithParam> { protected: - virtual void SetUp() override { notTrue = std::get<0>(GetParam()); } + void SetUp() override { notTrue = std::get<0>(GetParam()); } string notTrue; }; INSTANTIATE_TEST_CASE_P(NotTrue, BoolHintTest, diff --git a/test/librawspeed/metadata/ColorFilterArrayTest.cpp b/test/librawspeed/metadata/ColorFilterArrayTest.cpp index bd34497c7..dfe8b16fb 100644 --- a/test/librawspeed/metadata/ColorFilterArrayTest.cpp +++ b/test/librawspeed/metadata/ColorFilterArrayTest.cpp @@ -140,7 +140,7 @@ TEST(ColorFilterArrayTestBasic, HandlesOutOfBounds) { class ColorFilterArrayTest : public ::testing::TestWithParam { protected: ColorFilterArrayTest() = default; - virtual void SetUp() { param = GetParam(); } + void SetUp() override { param = GetParam(); } Bayer2x2 param; }; @@ -234,7 +234,7 @@ class ColorFilterArrayShiftTest std::tuple> { protected: ColorFilterArrayShiftTest() = default; - virtual void SetUp() { + void SetUp() override { auto param = GetParam(); mat = std::make_tuple(std::get<0>(param), std::get<1>(param), std::get<2>(param), std::get<3>(param));