summaryrefslogtreecommitdiff
path: root/src/external/rawspeed/src/librawspeed
diff options
context:
space:
mode:
authorDavid Bremner <bremner@debian.org>2018-12-25 22:44:44 +0900
committerDavid Bremner <bremner@debian.org>2018-12-25 22:44:44 +0900
commit33cc53ba511843ac9857470e74e043013d3620fe (patch)
treeebc0e94b5486710fc2f381d92fab9a594f1dc62c /src/external/rawspeed/src/librawspeed
parent1fddb41abdd4ca3be5bfdfe019e126b188879e15 (diff)
Importing darktable_2.6.0.orig.tar.xz
Diffstat (limited to 'src/external/rawspeed/src/librawspeed')
-rw-r--r--src/external/rawspeed/src/librawspeed/common/Array2DRef.h87
-rw-r--r--src/external/rawspeed/src/librawspeed/common/CMakeLists.txt6
-rw-r--r--src/external/rawspeed/src/librawspeed/common/ChecksumFile.cpp94
-rw-r--r--src/external/rawspeed/src/librawspeed/common/ChecksumFile.h41
-rw-r--r--src/external/rawspeed/src/librawspeed/common/Common.h62
-rw-r--r--src/external/rawspeed/src/librawspeed/common/DefaultInitAllocatorAdaptor.h101
-rw-r--r--src/external/rawspeed/src/librawspeed/common/DngOpcodes.cpp15
-rw-r--r--src/external/rawspeed/src/librawspeed/common/ErrorLog.cpp2
-rw-r--r--src/external/rawspeed/src/librawspeed/common/Optional.h52
-rw-r--r--src/external/rawspeed/src/librawspeed/common/RawImage.cpp21
-rw-r--r--src/external/rawspeed/src/librawspeed/common/RawImage.h6
-rw-r--r--src/external/rawspeed/src/librawspeed/common/RawImageDataFloat.cpp19
-rw-r--r--src/external/rawspeed/src/librawspeed/common/RawImageDataU16.cpp6
-rw-r--r--src/external/rawspeed/src/librawspeed/common/RawspeedException.h9
-rw-r--r--src/external/rawspeed/src/librawspeed/common/SimpleLUT.h67
-rw-r--r--src/external/rawspeed/src/librawspeed/common/Spline.h7
-rw-r--r--src/external/rawspeed/src/librawspeed/common/TableLookUp.cpp5
-rw-r--r--src/external/rawspeed/src/librawspeed/decoders/AbstractTiffDecoder.h4
-rw-r--r--src/external/rawspeed/src/librawspeed/decoders/ArwDecoder.cpp37
-rw-r--r--src/external/rawspeed/src/librawspeed/decoders/ArwDecoder.h2
-rw-r--r--src/external/rawspeed/src/librawspeed/decoders/Cr2Decoder.cpp35
-rw-r--r--src/external/rawspeed/src/librawspeed/decoders/Cr2Decoder.h2
-rw-r--r--src/external/rawspeed/src/librawspeed/decoders/CrwDecoder.cpp28
-rw-r--r--src/external/rawspeed/src/librawspeed/decoders/DcrDecoder.cpp28
-rw-r--r--src/external/rawspeed/src/librawspeed/decoders/DcrDecoder.h2
-rw-r--r--src/external/rawspeed/src/librawspeed/decoders/DcsDecoder.h2
-rw-r--r--src/external/rawspeed/src/librawspeed/decoders/DngDecoder.cpp53
-rw-r--r--src/external/rawspeed/src/librawspeed/decoders/ErfDecoder.h2
-rw-r--r--src/external/rawspeed/src/librawspeed/decoders/IiqDecoder.cpp93
-rw-r--r--src/external/rawspeed/src/librawspeed/decoders/IiqDecoder.h24
-rw-r--r--src/external/rawspeed/src/librawspeed/decoders/KdcDecoder.cpp18
-rw-r--r--src/external/rawspeed/src/librawspeed/decoders/KdcDecoder.h2
-rw-r--r--src/external/rawspeed/src/librawspeed/decoders/MefDecoder.h2
-rw-r--r--src/external/rawspeed/src/librawspeed/decoders/MosDecoder.cpp4
-rw-r--r--src/external/rawspeed/src/librawspeed/decoders/MrwDecoder.cpp18
-rw-r--r--src/external/rawspeed/src/librawspeed/decoders/MrwDecoder.h2
-rw-r--r--src/external/rawspeed/src/librawspeed/decoders/NefDecoder.cpp32
-rw-r--r--src/external/rawspeed/src/librawspeed/decoders/NefDecoder.h2
-rw-r--r--src/external/rawspeed/src/librawspeed/decoders/OrfDecoder.cpp114
-rw-r--r--src/external/rawspeed/src/librawspeed/decoders/OrfDecoder.h9
-rw-r--r--src/external/rawspeed/src/librawspeed/decoders/PefDecoder.cpp12
-rw-r--r--src/external/rawspeed/src/librawspeed/decoders/PefDecoder.h2
-rw-r--r--src/external/rawspeed/src/librawspeed/decoders/RafDecoder.cpp13
-rw-r--r--src/external/rawspeed/src/librawspeed/decoders/RafDecoder.h2
-rw-r--r--src/external/rawspeed/src/librawspeed/decoders/RawDecoder.cpp20
-rw-r--r--src/external/rawspeed/src/librawspeed/decoders/Rw2Decoder.cpp48
-rw-r--r--src/external/rawspeed/src/librawspeed/decoders/Rw2Decoder.h9
-rw-r--r--src/external/rawspeed/src/librawspeed/decoders/SimpleTiffDecoder.h2
-rw-r--r--src/external/rawspeed/src/librawspeed/decoders/SrwDecoder.cpp8
-rw-r--r--src/external/rawspeed/src/librawspeed/decoders/SrwDecoder.h2
-rw-r--r--src/external/rawspeed/src/librawspeed/decoders/ThreefrDecoder.cpp8
-rw-r--r--src/external/rawspeed/src/librawspeed/decoders/ThreefrDecoder.h2
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/AbstractDngDecompressor.cpp22
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/AbstractDngDecompressor.h1
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/AbstractHuffmanTable.h247
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/AbstractLJpegDecompressor.cpp21
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/AbstractLJpegDecompressor.h19
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/AbstractParallelizedDecompressor.h2
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/BinaryHuffmanTree.h237
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/CMakeLists.txt12
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/Cr2Decompressor.cpp15
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/Cr2Decompressor.h7
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/CrwDecompressor.cpp48
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/CrwDecompressor.h4
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/DeflateDecompressor.cpp16
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/DeflateDecompressor.h13
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/FujiDecompressor.cpp148
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/FujiDecompressor.h43
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/HasselbladDecompressor.cpp8
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/HasselbladDecompressor.h3
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/HuffmanTable.h351
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/HuffmanTableLUT.h257
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/HuffmanTableLookup.h171
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/HuffmanTableTree.h165
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/HuffmanTableVector.h155
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/JpegDecompressor.cpp15
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/JpegDecompressor.h3
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/KodakDecompressor.cpp26
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/KodakDecompressor.h5
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/LJpegDecompressor.cpp107
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/LJpegDecompressor.h10
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/NikonDecompressor.cpp434
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/NikonDecompressor.h33
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/OlympusDecompressor.cpp49
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/OlympusDecompressor.h3
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/PanasonicDecompressor.cpp292
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/PanasonicDecompressor.h55
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/PanasonicDecompressorV5.cpp255
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/PanasonicDecompressorV5.h109
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/PentaxDecompressor.cpp28
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/PentaxDecompressor.h8
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/PhaseOneDecompressor.cpp152
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/PhaseOneDecompressor.h55
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/SamsungV0Decompressor.cpp11
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/SamsungV0Decompressor.h2
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/SamsungV1Decompressor.cpp21
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/SamsungV2Decompressor.cpp14
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/SonyArw1Decompressor.cpp15
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/SonyArw1Decompressor.h3
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/SonyArw2Decompressor.cpp6
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/UncompressedDecompressor.h2
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/VC5Decompressor.cpp829
-rw-r--r--src/external/rawspeed/src/librawspeed/decompressors/VC5Decompressor.h229
-rw-r--r--src/external/rawspeed/src/librawspeed/io/BitPumpJPEG.h6
-rw-r--r--src/external/rawspeed/src/librawspeed/io/BitPumpLSB.h6
-rw-r--r--src/external/rawspeed/src/librawspeed/io/BitPumpMSB.h4
-rw-r--r--src/external/rawspeed/src/librawspeed/io/BitPumpMSB32.h4
-rw-r--r--src/external/rawspeed/src/librawspeed/io/BitStream.h24
-rw-r--r--src/external/rawspeed/src/librawspeed/io/Buffer.cpp7
-rw-r--r--src/external/rawspeed/src/librawspeed/io/Buffer.h9
-rw-r--r--src/external/rawspeed/src/librawspeed/io/ByteStream.h8
-rw-r--r--src/external/rawspeed/src/librawspeed/io/Endianness.h25
-rw-r--r--src/external/rawspeed/src/librawspeed/io/FileIOException.h2
-rw-r--r--src/external/rawspeed/src/librawspeed/io/FileReader.cpp11
-rw-r--r--src/external/rawspeed/src/librawspeed/metadata/CameraMetaData.cpp2
-rw-r--r--src/external/rawspeed/src/librawspeed/metadata/CameraMetaData.h11
-rw-r--r--src/external/rawspeed/src/librawspeed/metadata/CameraSensorInfo.cpp4
-rw-r--r--src/external/rawspeed/src/librawspeed/metadata/ColorFilterArray.cpp8
-rw-r--r--src/external/rawspeed/src/librawspeed/parsers/CiffParser.cpp15
-rw-r--r--src/external/rawspeed/src/librawspeed/parsers/FiffParser.cpp18
-rw-r--r--src/external/rawspeed/src/librawspeed/parsers/TiffParser.cpp11
-rw-r--r--src/external/rawspeed/src/librawspeed/tiff/CiffEntry.cpp10
-rw-r--r--src/external/rawspeed/src/librawspeed/tiff/CiffEntry.h5
-rw-r--r--src/external/rawspeed/src/librawspeed/tiff/CiffIFD.cpp22
-rw-r--r--src/external/rawspeed/src/librawspeed/tiff/CiffIFD.h3
-rw-r--r--src/external/rawspeed/src/librawspeed/tiff/TiffEntry.cpp11
-rw-r--r--src/external/rawspeed/src/librawspeed/tiff/TiffEntry.h2
-rw-r--r--src/external/rawspeed/src/librawspeed/tiff/TiffIFD.cpp16
-rw-r--r--src/external/rawspeed/src/librawspeed/tiff/TiffTag.h4
129 files changed, 4949 insertions, 1278 deletions
diff --git a/src/external/rawspeed/src/librawspeed/common/Array2DRef.h b/src/external/rawspeed/src/librawspeed/common/Array2DRef.h
new file mode 100644
index 000000000..ec3a6e16f
--- /dev/null
+++ b/src/external/rawspeed/src/librawspeed/common/Array2DRef.h
@@ -0,0 +1,87 @@
+/*
+ RawSpeed - RAW file decoder.
+
+ Copyright (C) 2018 Stefan Löffler
+ Copyright (C) 2018 Roman Lebedev
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#pragma once
+
+#include <cassert> // for assert
+#include <type_traits>
+#include <vector> // for vector
+
+namespace rawspeed {
+
+template <class T> class Array2DRef {
+ int _pitch = 0;
+ T* _data = nullptr;
+
+ friend Array2DRef<const T>; // We need to be able to convert to const version.
+
+public:
+ using value_type = T;
+ using cvless_value_type = typename std::remove_cv<value_type>::type;
+
+ int width = 0, height = 0;
+
+ Array2DRef() = default;
+
+ Array2DRef(T* data, int dataWidth, int dataHeight, int dataPitch = 0);
+
+ // Conversion from Array2DRef<T> to Array2DRef<const T>.
+ template <class T2, typename = std::enable_if_t<std::is_same<
+ typename std::remove_const<T>::type, T2>::value>>
+ Array2DRef(Array2DRef<T2> RHS) { // NOLINT google-explicit-constructor
+ _data = RHS._data;
+ _pitch = RHS._pitch;
+ width = RHS.width;
+ height = RHS.height;
+ }
+
+ template <typename AllocatorType =
+ typename std::vector<cvless_value_type>::allocator_type>
+ static Array2DRef<T>
+ create(std::vector<cvless_value_type, AllocatorType>* storage, int width,
+ int height) {
+ storage->resize(width * height);
+ return {storage->data(), width, height};
+ }
+
+ inline T& operator()(int x, int y) const;
+};
+
+template <class T>
+Array2DRef<T>::Array2DRef(T* data, const int dataWidth, const int dataHeight,
+ const int dataPitch /* = 0 */)
+ : _data(data), width(dataWidth), height(dataHeight) {
+ assert(width >= 0);
+ assert(height >= 0);
+ _pitch = (dataPitch == 0 ? dataWidth : dataPitch);
+}
+
+template <class T>
+T& Array2DRef<T>::operator()(const int x, const int y) const {
+ assert(_data);
+ assert(x >= 0);
+ assert(y >= 0);
+ assert(x < width);
+ assert(y < height);
+ return _data[y * _pitch + x];
+}
+
+} // namespace rawspeed
diff --git a/src/external/rawspeed/src/librawspeed/common/CMakeLists.txt b/src/external/rawspeed/src/librawspeed/common/CMakeLists.txt
index 495e8eeb7..cd984a0bf 100644
--- a/src/external/rawspeed/src/librawspeed/common/CMakeLists.txt
+++ b/src/external/rawspeed/src/librawspeed/common/CMakeLists.txt
@@ -1,7 +1,11 @@
FILE(GLOB SOURCES
+ "Array2DRef.h"
+ "ChecksumFile.cpp"
+ "ChecksumFile.h"
"Common.cpp"
"Common.h"
"Cpuid.cpp"
+ "DefaultInitAllocatorAdaptor.h"
"DngOpcodes.cpp"
"DngOpcodes.h"
"ErrorLog.cpp"
@@ -10,6 +14,7 @@ FILE(GLOB SOURCES
"Memory.h"
"Mutex.h"
"NORangesSet.h"
+ "Optional.h"
"Point.h"
"Range.h"
"RawImage.cpp"
@@ -17,6 +22,7 @@ FILE(GLOB SOURCES
"RawImageDataFloat.cpp"
"RawImageDataU16.cpp"
"RawspeedException.h"
+ "SimpleLUT.h"
"Spline.h"
"TableLookUp.cpp"
"TableLookUp.h"
diff --git a/src/external/rawspeed/src/librawspeed/common/ChecksumFile.cpp b/src/external/rawspeed/src/librawspeed/common/ChecksumFile.cpp
new file mode 100644
index 000000000..144e8c5fd
--- /dev/null
+++ b/src/external/rawspeed/src/librawspeed/common/ChecksumFile.cpp
@@ -0,0 +1,94 @@
+/*
+ RawSpeed - RAW file decoder.
+
+ Copyright (C) 2018 Roman Lebedev
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "common/ChecksumFile.h"
+#include "common/Common.h" // for splitString
+#include "common/RawspeedException.h" // for ThrowRSE
+#include "io/Buffer.h" // for Buffer
+#include "io/FileReader.h" // for FileReader
+#include <cassert> // for assert
+#include <memory> // for unique_ptr
+#include <string> // for string, allocator, operator+
+#include <vector> // for vector
+
+namespace rawspeed {
+
+namespace {
+
+// The lenght of the sha1 digest (160-bit, 40 hexadecimal chars).
+constexpr auto Sha1CheckSumLength = 40;
+// The separator after the digest and before filename.
+// Should be either " " or " b".
+constexpr auto CheckSumSeparatorWidth = 2;
+
+ChecksumFileEntry ParseChecksumFileLine(const std::string& Line,
+ const std::string& RootDir) {
+ ChecksumFileEntry Entry;
+
+ // We are just assuming that the checksum file is correct and valid.
+ // It is up to user to validate it first (via actually running `sha1sum -c`).
+
+ static constexpr auto Offset = Sha1CheckSumLength + CheckSumSeparatorWidth;
+
+ if (Line.size() <= Offset)
+ ThrowRSE("Malformed checksum line: \"%s\"", Line.c_str());
+
+ Entry.RelFileName = Line.substr(Offset);
+ assert(!Entry.RelFileName.empty());
+ assert(Entry.RelFileName.back() != '\n');
+
+ Entry.FullFileName = RootDir + "/" + Entry.RelFileName;
+
+ return Entry;
+}
+
+} // namespace
+
+std::vector<ChecksumFileEntry>
+ParseChecksumFileContent(const std::string& ChecksumFileContent,
+ const std::string& RootDir) {
+ std::vector<ChecksumFileEntry> Listing;
+
+ const std::vector<std::string> Lines = splitString(ChecksumFileContent, '\n');
+
+ Listing.reserve(Lines.size());
+
+ for (const auto& Line : Lines) {
+ assert(!Line.empty());
+ Listing.emplace_back(ParseChecksumFileLine(Line, RootDir));
+ }
+
+ return Listing;
+}
+
+std::vector<ChecksumFileEntry>
+ReadChecksumFile(const std::string& RootDir,
+ const std::string& ChecksumFileBasename) {
+ const std::string ChecksumFileName = RootDir + "/" + ChecksumFileBasename;
+ FileReader FR(ChecksumFileName.c_str());
+
+ std::unique_ptr<const Buffer> buf = FR.readFile();
+ const std::string ChecksumFileContent(
+ reinterpret_cast<const char*>(buf->begin()), buf->getSize());
+
+ return ParseChecksumFileContent(ChecksumFileContent, RootDir);
+}
+
+} // namespace rawspeed
diff --git a/src/external/rawspeed/src/librawspeed/common/ChecksumFile.h b/src/external/rawspeed/src/librawspeed/common/ChecksumFile.h
new file mode 100644
index 000000000..79bed10a4
--- /dev/null
+++ b/src/external/rawspeed/src/librawspeed/common/ChecksumFile.h
@@ -0,0 +1,41 @@
+/*
+ RawSpeed - RAW file decoder.
+
+ Copyright (C) 2018 Roman Lebedev
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#pragma once
+
+#include <string> // for string
+#include <vector> // for vector
+
+namespace rawspeed {
+
+struct ChecksumFileEntry {
+ std::string FullFileName;
+ std::string RelFileName;
+};
+
+std::vector<ChecksumFileEntry>
+ParseChecksumFileContent(const std::string& ChecksumFileContent,
+ const std::string& RootDir);
+
+std::vector<ChecksumFileEntry>
+ReadChecksumFile(const std::string& RootDir,
+ const std::string& ChecksumFileBasename = "filelist.sha1");
+
+} // namespace rawspeed
diff --git a/src/external/rawspeed/src/librawspeed/common/Common.h b/src/external/rawspeed/src/librawspeed/common/Common.h
index 9af437c5b..677947673 100644
--- a/src/external/rawspeed/src/librawspeed/common/Common.h
+++ b/src/external/rawspeed/src/librawspeed/common/Common.h
@@ -22,12 +22,14 @@
#include "rawspeedconfig.h"
+#include <algorithm> // IWYU pragma: keep
#include <cassert> // for assert
+#include <climits> // for CHAR_BIT
#include <cstdint> // for uintptr_t
-#include <cstring> // for memcpy, size_t
+#include <cstring> // for size_t, memcpy
#include <initializer_list> // for initializer_list
#include <string> // for string
-#include <type_traits> // for enable_if, is_pointer
+#include <type_traits> // for enable_if, is_pointer, is_signed, is_uns...
#include <vector> // for vector
extern "C" int rawspeed_get_number_of_processor_cores();
@@ -73,10 +75,25 @@ template <typename T> inline constexpr bool isPowerOfTwo(T val) {
}
constexpr inline size_t __attribute__((const))
+roundToMultiple(size_t value, size_t multiple, bool roundDown) {
+ if ((multiple == 0) || (value % multiple == 0))
+ return value;
+ // Drop remainder.
+ size_t roundedDown = value - (value % multiple);
+ if (roundDown) // If we were rounding down, then that's it.
+ return roundedDown;
+ // Else, just add one multiple.
+ return roundedDown + multiple;
+}
+
+constexpr inline size_t __attribute__((const))
+roundDown(size_t value, size_t multiple) {
+ return roundToMultiple(value, multiple, /*roundDown=*/true);
+}
+
+constexpr inline size_t __attribute__((const))
roundUp(size_t value, size_t multiple) {
- return ((multiple == 0) || (value % multiple == 0))
- ? value
- : value + multiple - (value % multiple);
+ return roundToMultiple(value, multiple, /*roundDown=*/false);
}
constexpr inline size_t __attribute__((const))
@@ -122,13 +139,34 @@ inline uint32 getThreadCount()
#endif
}
-// clampBits clamps the given int to the range 0 .. 2^n-1, with n <= 16
-inline ushort16 __attribute__((const)) clampBits(int x, uint32 n) {
- assert(n <= 16);
- const int tmp = (1 << n) - 1;
- x = x < 0 ? 0 : x;
- x = x > tmp ? tmp : x;
- return x;
+// Clamps the given unsigned value to the range 0 .. 2^n-1, with n <= 16
+template <class T>
+inline constexpr __attribute__((const)) ushort16 clampBits(
+ T value, unsigned int nBits,
+ typename std::enable_if<std::is_unsigned<T>::value>::type* /*unused*/ =
+ nullptr) {
+ // We expect to produce ushort16.
+ assert(nBits <= 16);
+ // Check that the clamp is not a no-op. Not of ushort16 to 16 bits e.g.
+ // (Well, not really, if we are called from clampBits<signed>, it's ok..).
+ constexpr auto BitWidthOfT = CHAR_BIT * sizeof(T);
+ (void)BitWidthOfT;
+ assert(BitWidthOfT > nBits); // If nBits >= BitWidthOfT, then shift is UB.
+ const T maxVal = (T(1) << nBits) - T(1);
+ return std::min(value, maxVal);
+}
+
+// Clamps the given signed value to the range 0 .. 2^n-1, with n <= 16
+template <typename T>
+inline constexpr ushort16 __attribute__((const))
+clampBits(T value, unsigned int nBits,
+ typename std::enable_if<std::is_signed<T>::value>::type* /*unused*/ =
+ nullptr) {
+ // If the value is negative, clamp it to zero.
+ value = std::max(value, T(0));
+ // Now, let the unsigned case clamp to the upper limit.
+ using UnsignedT = typename std::make_unsigned<T>::type;
+ return clampBits<UnsignedT>(value, nBits);
}
// Trim both leading and trailing spaces from the string
diff --git a/src/external/rawspeed/src/librawspeed/common/DefaultInitAllocatorAdaptor.h b/src/external/rawspeed/src/librawspeed/common/DefaultInitAllocatorAdaptor.h
new file mode 100644
index 000000000..910f9adfe
--- /dev/null
+++ b/src/external/rawspeed/src/librawspeed/common/DefaultInitAllocatorAdaptor.h
@@ -0,0 +1,101 @@
+/*
+ RawSpeed - RAW file decoder.
+
+ Copyright (C) 2018 Roman Lebedev
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#pragma once
+
+#include <memory>
+#include <type_traits>
+
+namespace rawspeed {
+
+template <typename T, typename ActualAllocator = std::allocator<T>,
+ typename = std::enable_if_t<std::is_pod<T>::value>>
+class DefaultInitAllocatorAdaptor {
+public:
+ using allocator_traits = std::allocator_traits<ActualAllocator>;
+
+ using value_type = typename allocator_traits::value_type;
+ using pointer = typename allocator_traits::pointer;
+ using const_pointer = typename allocator_traits::const_pointer;
+ using size_type = typename allocator_traits::size_type;
+ using difference_type = typename allocator_traits::difference_type;
+
+ static_assert(std::is_same<T, value_type>::value, "");
+
+ template <class To> struct rebind {
+ using other = DefaultInitAllocatorAdaptor<
+ To, typename allocator_traits::template rebind_alloc<To>>;
+ };
+
+ using allocator_type =
+ typename allocator_traits::template rebind_alloc<value_type>;
+
+ allocator_type allocator;
+
+ const allocator_type& get_allocator() const noexcept { return allocator; }
+
+ DefaultInitAllocatorAdaptor() noexcept = default;
+
+ explicit DefaultInitAllocatorAdaptor(
+ const allocator_type& allocator_) noexcept
+ : allocator(allocator_) {}
+
+ template <class To>
+ explicit DefaultInitAllocatorAdaptor(
+ const DefaultInitAllocatorAdaptor<
+ To, typename allocator_traits::template rebind_alloc<To>>&
+ allocator_) noexcept
+ : allocator(allocator_.get_allocator()) {}
+
+ pointer allocate(size_type n, const void* hint = nullptr) {
+ return allocator.allocate(n, hint);
+ }
+
+ void deallocate(pointer p, size_type n) noexcept {
+ allocator.deallocate(p, n);
+ }
+
+ template <typename U>
+ void
+ construct(U* ptr) noexcept(std::is_nothrow_default_constructible<U>::value) {
+ ::new (static_cast<void*>(ptr)) U; // start the life-time, but do not init.
+ }
+
+ using propagate_on_container_copy_assignment =
+ typename allocator_traits::propagate_on_container_copy_assignment;
+ using propagate_on_container_move_assignment =
+ typename allocator_traits::propagate_on_container_move_assignment;
+ using propagate_on_container_swap =
+ typename allocator_traits::propagate_on_container_swap;
+};
+
+template <typename T0, typename A0, typename T1, typename A1>
+bool operator==(DefaultInitAllocatorAdaptor<T0, A0> const& x,
+ DefaultInitAllocatorAdaptor<T1, A1> const& y) noexcept {
+ return x.get_allocator() == y.get_allocator();
+}
+
+template <typename T0, typename A0, typename T1, typename A1>
+bool operator!=(DefaultInitAllocatorAdaptor<T0, A0> const& x,
+ DefaultInitAllocatorAdaptor<T1, A1> const& y) noexcept {
+ return !(x == y);
+}
+
+} // namespace rawspeed
diff --git a/src/external/rawspeed/src/librawspeed/common/DngOpcodes.cpp b/src/external/rawspeed/src/librawspeed/common/DngOpcodes.cpp
index 049ce3d3c..747027f28 100644
--- a/src/external/rawspeed/src/librawspeed/common/DngOpcodes.cpp
+++ b/src/external/rawspeed/src/librawspeed/common/DngOpcodes.cpp
@@ -321,9 +321,9 @@ public:
// Create lookup
lookup.resize(65536);
- for (auto i = 0U; i < lookup.size(); ++i) {
+ for (auto i = 0UL; i < lookup.size(); ++i) {
double val = polynomial[0];
- for (auto j = 1U; j < polynomial.size(); ++j)
+ for (auto j = 1UL; j < polynomial.size(); ++j)
val += polynomial[j] * pow(i / 65536.0, j);
lookup[i] = (clampBits(static_cast<int>(val * 65535.5), 16));
}
@@ -433,11 +433,13 @@ public:
template <typename S>
class DngOpcodes::ScalePerRowOrCol final : public DeltaRowOrCol<S> {
// We have pixel value in range of [0..65535]. We scale by float X.
- // For this to generate a value within the same range , the scale X needs
- // to be in the range [0..65535]. Since the offset is multiplied
+ // For this to generate a value within the same range, the scale X needs
+ // to be in the range [0..65535]. However, we are operating with 32-bit
+ // signed integer space, so the new value can not be larger than 2^31,
+ // else we'd have signed integer overflow. Since the offset is multiplied
// by f2iScale before applying, we need to divide by f2iScale here.
- // So the maxLimit has the same value as absLimit for OffsetPerRowOrCol.
static constexpr const double minLimit = 0.0;
+ static constexpr int rounding = 512;
const double maxLimit;
bool valueIsOk(float value) final {
@@ -447,7 +449,8 @@ class DngOpcodes::ScalePerRowOrCol final : public DeltaRowOrCol<S> {
public:
explicit ScalePerRowOrCol(const RawImage& ri, ByteStream* bs)
: DeltaRowOrCol<S>(ri, bs, 1024.0F),
- maxLimit(double(std::numeric_limits<ushort16>::max()) /
+ maxLimit((double(std::numeric_limits<int>::max() - rounding) /
+ double(std::numeric_limits<ushort16>::max())) /
this->f2iScale) {}
void apply(const RawImage& ri) override {
diff --git a/src/external/rawspeed/src/librawspeed/common/ErrorLog.cpp b/src/external/rawspeed/src/librawspeed/common/ErrorLog.cpp
index d188ef83b..801674818 100644
--- a/src/external/rawspeed/src/librawspeed/common/ErrorLog.cpp
+++ b/src/external/rawspeed/src/librawspeed/common/ErrorLog.cpp
@@ -20,7 +20,7 @@
#include "ErrorLog.h"
#include "common/Mutex.h" // for MutexLocker
-#include <algorithm> // for move
+#include <utility> // for move
namespace rawspeed {
diff --git a/src/external/rawspeed/src/librawspeed/common/Optional.h b/src/external/rawspeed/src/librawspeed/common/Optional.h
new file mode 100644
index 000000000..78a03d538
--- /dev/null
+++ b/src/external/rawspeed/src/librawspeed/common/Optional.h
@@ -0,0 +1,52 @@
+/*
+ RawSpeed - RAW file decoder.
+
+ Copyright (C) 2018 Roman Lebedev
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#pragma once
+
+#include <utility> // for move
+
+namespace rawspeed {
+
+template <class T> class Optional final {
+ T data;
+ bool hasData = false;
+
+public:
+ Optional() = default;
+
+ explicit Optional(T RHS) : data(RHS), hasData(true) {}
+
+ Optional& operator=(T RHS) {
+ Optional tmp(RHS);
+ *this = std::move(tmp);
+ return *this;
+ }
+
+ bool hasValue() const { return hasData; }
+
+ void reset() { hasData = false; }
+
+ T getValue() const {
+ assert(hasValue());
+ return data;
+ }
+};
+
+} // namespace rawspeed
diff --git a/src/external/rawspeed/src/librawspeed/common/RawImage.cpp b/src/external/rawspeed/src/librawspeed/common/RawImage.cpp
index de7a0e81e..7fa9ba26a 100644
--- a/src/external/rawspeed/src/librawspeed/common/RawImage.cpp
+++ b/src/external/rawspeed/src/librawspeed/common/RawImage.cpp
@@ -18,23 +18,26 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "rawspeedconfig.h" // for WITH_SSE2
+#include "rawspeedconfig.h" // for HAVE_PTHREAD
#include "common/RawImage.h"
-#include "AddressSanitizer.h" // for ASan::...
-#include "MemorySanitizer.h" // for MSan::CheckMemIsInitialized
+#include "MemorySanitizer.h" // for MSan
#include "common/Memory.h" // for alignedFree, alignedMalloc...
#include "decoders/RawDecoderException.h" // for ThrowRDE, RawDecoderException
#include "io/IOException.h" // for IOException
#include "parsers/TiffParserException.h" // for TiffParserException
-#include <algorithm> // for min
+#include <algorithm> // for fill_n, min
#include <cassert> // for assert
#include <cmath> // for NAN
-#include <cstdlib> // for free
-#include <cstring> // for memset, memcpy, strdup
+#include <cstdlib> // for size_t
+#include <cstring> // for memcpy, memset
#include <limits> // for numeric_limits
-#include <memory> // for unique_ptr
+#include <memory> // for unique_ptr, make_unique
+#include <utility> // for move, swap
+
+#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
+#include "AddressSanitizer.h" // for ASan::...
+#endif
-using std::fill_n;
using std::string;
namespace rawspeed {
@@ -60,7 +63,7 @@ ImageMetaData::ImageMetaData() {
isoSpeed = 0;
pixelAspectRatio = 1;
fujiRotationPos = 0;
- fill_n(wbCoeffs, 4, NAN);
+ wbCoeffs.fill(NAN);
}
RawImageData::~RawImageData() {
diff --git a/src/external/rawspeed/src/librawspeed/common/RawImage.h b/src/external/rawspeed/src/librawspeed/common/RawImage.h
index 79d8efdc3..d63511afd 100644
--- a/src/external/rawspeed/src/librawspeed/common/RawImage.h
+++ b/src/external/rawspeed/src/librawspeed/common/RawImage.h
@@ -86,7 +86,7 @@ public:
double pixelAspectRatio;
// White balance coefficients of the image
- float wbCoeffs[4];
+ std::array<float, 4> wbCoeffs;
// How many pixels far down the left edge and far up the right edge the image
// corners are when the image is rotated 45 degrees in Fuji rotated sensors.
@@ -206,7 +206,7 @@ protected:
void doLookup(int start_y, int end_y) override;
RawImageDataU16();
- explicit RawImageDataU16(const iPoint2D& dim, uint32 cpp = 1);
+ explicit RawImageDataU16(const iPoint2D& dim_, uint32 cpp_ = 1);
friend class RawImage;
};
@@ -221,7 +221,7 @@ protected:
void fixBadPixel(uint32 x, uint32 y, int component = 0) override;
[[noreturn]] void doLookup(int start_y, int end_y) override;
RawImageDataFloat();
- explicit RawImageDataFloat(const iPoint2D& dim, uint32 cpp = 1);
+ explicit RawImageDataFloat(const iPoint2D& dim_, uint32 cpp_ = 1);
friend class RawImage;
};
diff --git a/src/external/rawspeed/src/librawspeed/common/RawImageDataFloat.cpp b/src/external/rawspeed/src/librawspeed/common/RawImageDataFloat.cpp
index a2f40be6f..06423a20d 100644
--- a/src/external/rawspeed/src/librawspeed/common/RawImageDataFloat.cpp
+++ b/src/external/rawspeed/src/librawspeed/common/RawImageDataFloat.cpp
@@ -18,12 +18,13 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "common/RawImage.h" // for RawImageDataFloat, RawImag...
+#include "common/RawImage.h" // for RawImageDataFloat, TYPE_FL...
#include "common/Common.h" // for uchar8, uint32, writeLog
#include "common/Point.h" // for iPoint2D
#include "decoders/RawDecoderException.h" // for ThrowRDE
#include "metadata/BlackArea.h" // for BlackArea
#include <algorithm> // for max, min
+#include <array> // for array
#include <memory> // for operator==, unique_ptr
#include <vector> // for vector
@@ -44,7 +45,8 @@ RawImageDataFloat::RawImageDataFloat() {
void RawImageDataFloat::calculateBlackAreas() {
- float accPixels[4] = {0,0,0,0};
+ std::array<float, 4> accPixels;
+ accPixels.fill(0);
int totalpixels = 0;
for (auto area : blackAreas) {
@@ -258,8 +260,8 @@ RawImageDataFloat::RawImageDataFloat() {
void RawImageDataFloat::scaleValues(int start_y, int end_y) {
int gw = dim.x * cpp;
- float mul[4];
- float sub[4];
+ std::array<float, 4> mul;
+ std::array<float, 4> sub;
for (int i = 0; i < 4; i++) {
int v = i;
if ((mOffset.x&1) != 0)
@@ -289,12 +291,11 @@ RawImageDataFloat::RawImageDataFloat() {
void RawImageDataFloat::fixBadPixel( uint32 x, uint32 y, int component )
{
- float values[4];
- float dist[4];
- float weight[4];
+ std::array<float, 4> values;
+ values.fill(-1);
+ std::array<float, 4> dist = {{}};
+ std::array<float, 4> weight;
- values[0] = values[1] = values[2] = values[3] = -1;
- dist[0] = dist[1] = dist[2] = dist[3] = 0;
uchar8* bad_line = &mBadPixelMap[y*mBadPixelMapPitch];
// Find pixel to the left
diff --git a/src/external/rawspeed/src/librawspeed/common/RawImageDataU16.cpp b/src/external/rawspeed/src/librawspeed/common/RawImageDataU16.cpp
index 7570f6b5d..d47551301 100644
--- a/src/external/rawspeed/src/librawspeed/common/RawImageDataU16.cpp
+++ b/src/external/rawspeed/src/librawspeed/common/RawImageDataU16.cpp
@@ -339,8 +339,8 @@ void RawImageDataU16::scaleValues_plain(int start_y, int end_y) {
// Not SSE2
int gw = dim.x * cpp;
- int mul[4];
- int sub[4];
+ std::array<int, 4> mul;
+ std::array<int, 4> sub;
for (int i = 0; i < 4; i++) {
int v = i;
if ((mOffset.x & 1) != 0)
@@ -488,7 +488,7 @@ void RawImageDataU16::doLookup( int start_y, int end_y )
uint32 delta = lookup >> 16;
v = 15700 *(v & 65535) + (v >> 16);
uint32 pix = base + ((delta * (v & 2047) + 1024) >> 12);
- *pixel = pix;
+ *pixel = clampBits(pix, 16);
pixel++;
}
}
diff --git a/src/external/rawspeed/src/librawspeed/common/RawspeedException.h b/src/external/rawspeed/src/librawspeed/common/RawspeedException.h
index 28a72f86b..53a818853 100644
--- a/src/external/rawspeed/src/librawspeed/common/RawspeedException.h
+++ b/src/external/rawspeed/src/librawspeed/common/RawspeedException.h
@@ -24,6 +24,7 @@
#include "rawspeedconfig.h"
#include "common/Common.h"
+#include <array>
#include <cstdarg>
#include <cstdio>
#include <stdexcept>
@@ -36,7 +37,7 @@ template <typename T>
ThrowException(const char* fmt, ...) {
static constexpr size_t bufSize = 8192;
#if defined(HAVE_CXX_THREAD_LOCAL)
- static thread_local char buf[bufSize];
+ static thread_local std::array<char, bufSize> buf;
#elif defined(HAVE_GCC_THREAD_LOCAL)
static __thread char buf[bufSize];
#else
@@ -47,10 +48,10 @@ ThrowException(const char* fmt, ...) {
va_list val;
va_start(val, fmt);
- vsnprintf(buf, sizeof(buf), fmt, val);
+ vsnprintf(buf.data(), sizeof(buf), fmt, val);
va_end(val);
- writeLog(DEBUG_PRIO_EXTRA, "EXCEPTION: %s", buf);
- throw T(buf);
+ writeLog(DEBUG_PRIO_EXTRA, "EXCEPTION: %s", buf.data());
+ throw T(buf.data());
}
class RawspeedException : public std::runtime_error {
diff --git a/src/external/rawspeed/src/librawspeed/common/SimpleLUT.h b/src/external/rawspeed/src/librawspeed/common/SimpleLUT.h
new file mode 100644
index 000000000..ccc64de50
--- /dev/null
+++ b/src/external/rawspeed/src/librawspeed/common/SimpleLUT.h
@@ -0,0 +1,67 @@
+/*
+ RawSpeed - RAW file decoder.
+
+ Copyright (C) 2018 Stefan Löffler
+ Copyright (C) 2018 Roman Lebedev
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#pragma once
+
+#include "common/Common.h" // for clampBits
+#include <algorithm> // for generate_n
+#include <cassert> // for assert
+#include <functional> // for function
+#include <iterator> // for back_inserter
+#include <type_traits> // for enable_if, is_convertible
+#include <vector> // for vector
+
+namespace rawspeed {
+
+template <typename T, int TableBitWidth> class SimpleLUT final {
+public:
+ using value_type = T;
+
+ SimpleLUT() = default;
+
+private:
+ std::vector<value_type> table;
+
+public:
+ template <typename F,
+ typename = std::enable_if<std::is_convertible<
+ F, std::function<value_type(
+ typename decltype(table)::size_type,
+ typename decltype(table)::size_type)>>::value>>
+ explicit SimpleLUT(F&& f) {
+ const auto fullTableSize = 1U << TableBitWidth;
+ table.reserve(fullTableSize);
+ std::generate_n(std::back_inserter(table), fullTableSize,
+ [&f, table = &table]() {
+ // which row [0..fullTableSize) are we filling?
+ const auto i = table->size();
+ return f(i, fullTableSize);
+ });
+ assert(table.size() == fullTableSize);
+ }
+
+ inline value_type operator[](int x) const {
+ unsigned clampedX = clampBits(x, TableBitWidth);
+ return table[clampedX];
+ }
+};
+
+} // namespace rawspeed
diff --git a/src/external/rawspeed/src/librawspeed/common/Spline.h b/src/external/rawspeed/src/librawspeed/common/Spline.h
index fa87f585e..bcfa97e24 100644
--- a/src/external/rawspeed/src/librawspeed/common/Spline.h
+++ b/src/external/rawspeed/src/librawspeed/common/Spline.h
@@ -23,11 +23,12 @@
#include "common/Common.h" // for ushort16
#include "common/Point.h" // for iPoint2D
-#include <algorithm> // for adjacent_find
-#include <algorithm> // for min, max
+#include <algorithm> // for max, min, adjacent_find, for_each
#include <cassert> // for assert
+#include <functional> // for greater_equal
#include <limits> // for numeric_limits
-#include <type_traits> // for enable_if_t, is_arithmetic
+#include <memory> // for allocator_traits<>::value_type
+#include <type_traits> // for is_floating_point, enable_if_t, is_arithm...
#include <vector> // for vector
namespace rawspeed {
diff --git a/src/external/rawspeed/src/librawspeed/common/TableLookUp.cpp b/src/external/rawspeed/src/librawspeed/common/TableLookUp.cpp
index abaeec3a4..803a323e7 100644
--- a/src/external/rawspeed/src/librawspeed/common/TableLookUp.cpp
+++ b/src/external/rawspeed/src/librawspeed/common/TableLookUp.cpp
@@ -58,8 +58,9 @@ void TableLookUp::setTable(int ntable, const std::vector<ushort16>& table) {
int lower = i > 0 ? table[i - 1] : center;
int upper = i < (nfilled - 1) ? table[i + 1] : center;
int delta = upper - lower;
- t[i * 2] = center - ((upper - lower + 2) / 4);
- t[i * 2 + 1] = delta;
+ t[i * 2] = clampBits(center - ((upper - lower + 2) / 4), 16);
+ t[i * 2 + 1] = ushort16(delta);
+ // FIXME: this is completely broken when the curve is non-monotonic.
}
for (int i = nfilled; i < 65536; i++) {
diff --git a/src/external/rawspeed/src/librawspeed/decoders/AbstractTiffDecoder.h b/src/external/rawspeed/src/librawspeed/decoders/AbstractTiffDecoder.h
index 470c3f2a2..830f2a9bb 100644
--- a/src/external/rawspeed/src/librawspeed/decoders/AbstractTiffDecoder.h
+++ b/src/external/rawspeed/src/librawspeed/decoders/AbstractTiffDecoder.h
@@ -22,10 +22,10 @@
#include "decoders/RawDecoder.h" // for RawDecoder
#include "tiff/TiffIFD.h" // for TiffID, TiffRootIFD, TiffRootIFDOwner
-#include "tiff/TiffTag.h" // for TiffTag::IMAGEWIDTH, TiffTag
-#include <algorithm> // for move
+#include "tiff/TiffTag.h" // for IMAGEWIDTH, TiffTag
#include <memory> // for unique_ptr
#include <string> // for string
+#include <utility> // for move
namespace rawspeed {
diff --git a/src/external/rawspeed/src/librawspeed/decoders/ArwDecoder.cpp b/src/external/rawspeed/src/librawspeed/decoders/ArwDecoder.cpp
index 728e260ea..bb53164d4 100644
--- a/src/external/rawspeed/src/librawspeed/decoders/ArwDecoder.cpp
+++ b/src/external/rawspeed/src/librawspeed/decoders/ArwDecoder.cpp
@@ -24,23 +24,21 @@
#include "common/Point.h" // for iPoint2D
#include "common/RawspeedException.h" // for RawspeedException
#include "decoders/RawDecoderException.h" // for ThrowRDE
-#include "decompressors/HuffmanTable.h" // for HuffmanTable
#include "decompressors/SonyArw1Decompressor.h" // for SonyArw1Decompre...
#include "decompressors/SonyArw2Decompressor.h" // for SonyArw2Decompre...
#include "decompressors/UncompressedDecompressor.h" // for UncompressedDeco...
-#include "io/BitPumpMSB.h" // for BitPumpMSB
#include "io/Buffer.h" // for Buffer, DataBuffer
#include "io/ByteStream.h" // for ByteStream
#include "io/Endianness.h" // for Endianness, Endi...
-#include "io/IOException.h" // for IOException
#include "metadata/Camera.h" // for Hints
-#include "metadata/ColorFilterArray.h" // for CFAColor::CFA_GREEN
+#include "metadata/ColorFilterArray.h" // for CFA_GREEN, CFA_BLUE
#include "tiff/TiffEntry.h" // for TiffEntry
#include "tiff/TiffIFD.h" // for TiffRootIFD, Tif...
-#include "tiff/TiffTag.h" // for TiffTag::DNGPRIV...
+#include "tiff/TiffTag.h" // for DNGPRIVATEDATA
#include <cassert> // for assert
#include <cstring> // for memcpy, size_t
#include <memory> // for unique_ptr
+#include <set> // for set
#include <string> // for operator==, string
#include <vector> // for vector
@@ -198,7 +196,7 @@ RawImage ArwDecoder::decodeRawInternal() {
std::vector<ushort16> curve(0x4001);
TiffEntry *c = raw->getEntry(SONY_CURVE);
- uint32 sony_curve[] = { 0, 0, 0, 0, 0, 4095 };
+ std::array<uint32, 6> sony_curve = {{0, 0, 0, 0, 0, 4095}};
for (uint32 i = 0; i < 4; i++)
sony_curve[i+1] = (c->getU16(i) >> 2) & 0xfff;
@@ -322,8 +320,8 @@ void ArwDecoder::ParseA100WB() {
bs.skipBytes(4);
- ushort16 tmp[4];
bs.setByteOrder(Endianness::little);
+ std::array<ushort16, 4> tmp;
for (auto& coeff : tmp)
coeff = bs.getU16();
@@ -369,11 +367,11 @@ void ArwDecoder::SonyDecrypt(const uint32* ibuf, uint32* obuf, uint32 len,
if (0 == len)
return;
- uint32 pad[128];
+ std::array<uint32, 128> pad;
// Initialize the decryption pad from the key
for (int p=0; p < 4; p++)
- pad[p] = key = key * 48828125UL + 1UL;
+ pad[p] = key = uint32(key * 48828125UL + 1UL);
pad[3] = pad[3] << 1 | (pad[0]^pad[2]) >> 31;
for (int p=4; p < 127; p++)
pad[p] = (pad[p-4]^pad[p-2]) << 1 | (pad[p-3]^pad[p-1]) >> 31;
@@ -386,7 +384,7 @@ void ArwDecoder::SonyDecrypt(const uint32* ibuf, uint32* obuf, uint32 len,
pad[p & 127] = pad[(p+1) & 127] ^ pad[(p+1+64) & 127];
uint32 pv;
- memcpy(&pv, pad + (p & 127), sizeof(uint32));
+ memcpy(&pv, &(pad[p & 127]), sizeof(uint32));
uint32 bv;
memcpy(&bv, ibuf, sizeof(uint32));
@@ -420,22 +418,29 @@ void ArwDecoder::GetWB() {
uint32 off = sony_offset->getU32();
assert(sony_length != nullptr);
- uint32 len = sony_length->getU32();
+ // The Decryption is done in blocks of 4 bytes.
+ uint32 len = roundDown(sony_length->getU32(), 4);
assert(sony_key != nullptr);
uint32 key = getU32LE(sony_key->getData(4));
// "Decrypt" IFD
const auto& ifd_crypt = priv->getRootIfdData();
- auto ifd_size = ifd_crypt.getSize();
- auto ifd_decoded = Buffer::Create(ifd_size);
+ const auto EncryptedBuffer = ifd_crypt.getSubView(off, len);
+ // We do have to prepend 'off' padding, because TIFF uses absolute offsets.
+ const auto DecryptedBufferSize = off + EncryptedBuffer.getSize();
+ auto DecryptedBuffer = Buffer::Create(DecryptedBufferSize);
- SonyDecrypt(reinterpret_cast<const uint32*>(ifd_crypt.getData(off, len)),
- reinterpret_cast<uint32*>(ifd_decoded.get() + off), len / 4,
+ SonyDecrypt(reinterpret_cast<const uint32*>(EncryptedBuffer.begin()),
+ reinterpret_cast<uint32*>(DecryptedBuffer.get() + off), len / 4,
key);
NORangesSet<Buffer> ifds_decoded;
- Buffer decIFD(move(ifd_decoded), ifd_size);
+ Buffer decIFD(std::move(DecryptedBuffer), DecryptedBufferSize);
+ const Buffer Padding(decIFD.getSubView(0, off));
+ // The Decrypted Root Ifd can not point to preceding padding buffer.
+ ifds_decoded.emplace(Padding);
+
DataBuffer dbIDD(decIFD, priv->getRootIfdData().getByteOrder());
TiffRootIFD encryptedIFD(nullptr, &ifds_decoded, dbIDD, off);
diff --git a/src/external/rawspeed/src/librawspeed/decoders/ArwDecoder.h b/src/external/rawspeed/src/librawspeed/decoders/ArwDecoder.h
index ddebea2d3..c89a21ba5 100644
--- a/src/external/rawspeed/src/librawspeed/decoders/ArwDecoder.h
+++ b/src/external/rawspeed/src/librawspeed/decoders/ArwDecoder.h
@@ -26,7 +26,7 @@
#include "decoders/AbstractTiffDecoder.h" // for AbstractTiffDecoder
#include "io/ByteStream.h" // for ByteStream
#include "tiff/TiffIFD.h" // for TiffIFD (ptr only), TiffRo...
-#include <algorithm> // for move
+#include <utility> // for move
namespace rawspeed {
diff --git a/src/external/rawspeed/src/librawspeed/decoders/Cr2Decoder.cpp b/src/external/rawspeed/src/librawspeed/decoders/Cr2Decoder.cpp
index ff5812c93..004e1a568 100644
--- a/src/external/rawspeed/src/librawspeed/decoders/Cr2Decoder.cpp
+++ b/src/external/rawspeed/src/librawspeed/decoders/Cr2Decoder.cpp
@@ -21,25 +21,25 @@
*/
#include "decoders/Cr2Decoder.h"
-#include "common/Common.h" // for ushort16, clampBits, uint32
-#include "common/Point.h" // for iPoint2D
-#include "common/RawspeedException.h" // for RawspeedException
-#include "decoders/RawDecoderException.h" // for RawDecoderException, Thro...
-#include "decompressors/Cr2Decompressor.h" // for Cr2Decompressor
+#include "common/Common.h" // for uint32, ushort16
+#include "common/Point.h" // for iPoint2D
+#include "common/RawspeedException.h" // for RawspeedException
+#include "decoders/RawDecoderException.h" // for ThrowRDE
+#include "decompressors/Cr2Decompressor.h" // for Cr2Decompressor, Cr2S...
#include "interpolators/Cr2sRawInterpolator.h" // for Cr2sRawInterpolator
#include "io/Buffer.h" // for Buffer
#include "io/ByteStream.h" // for ByteStream
-#include "io/Endianness.h" // for getHostEndianness, Endian...
-#include "io/IOException.h" // for IOException
-#include "metadata/Camera.h" // for Hints
-#include "metadata/ColorFilterArray.h" // for CFAColor::CFA_GREEN, CFAC...
-#include "parsers/TiffParserException.h" // for ThrowTPE
-#include "tiff/TiffEntry.h" // for TiffEntry, TiffDataType::...
-#include "tiff/TiffTag.h" // for TiffTag, TiffTag::CANONCO...
-#include <array> // for array
-#include <cassert> // for assert
-#include <memory> // for unique_ptr, allocator
-#include <string> // for string, operator==
+#include "io/Endianness.h" // for Endianness, Endiannes...
+#include "metadata/Camera.h" // for Hints
+#include "metadata/ColorFilterArray.h" // for CFA_GREEN, CFA_BLUE
+#include "parsers/TiffParserException.h" // for ThrowTPE
+#include "tiff/TiffEntry.h" // for TiffEntry, TIFF_SHORT
+#include "tiff/TiffTag.h" // for TiffTag, CANONCOLORDATA
+#include <array> // for array
+#include <cassert> // for assert
+#include <memory> // for unique_ptr, allocator...
+#include <string> // for operator==, string
+#include <vector> // for vector
// IWYU pragma: no_include <ext/alloc_traits.h>
using std::string;
@@ -54,7 +54,8 @@ bool Cr2Decoder::isAppropriateDecoder(const TiffRootIFD* rootIFD,
// FIXME: magic
- return make == "Canon" || (make == "Kodak" && model == "DCS560C");
+ return make == "Canon" ||
+ (make == "Kodak" && (model == "DCS520C" || model == "DCS560C"));
}
RawImage Cr2Decoder::decodeOldFormat() {
diff --git a/src/external/rawspeed/src/librawspeed/decoders/Cr2Decoder.h b/src/external/rawspeed/src/librawspeed/decoders/Cr2Decoder.h
index 9def2ff80..d5a80fed1 100644
--- a/src/external/rawspeed/src/librawspeed/decoders/Cr2Decoder.h
+++ b/src/external/rawspeed/src/librawspeed/decoders/Cr2Decoder.h
@@ -23,7 +23,7 @@
#include "common/RawImage.h" // for RawImage
#include "decoders/AbstractTiffDecoder.h" // for AbstractTiffDecoder
#include "tiff/TiffIFD.h" // for TiffRootIFDOwner
-#include <algorithm> // for move
+#include <utility> // for move
namespace rawspeed {
diff --git a/src/external/rawspeed/src/librawspeed/decoders/CrwDecoder.cpp b/src/external/rawspeed/src/librawspeed/decoders/CrwDecoder.cpp
index 264bd26b2..033273770 100644
--- a/src/external/rawspeed/src/librawspeed/decoders/CrwDecoder.cpp
+++ b/src/external/rawspeed/src/librawspeed/decoders/CrwDecoder.cpp
@@ -21,24 +21,25 @@
*/
#include "decoders/CrwDecoder.h"
-#include "common/Common.h" // for ushort16, uint32
+#include "common/Common.h" // for ushort16, uchar8, uint32
#include "common/Point.h" // for iPoint2D
#include "common/RawspeedException.h" // for RawspeedException
-#include "decoders/RawDecoderException.h" // for RawDecoderException (ptr ...
+#include "decoders/RawDecoderException.h" // for ThrowRDE
#include "decompressors/CrwDecompressor.h" // for CrwDecompressor
+#include "io/Buffer.h" // for Buffer
#include "metadata/Camera.h" // for Hints
-#include "metadata/ColorFilterArray.h" // for CFAColor::CFA_GREEN, CFAC...
-#include "tiff/CiffEntry.h" // for CiffEntry, CiffDataType::...
+#include "metadata/ColorFilterArray.h" // for CFA_GREEN, CFA_BLUE, CFA_RED
+#include "tiff/CiffEntry.h" // for CiffEntry, CIFF_SHORT
#include "tiff/CiffIFD.h" // for CiffIFD
-#include "tiff/CiffTag.h" // for CiffTag, CiffTag::CIFF_MA...
-#include <algorithm> // for move
+#include "tiff/CiffTag.h" // for CIFF_MAKEMODEL, CIFF_SHOT...
#include <array> // for array
#include <cassert> // for assert
-#include <cmath> // for copysignf, expf, logf
+#include <cmath> // for abs, copysignf, expf, logf
+#include <cstring> // for memcmp, size_t
#include <memory> // for unique_ptr
#include <string> // for string
+#include <utility> // for move
#include <vector> // for vector
-// IWYU pragma: no_include <bits/std_abs.h>
using std::vector;
using std::string;
@@ -49,12 +50,11 @@ namespace rawspeed {
class CameraMetaData;
bool CrwDecoder::isCRW(const Buffer* input) {
- static const char magic[] = "HEAPCCDR";
+ static const std::array<char, 8> magic = {
+ {'H', 'E', 'A', 'P', 'C', 'C', 'D', 'R'}};
static const size_t magic_offset = 6;
- static const size_t magic_size = sizeof(magic) - 1; // excluding \0
- static_assert(magic_size == 8, "Wrong magic size!");
- const unsigned char* data = input->getData(magic_offset, magic_size);
- return 0 == memcmp(&data[0], magic, magic_size);
+ const unsigned char* data = input->getData(magic_offset, magic.size());
+ return 0 == memcmp(data, magic.data(), magic.size());
}
CrwDecoder::CrwDecoder(std::unique_ptr<const CiffIFD> rootIFD,
@@ -168,7 +168,7 @@ void CrwDecoder::decodeMetaDataInternal(const CameraMetaData* meta) {
// correct offset for most cameras
int offset = hints.get("wb_offset", 120);
- ushort16 key[] = { 0x410, 0x45f3 };
+ std::array<ushort16, 2> key = {{0x410, 0x45f3}};
if (! hints.has("wb_mangle"))
key[0] = key[1] = 0;
diff --git a/src/external/rawspeed/src/librawspeed/decoders/DcrDecoder.cpp b/src/external/rawspeed/src/librawspeed/decoders/DcrDecoder.cpp
index cdad0691e..69cfe4e72 100644
--- a/src/external/rawspeed/src/librawspeed/decoders/DcrDecoder.cpp
+++ b/src/external/rawspeed/src/librawspeed/decoders/DcrDecoder.cpp
@@ -20,14 +20,15 @@
*/
#include "decoders/DcrDecoder.h"
-#include "common/NORangesSet.h" // for NORangesSet
-#include "decoders/RawDecoderException.h" // for RawDecoderException (ptr ...
+#include "common/NORangesSet.h" // for set
+#include "decoders/RawDecoderException.h" // for ThrowRDE
#include "decompressors/KodakDecompressor.h" // for KodakDecompressor
#include "io/ByteStream.h" // for ByteStream
-#include "tiff/TiffEntry.h" // for TiffEntry, TiffDataType::...
-#include "tiff/TiffIFD.h" // for TiffRootIFD, TiffIFD
-#include "tiff/TiffTag.h" // for TiffTag, TiffTag::COMPRES...
+#include "tiff/TiffEntry.h" // for TiffEntry, TIFF_SHORT
+#include "tiff/TiffIFD.h" // for TiffRootIFD, TiffID
+#include "tiff/TiffTag.h" // for COMPRESSION, KODAK_IFD
#include <cassert> // for assert
+#include <memory> // for unique_ptr
#include <string> // for operator==, string
namespace rawspeed {
@@ -69,12 +70,13 @@ RawImage DcrDecoder::decodeRawInternal() {
ifdoffset->getU32());
TiffEntry* linearization = kodakifd.getEntryRecursive(KODAK_LINEARIZATION);
- if (!linearization || linearization->count != 1024 ||
+ if (!linearization ||
+ !(linearization->count == 1024 || linearization->count == 4096) ||
linearization->type != TIFF_SHORT)
ThrowRDE("Couldn't find the linearization table");
assert(linearization != nullptr);
- auto linTable = linearization->getU16Array(1024);
+ auto linTable = linearization->getU16Array(linearization->count);
RawImageCurveGuard curveHandler(&mRaw, linTable, uncorrectedRawValues);
@@ -92,7 +94,17 @@ RawImage DcrDecoder::decodeRawInternal() {
}
}
- KodakDecompressor k(mRaw, input, uncorrectedRawValues);
+ const int bps = [CurveSize = linearization->count]() -> int {
+ switch (CurveSize) {
+ case 1024:
+ return 10;
+ case 4096:
+ return 12;
+ }
+ __builtin_unreachable();
+ }();
+
+ KodakDecompressor k(mRaw, input, bps, uncorrectedRawValues);
k.decompress();
return mRaw;
diff --git a/src/external/rawspeed/src/librawspeed/decoders/DcrDecoder.h b/src/external/rawspeed/src/librawspeed/decoders/DcrDecoder.h
index 44ed4c833..82cf94260 100644
--- a/src/external/rawspeed/src/librawspeed/decoders/DcrDecoder.h
+++ b/src/external/rawspeed/src/librawspeed/decoders/DcrDecoder.h
@@ -24,7 +24,7 @@
#include "common/RawImage.h" // for RawImage
#include "decoders/SimpleTiffDecoder.h" // for SimpleTiffDecoder
#include "tiff/TiffIFD.h" // for TiffRootIFDOwner
-#include <algorithm> // for move
+#include <utility> // for move
namespace rawspeed {
diff --git a/src/external/rawspeed/src/librawspeed/decoders/DcsDecoder.h b/src/external/rawspeed/src/librawspeed/decoders/DcsDecoder.h
index 252aff385..c6ab0fa6c 100644
--- a/src/external/rawspeed/src/librawspeed/decoders/DcsDecoder.h
+++ b/src/external/rawspeed/src/librawspeed/decoders/DcsDecoder.h
@@ -24,7 +24,7 @@
#include "common/RawImage.h" // for RawImage
#include "decoders/SimpleTiffDecoder.h" // for SimpleTiffDecoder
#include "tiff/TiffIFD.h" // for TiffRootIFDOwner
-#include <algorithm> // for move
+#include <utility> // for move
namespace rawspeed {
diff --git a/src/external/rawspeed/src/librawspeed/decoders/DngDecoder.cpp b/src/external/rawspeed/src/librawspeed/decoders/DngDecoder.cpp
index 80729b2cb..70a459f47 100644
--- a/src/external/rawspeed/src/librawspeed/decoders/DngDecoder.cpp
+++ b/src/external/rawspeed/src/librawspeed/decoders/DngDecoder.cpp
@@ -20,28 +20,32 @@
#include "rawspeedconfig.h" // for HAVE_JPEG, HAVE_ZLIB
#include "decoders/DngDecoder.h"
-#include "common/Common.h" // for uint32, writeLog
+#include "common/Common.h" // for uint32, roundUpDi...
#include "common/DngOpcodes.h" // for DngOpcodes
-#include "common/NORangesSet.h" // for NORangesSet
+#include "common/NORangesSet.h" // for set
#include "common/Point.h" // for iPoint2D, iRectan...
#include "common/RawspeedException.h" // for RawspeedException
#include "decoders/RawDecoderException.h" // for ThrowRDE, RawDeco...
-#include "decompressors/AbstractDngDecompressor.h" // for AbstractDngDecomp...
-#include "io/Buffer.h" // for Buffer
+#include "decompressors/AbstractDngDecompressor.h" // for DngSliceElement
+#include "io/Buffer.h" // for Buffer, DataBuffer
+#include "io/ByteStream.h" // for ByteStream
+#include "metadata/BlackArea.h" // for BlackArea
#include "metadata/Camera.h" // for Camera
#include "metadata/CameraMetaData.h" // for CameraMetaData
#include "metadata/ColorFilterArray.h" // for CFAColor, ColorFi...
-#include "tiff/TiffEntry.h" // for TiffEntry, TiffDa...
+#include "parsers/TiffParserException.h" // for ThrowTPE
+#include "tiff/TiffEntry.h" // for TiffEntry, TIFF_LONG
#include "tiff/TiffIFD.h" // for TiffIFD, TiffRootIFD
-#include "tiff/TiffTag.h" // for TiffTag::ACTIVEAREA
-#include <algorithm> // for move
+#include "tiff/TiffTag.h" // for ACTIVEAREA, TILEO...
+#include <algorithm> // for any_of
+#include <array> // for array, array<>::v...
#include <cassert> // for assert
-#include <cstring> // for memset
#include <limits> // for numeric_limits
#include <map> // for map
#include <memory> // for unique_ptr
#include <stdexcept> // for out_of_range
#include <string> // for string, operator+
+#include <utility> // for move, pair
#include <vector> // for vector, allocator
using std::vector;
@@ -105,6 +109,7 @@ void DngDecoder::dropUnsuportedChunks(std::vector<const TiffIFD*>* data) {
#ifdef HAVE_ZLIB
case 8: // deflate
#endif
+ case 9: // VC-5 as used by GoPro
#ifdef HAVE_JPEG
case 0x884c: // lossy JPEG
#endif
@@ -272,10 +277,17 @@ void DngDecoder::decodeData(const TiffIFD* raw, uint32 sample_format) {
"JPEG-compressed data.");
}
- uint32 predictor = -1;
+ uint32 predictor = ~0U;
if (raw->hasEntry(PREDICTOR))
predictor = raw->getEntry(PREDICTOR)->getU32();
+ // Some decompressors (such as VC5) may depend on the white point
+ if (raw->hasEntry(WHITELEVEL)) {
+ TiffEntry* whitelevel = raw->getEntry(WHITELEVEL);
+ if (whitelevel->isInt())
+ mRaw->whitePoint = whitelevel->getU32();
+ }
+
AbstractDngDecompressor slices(mRaw, getTilingDescription(raw), compression,
mFixLjpeg, bps, predictor);
@@ -479,8 +491,12 @@ void DngDecoder::handleMetadata(const TiffIFD* raw) {
// Apply stage 1 opcodes
if (applyStage1DngOpcodes && raw->hasEntry(OPCODELIST1)) {
try {
- DngOpcodes codes(mRaw, raw->getEntry(OPCODELIST1));
- codes.applyOpCodes(mRaw);
+ TiffEntry* opcodes = raw->getEntry(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);
+ }
} catch (RawDecoderException& e) {
// We push back errors from the opcode parser, since the image may still
// be usable
@@ -498,8 +514,13 @@ void DngDecoder::handleMetadata(const TiffIFD* raw) {
mRaw->sixteenBitLookup();
}
- // Default white level is (2 ** BitsPerSample) - 1
- mRaw->whitePoint = (1UL << bps) - 1UL;
+ if (mRaw->getDataType() == TYPE_USHORT16) {
+ // Default white level is (2 ** BitsPerSample) - 1
+ mRaw->whitePoint = (1UL << bps) - 1UL;
+ } else if (mRaw->getDataType() == TYPE_FLOAT32) {
+ // Default white level is 1.0f. But we can't represent that here.
+ mRaw->whitePoint = 65535;
+ }
if (raw->hasEntry(WHITELEVEL)) {
TiffEntry *whitelevel = raw->getEntry(WHITELEVEL);
@@ -587,7 +608,7 @@ void DngDecoder::decodeMetaDataInternal(const CameraMetaData* meta) {
mRaw->metadata.wbCoeffs[2] =
1 - mRaw->metadata.wbCoeffs[0] - mRaw->metadata.wbCoeffs[1];
- const float d65_white[3] = {0.950456, 1, 1.088754};
+ const std::array<float, 3> d65_white = {{0.950456, 1, 1.088754}};
for (uint32 i = 0; i < 3; i++)
mRaw->metadata.wbCoeffs[i] /= d65_white[i];
}
@@ -709,7 +730,7 @@ bool DngDecoder::decodeBlackLevels(const TiffIFD* raw) {
TiffEntry *blackleveldeltav = raw->getEntry(BLACKLEVELDELTAV);
if (static_cast<int>(blackleveldeltav->count) < mRaw->dim.y)
ThrowRDE("BLACKLEVELDELTAV array is too small");
- float black_sum[2] = {0.0F, 0.0F};
+ std::array<float, 2> black_sum = {{}};
for (int i = 0; i < mRaw->dim.y; i++)
black_sum[i&1] += blackleveldeltav->getFloat(i);
@@ -730,7 +751,7 @@ bool DngDecoder::decodeBlackLevels(const TiffIFD* raw) {
TiffEntry *blackleveldeltah = raw->getEntry(BLACKLEVELDELTAH);
if (static_cast<int>(blackleveldeltah->count) < mRaw->dim.x)
ThrowRDE("BLACKLEVELDELTAH array is too small");
- float black_sum[2] = {0.0F, 0.0F};
+ std::array<float, 2> black_sum = {{}};
for (int i = 0; i < mRaw->dim.x; i++)
black_sum[i&1] += blackleveldeltah->getFloat(i);
diff --git a/src/external/rawspeed/src/librawspeed/decoders/ErfDecoder.h b/src/external/rawspeed/src/librawspeed/decoders/ErfDecoder.h
index b884b4099..c286cdbb1 100644
--- a/src/external/rawspeed/src/librawspeed/decoders/ErfDecoder.h
+++ b/src/external/rawspeed/src/librawspeed/decoders/ErfDecoder.h
@@ -24,7 +24,7 @@
#include "common/RawImage.h" // for RawImage
#include "decoders/SimpleTiffDecoder.h" // for SimpleTiffDecoder
#include "tiff/TiffIFD.h" // for TiffRootIFDOwner
-#include <algorithm> // for move
+#include <utility> // for move
namespace rawspeed {
diff --git a/src/external/rawspeed/src/librawspeed/decoders/IiqDecoder.cpp b/src/external/rawspeed/src/librawspeed/decoders/IiqDecoder.cpp
index 027df1a3a..41ae2d716 100644
--- a/src/external/rawspeed/src/librawspeed/decoders/IiqDecoder.cpp
+++ b/src/external/rawspeed/src/librawspeed/decoders/IiqDecoder.cpp
@@ -21,22 +21,25 @@
*/
#include "decoders/IiqDecoder.h"
-#include "common/Common.h" // for uint32, int32, ushort16
-#include "common/Point.h" // for iPoint2D
-#include "common/Spline.h" // for calculateCurve
-#include "decoders/RawDecoderException.h" // for ThrowRDE
-#include "io/BitPumpMSB32.h" // for BitPumpMSB32
-#include "io/Buffer.h" // for Buffer, DataBuffer
-#include "io/ByteStream.h" // for ByteStream
-#include "io/Endianness.h" // for Endianness, Endianness::li...
-#include "tiff/TiffIFD.h" // for TiffRootIFD, TiffID
-#include <algorithm> // for move, sort, adjacent_find
-#include <cassert> // for assert
-#include <functional> // for greater_equal
-#include <iterator> // for advance, begin, end, next
-#include <memory> // for unique_ptr
-#include <string> // for operator==, string
-#include <vector> // for vector
+#include "common/Common.h" // for uint32, ushort16
+#include "common/Point.h" // for iPoint2D
+#include "common/Spline.h" // for Spline, Spline<>::va...
+#include "decoders/RawDecoder.h" // for RawDecoder::(anonymous)
+#include "decoders/RawDecoderException.h" // for ThrowRDE
+#include "decompressors/PhaseOneDecompressor.h" // for PhaseOneStrip, Phase...
+#include "io/Buffer.h" // for Buffer, DataBuffer
+#include "io/ByteStream.h" // for ByteStream
+#include "io/Endianness.h" // for Endianness, Endianne...
+#include "tiff/TiffIFD.h" // for TiffRootIFD, TiffID
+#include <algorithm> // for adjacent_find, gener...
+#include <array> // for array, array<>::cons...
+#include <cassert> // for assert
+#include <functional> // for greater_equal
+#include <iterator> // for advance, next, begin
+#include <memory> // for unique_ptr
+#include <string> // for operator==, string
+#include <utility> // for move
+#include <vector> // for vector
namespace rawspeed {
@@ -61,7 +64,7 @@ bool IiqDecoder::isAppropriateDecoder(const TiffRootIFD* rootIFD,
}
// FIXME: this is very close to SamsungV0Decompressor::computeStripes()
-std::vector<IiqDecoder::IiqStrip>
+std::vector<PhaseOneStrip>
IiqDecoder::computeSripes(const Buffer& raw_data,
std::vector<IiqOffset>&& offsets,
uint32 height) const {
@@ -82,7 +85,7 @@ IiqDecoder::computeSripes(const Buffer& raw_data,
return a.offset < b.offset;
});
- std::vector<IiqDecoder::IiqStrip> slices;
+ std::vector<PhaseOneStrip> slices;
slices.reserve(height);
auto offset_iterator = std::begin(offsets);
@@ -198,13 +201,15 @@ RawImage IiqDecoder::decodeRawInternal() {
// which will be used much like end()
offsets.emplace_back(height, raw_data.getSize());
- const std::vector<IiqStrip> strips(
+ std::vector<PhaseOneStrip> strips(
computeSripes(raw_data, std::move(offsets), height));
mRaw->dim = iPoint2D(width, height);
+
+ PhaseOneDecompressor p(mRaw, std::move(strips));
mRaw->createData();
+ p.decompress();
- DecodePhaseOneC(strips, width, height);
if (correction_meta_data.getSize() != 0 && iiq)
CorrectPhaseOneC(correction_meta_data, split_row, split_col);
@@ -214,54 +219,6 @@ RawImage IiqDecoder::decodeRawInternal() {
return mRaw;
}
-void IiqDecoder::DecodeStrip(const IiqStrip& strip, uint32 width,
- uint32 height) {
- const int length[] = {8, 7, 6, 9, 11, 10, 5, 12, 14, 13};
-
- BitPumpMSB32 pump(strip.bs);
-
- int32 pred[2];
- uint32 len[2];
- pred[0] = pred[1] = 0;
- auto* img = reinterpret_cast<ushort16*>(mRaw->getData(0, strip.n));
- for (uint32 col = 0; col < width; col++) {
- if (col >= (width & -8))
- len[0] = len[1] = 14;
- else if ((col & 7) == 0) {
- for (unsigned int& i : len) {
- int j = 0;
-
- for (; j < 5; j++) {
- if (pump.getBits(1) != 0) {
- if (col == 0)
- ThrowRDE("Can not initialize lengths. Data is corrupt.");
-
- // else, we have previously initialized lengths, so we are fine
- break;
- }
- }
-
- assert((col == 0 && j > 0) || col != 0);
- if (j > 0)
- i = length[2 * (j - 1) + pump.getBits(1)];
- }
- }
-
- int i = len[col & 1];
- if (i == 14)
- img[col] = pred[col & 1] = pump.getBits(16);
- else
- img[col] = pred[col & 1] +=
- static_cast<signed>(pump.getBits(i)) + 1 - (1 << (i - 1));
- }
-}
-
-void IiqDecoder::DecodePhaseOneC(const std::vector<IiqStrip>& strips,
- uint32 width, uint32 height) {
- for (const auto& strip : strips)
- DecodeStrip(strip, width, height);
-}
-
void IiqDecoder::CorrectPhaseOneC(ByteStream meta_data, uint32 split_row,
uint32 split_col) {
meta_data.skipBytes(8);
diff --git a/src/external/rawspeed/src/librawspeed/decoders/IiqDecoder.h b/src/external/rawspeed/src/librawspeed/decoders/IiqDecoder.h
index d414b2dbe..041d170ae 100644
--- a/src/external/rawspeed/src/librawspeed/decoders/IiqDecoder.h
+++ b/src/external/rawspeed/src/librawspeed/decoders/IiqDecoder.h
@@ -24,15 +24,16 @@
#include "common/Common.h" // for uint32
#include "common/RawImage.h" // for RawImage
#include "decoders/AbstractTiffDecoder.h" // for AbstractTiffDecoder
-#include "io/ByteStream.h" // for ByteStream
#include "tiff/TiffIFD.h" // for TiffRootIFD (ptr only)
-#include <algorithm> // for move
+#include <utility> // for move
#include <vector> // for vector
namespace rawspeed {
-class CameraMetaData;
class Buffer;
+class ByteStream;
+class CameraMetaData;
+struct PhaseOneStrip;
class IiqDecoder final : public AbstractTiffDecoder {
struct IiqOffset {
@@ -43,18 +44,9 @@ class IiqDecoder final : public AbstractTiffDecoder {
IiqOffset(uint32 block, uint32 offset_) : n(block), offset(offset_) {}
};
- struct IiqStrip {
- const int n;
- const ByteStream bs;
-
- IiqStrip(int block, ByteStream bs_) : n(block), bs(std::move(bs_)) {}
- };
-
- std::vector<IiqStrip> computeSripes(const Buffer& raw_data,
- std::vector<IiqOffset>&& offsets,
- uint32 height) const;
-
- void DecodeStrip(const IiqStrip& strip, uint32 width, uint32 height);
+ std::vector<PhaseOneStrip> computeSripes(const Buffer& raw_data,
+ std::vector<IiqOffset>&& offsets,
+ uint32 height) const;
public:
static bool isAppropriateDecoder(const Buffer* file);
@@ -71,8 +63,6 @@ public:
protected:
int getDecoderVersion() const override { return 0; }
uint32 black_level = 0;
- void DecodePhaseOneC(const std::vector<IiqStrip>& strips, uint32 width,
- uint32 height);
void CorrectPhaseOneC(ByteStream meta_data, uint32 split_row,
uint32 split_col);
void CorrectQuadrantMultipliersCombined(ByteStream data, uint32 split_row,
diff --git a/src/external/rawspeed/src/librawspeed/decoders/KdcDecoder.cpp b/src/external/rawspeed/src/librawspeed/decoders/KdcDecoder.cpp
index 53f962e7a..23e95f006 100644
--- a/src/external/rawspeed/src/librawspeed/decoders/KdcDecoder.cpp
+++ b/src/external/rawspeed/src/librawspeed/decoders/KdcDecoder.cpp
@@ -56,13 +56,23 @@ RawImage KdcDecoder::decodeRawInternal() {
if (7 != compression)
ThrowRDE("Unsupported compression %d", compression);
+ TiffEntry* ifdoffset = mRootIFD->getEntryRecursive(KODAK_IFD2);
+ if (!ifdoffset)
+ ThrowRDE("Couldn't find the Kodak IFD offset");
+
+ NORangesSet<Buffer> ifds;
+
+ assert(ifdoffset != nullptr);
+ TiffRootIFD kodakifd(nullptr, &ifds, ifdoffset->getRootIfdData(),
+ ifdoffset->getU32());
+
uint32 width = 0;
uint32 height = 0;
- TiffEntry *ew = mRootIFD->getEntryRecursive(KODAK_KDC_WIDTH);
- TiffEntry *eh = mRootIFD->getEntryRecursive(KODAK_KDC_HEIGHT);
+ TiffEntry* ew = kodakifd.getEntryRecursive(KODAK_KDC_SENSOR_WIDTH);
+ TiffEntry* eh = kodakifd.getEntryRecursive(KODAK_KDC_SENSOR_HEIGHT);
if (ew && eh) {
- width = ew->getU32()+80;
- height = eh->getU32()+70;
+ width = ew->getU32();
+ height = eh->getU32();
} else
ThrowRDE("Unable to retrieve image size");
diff --git a/src/external/rawspeed/src/librawspeed/decoders/KdcDecoder.h b/src/external/rawspeed/src/librawspeed/decoders/KdcDecoder.h
index ebd20372d..5e5038ec1 100644
--- a/src/external/rawspeed/src/librawspeed/decoders/KdcDecoder.h
+++ b/src/external/rawspeed/src/librawspeed/decoders/KdcDecoder.h
@@ -24,7 +24,7 @@
#include "common/RawImage.h" // for RawImage
#include "decoders/AbstractTiffDecoder.h" // for AbstractTiffDecoder
#include "tiff/TiffIFD.h" // for TiffRootIFDOwner
-#include <algorithm> // for move
+#include <utility> // for move
namespace rawspeed {
diff --git a/src/external/rawspeed/src/librawspeed/decoders/MefDecoder.h b/src/external/rawspeed/src/librawspeed/decoders/MefDecoder.h
index eb336f1b7..66cb2808a 100644
--- a/src/external/rawspeed/src/librawspeed/decoders/MefDecoder.h
+++ b/src/external/rawspeed/src/librawspeed/decoders/MefDecoder.h
@@ -24,7 +24,7 @@
#include "common/RawImage.h" // for RawImage
#include "decoders/SimpleTiffDecoder.h" // for SimpleTiffDecoder
#include "tiff/TiffIFD.h" // for TiffRootIFDOwner
-#include <algorithm> // for move
+#include <utility> // for move
namespace rawspeed {
diff --git a/src/external/rawspeed/src/librawspeed/decoders/MosDecoder.cpp b/src/external/rawspeed/src/librawspeed/decoders/MosDecoder.cpp
index 3c2e0bbfd..2e0c62125 100644
--- a/src/external/rawspeed/src/librawspeed/decoders/MosDecoder.cpp
+++ b/src/external/rawspeed/src/librawspeed/decoders/MosDecoder.cpp
@@ -33,12 +33,12 @@
#include "tiff/TiffEntry.h" // for TiffEntry
#include "tiff/TiffIFD.h" // for TiffRootIFD, Tif...
#include "tiff/TiffTag.h" // for TiffTag::TILEOFF...
-#include <algorithm> // for move
#include <cassert> // for assert
#include <cstring> // for memchr
#include <istream> // for istringstream
#include <memory> // for unique_ptr
#include <string> // for string, allocator
+#include <utility> // for move
using std::string;
@@ -162,7 +162,7 @@ void MosDecoder::decodeMetaDataInternal(const CameraMetaData* meta) {
// check for nulltermination of string inside bounds
if (!memchr(bs.peekData(bs.getRemainSize()), 0, bs.getRemainSize()))
break;
- uint32 tmp[4] = {0};
+ std::array<uint32, 4> tmp = {{}};
std::istringstream iss(bs.peekString());
iss >> tmp[0] >> tmp[1] >> tmp[2] >> tmp[3];
if (!iss.fail() && tmp[0] > 0 && tmp[1] > 0 && tmp[2] > 0 &&
diff --git a/src/external/rawspeed/src/librawspeed/decoders/MrwDecoder.cpp b/src/external/rawspeed/src/librawspeed/decoders/MrwDecoder.cpp
index 6e91d8062..0c8dadec4 100644
--- a/src/external/rawspeed/src/librawspeed/decoders/MrwDecoder.cpp
+++ b/src/external/rawspeed/src/librawspeed/decoders/MrwDecoder.cpp
@@ -23,15 +23,14 @@
#include "decoders/MrwDecoder.h"
#include "common/Common.h" // for uint32
#include "common/Point.h" // for iPoint2D
-#include "decoders/RawDecoderException.h" // for RawDecoderExcept...
+#include "decoders/RawDecoderException.h" // for ThrowRDE
#include "decompressors/UncompressedDecompressor.h" // for UncompressedDeco...
-#include "io/Buffer.h" // for Buffer, DataBuffer
+#include "io/Buffer.h" // for DataBuffer, Buffer
#include "io/ByteStream.h" // for ByteStream
-#include "io/Endianness.h" // for Endianness::big
-#include "io/IOException.h" // for IOException
+#include "io/Endianness.h" // for Endianness, Endi...
#include "metadata/Camera.h" // for Hints
#include "parsers/TiffParser.h" // for TiffParser
-#include "tiff/TiffIFD.h" // for TiffID, TiffRoot...
+#include "tiff/TiffIFD.h" // for TiffRootIFDOwner
#include <cassert> // for assert
#include <cstring> // for memcmp, size_t
#include <memory> // for unique_ptr
@@ -43,12 +42,9 @@ class CameraMetaData;
MrwDecoder::MrwDecoder(const Buffer* file) : RawDecoder(file) { parseHeader(); }
int MrwDecoder::isMRW(const Buffer* input) {
- static const char magic[] = {0x00, 'M', 'R', 'M'};
- static const size_t magic_size = sizeof(magic);
- static_assert(4 == magic_size, "wrong magic size");
-
- const unsigned char* data = input->getData(0, magic_size);
- return 0 == memcmp(&data[0], magic, magic_size);
+ static const std::array<char, 4> magic = {{0x00, 'M', 'R', 'M'}};
+ const unsigned char* data = input->getData(0, magic.size());
+ return 0 == memcmp(data, magic.data(), magic.size());
}
void MrwDecoder::parseHeader() {
diff --git a/src/external/rawspeed/src/librawspeed/decoders/MrwDecoder.h b/src/external/rawspeed/src/librawspeed/decoders/MrwDecoder.h
index 59611896a..2c50fddb4 100644
--- a/src/external/rawspeed/src/librawspeed/decoders/MrwDecoder.h
+++ b/src/external/rawspeed/src/librawspeed/decoders/MrwDecoder.h
@@ -40,7 +40,7 @@ class MrwDecoder final : public RawDecoder {
Buffer imageData;
uint32 bpp = 0;
uint32 packed = 0;
- float wb_coeffs[4] = {NAN, NAN, NAN, NAN};
+ std::array<float, 4> wb_coeffs = {{NAN, NAN, NAN, NAN}};
public:
explicit MrwDecoder(const Buffer* file);
diff --git a/src/external/rawspeed/src/librawspeed/decoders/NefDecoder.cpp b/src/external/rawspeed/src/librawspeed/decoders/NefDecoder.cpp
index 72fa3b85b..63e410cd2 100644
--- a/src/external/rawspeed/src/librawspeed/decoders/NefDecoder.cpp
+++ b/src/external/rawspeed/src/librawspeed/decoders/NefDecoder.cpp
@@ -22,23 +22,23 @@
#include "decoders/NefDecoder.h"
#include "common/Common.h" // for uint32, uchar8
#include "common/Point.h" // for iPoint2D
-#include "decoders/RawDecoderException.h" // for ThrowRDE, RawDec...
+#include "decoders/RawDecoderException.h" // for ThrowRDE
#include "decompressors/NikonDecompressor.h" // for NikonDecompressor
#include "decompressors/UncompressedDecompressor.h" // for UncompressedDeco...
#include "io/BitPumpMSB.h" // for BitPumpMSB
#include "io/Buffer.h" // for Buffer
#include "io/ByteStream.h" // for ByteStream
-#include "io/Endianness.h" // for getU16BE, getU32LE
-#include "io/IOException.h" // for IOException, Thr...
+#include "io/Endianness.h" // for getU16BE, Endian...
+#include "io/IOException.h" // for ThrowIOE
#include "metadata/Camera.h" // for Hints
#include "metadata/CameraMetaData.h" // for CameraMetaData
-#include "metadata/ColorFilterArray.h" // for CFAColor::CFA_GREEN
-#include "tiff/TiffEntry.h" // for TiffEntry, TiffD...
+#include "metadata/ColorFilterArray.h" // for CFA_GREEN, CFA_BLUE
+#include "tiff/TiffEntry.h" // for TiffEntry, TIFF_...
#include "tiff/TiffIFD.h" // for TiffRootIFD, Tif...
-#include "tiff/TiffTag.h" // for TiffTag, TiffTag...
+#include "tiff/TiffTag.h" // for TiffTag, IMAGELE...
+#include <algorithm> // for min
#include <cassert> // for assert
#include <cmath> // for pow, exp, log
-#include <cstring> // for strncmp
#include <memory> // for unique_ptr, allo...
#include <sstream> // for operator<<, ostr...
#include <string> // for string, operator==
@@ -120,9 +120,9 @@ RawImage NefDecoder::decodeRawInternal() {
ByteStream rawData(mFile, offsets->getU32(), counts->getU32());
- NikonDecompressor n(mRaw, bitPerPixel);
+ NikonDecompressor n(mRaw, meta->getData(), bitPerPixel);
mRaw->createData();
- n.decompress(meta->getData(), rawData, uncorrectedRawValues);
+ n.decompress(rawData, uncorrectedRawValues);
return mRaw;
}
@@ -509,9 +509,9 @@ void NefDecoder::decodeMetaDataInternal(const CameraMetaData* meta) {
ByteStream bs = wb->getData();
bs.skipBytes(version == 0x204 ? 284 : 4);
- uchar8 buf[14+8];
+ std::array<uchar8, 14 + 8> buf;
for (unsigned char& i : buf) {
- cj += ci * ck;
+ cj = uchar8(cj + ci * ck); // modulo arithmetics.
i = bs.getByte() ^ cj;
ck++;
}
@@ -519,11 +519,11 @@ void NefDecoder::decodeMetaDataInternal(const CameraMetaData* meta) {
// Finally set the WB coeffs
uint32 off = (version == 0x204) ? 6 : 14;
mRaw->metadata.wbCoeffs[0] =
- static_cast<float>(getU16BE(buf + off + 0));
+ static_cast<float>(getU16BE(buf.data() + off + 0));
mRaw->metadata.wbCoeffs[1] =
- static_cast<float>(getU16BE(buf + off + 2));
+ static_cast<float>(getU16BE(buf.data() + off + 2));
mRaw->metadata.wbCoeffs[2] =
- static_cast<float>(getU16BE(buf + off + 6));
+ static_cast<float>(getU16BE(buf.data() + off + 6));
}
}
} else if (mRootIFD->hasEntryRecursive(static_cast<TiffTag>(0x0014))) {
@@ -697,7 +697,9 @@ std::vector<ushort16> NefDecoder::gammaCurve(double pwr, double ts, int mode,
std::vector<ushort16> curve(65536);
int i;
- double g[6], bnd[2]={0,0}, r;
+ std::array<double, 6> g;
+ std::array<double, 2> bnd = {{}};
+ double r;
g[0] = pwr;
g[1] = ts;
g[2] = g[3] = g[4] = 0;
diff --git a/src/external/rawspeed/src/librawspeed/decoders/NefDecoder.h b/src/external/rawspeed/src/librawspeed/decoders/NefDecoder.h
index 1d14aa830..6acc73e14 100644
--- a/src/external/rawspeed/src/librawspeed/decoders/NefDecoder.h
+++ b/src/external/rawspeed/src/librawspeed/decoders/NefDecoder.h
@@ -25,9 +25,9 @@
#include "decoders/AbstractTiffDecoder.h" // for AbstractTiffDecoder
#include "decoders/RawDecoder.h" // for RawDecoder::RawSlice
#include "tiff/TiffIFD.h" // for TiffIFD (ptr only), TiffRo...
-#include <algorithm> // for move
#include <array> // for array
#include <string> // for string
+#include <utility> // for move
#include <vector> // for vector
namespace rawspeed {
diff --git a/src/external/rawspeed/src/librawspeed/decoders/OrfDecoder.cpp b/src/external/rawspeed/src/librawspeed/decoders/OrfDecoder.cpp
index 0063dd128..4a92fe8da 100644
--- a/src/external/rawspeed/src/librawspeed/decoders/OrfDecoder.cpp
+++ b/src/external/rawspeed/src/librawspeed/decoders/OrfDecoder.cpp
@@ -21,26 +21,20 @@
*/
#include "decoders/OrfDecoder.h"
-#include "common/Common.h" // for uint32, ushort16
-#include "common/NORangesSet.h" // for NORangesSet
+#include "common/Common.h" // for uint32, uchar8
+#include "common/NORangesSet.h" // for set
#include "common/Point.h" // for iPoint2D
-#include "decoders/RawDecoderException.h" // for RawDecoderExcept...
+#include "decoders/RawDecoderException.h" // for ThrowRDE
#include "decompressors/OlympusDecompressor.h" // for OlympusDecompressor
#include "decompressors/UncompressedDecompressor.h" // for UncompressedDeco...
-#include "io/BitPumpMSB.h" // for BitPumpMSB
#include "io/Buffer.h" // for Buffer
#include "io/ByteStream.h" // for ByteStream
-#include "io/Endianness.h" // for Endianness
-#include "io/IOException.h" // for IOException
-#include "metadata/Camera.h" // for Hints
+#include "io/Endianness.h" // for Endianness, getH...
#include "metadata/ColorFilterArray.h" // for ColorFilterArray
-#include "tiff/TiffEntry.h" // for TiffEntry
+#include "tiff/TiffEntry.h" // for TiffEntry, TIFF_...
#include "tiff/TiffIFD.h" // for TiffRootIFD, Tif...
-#include "tiff/TiffTag.h" // for TiffTag, TiffTag...
-#include <algorithm> // for min
-#include <cassert> // for assert
-#include <cmath> // for signbit
-#include <cstdlib> // for abs
+#include "tiff/TiffTag.h" // for STRIPOFFSETS
+#include <array> // for array
#include <memory> // for unique_ptr
#include <string> // for operator==, string
@@ -122,48 +116,108 @@ RawImage OrfDecoder::decodeRawInternal() {
ByteStream input(handleSlices());
- if (raw->getEntry(STRIPOFFSETS)->count != 1 ||
- hints.has("force_uncompressed")) {
- mRaw->createData();
- decodeUncompressed(input, width, height, input.getSize());
- } else {
- OlympusDecompressor o(mRaw);
- mRaw->createData();
- o.decompress(std::move(input));
- }
+ if (decodeUncompressed(input, width, height, input.getSize()))
+ return mRaw;
+
+ if (raw->getEntry(STRIPOFFSETS)->count != 1)
+ ThrowRDE("%u stripes, and not uncompressed. Unsupported.",
+ raw->getEntry(STRIPOFFSETS)->count);
+
+ OlympusDecompressor o(mRaw);
+ mRaw->createData();
+ o.decompress(std::move(input));
return mRaw;
}
-void OrfDecoder::decodeUncompressed(const ByteStream& s, uint32 w, uint32 h,
+bool OrfDecoder::decodeUncompressed(const ByteStream& s, uint32 w, uint32 h,
uint32 size) {
UncompressedDecompressor u(s, mRaw);
- if (hints.has("packed_with_control"))
+ // 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();
u.decode12BitRaw<Endianness::little, false, true>(w, h);
- else if (hints.has("jpeg32_bitorder")) {
+ return true;
+ }
+
+ if (size == w * h * 12 / 8) { // We're in a 12-bit packed raw
iPoint2D dimensions(w, h);
iPoint2D pos(0, 0);
+ mRaw->createData();
u.readUncompressedRaw(dimensions, pos, w * 12 / 8, 12, BitOrder_MSB32);
- } else if (size >= w * h * 2) { // We're in an unpacked raw
+ return true;
+ }
+
+ if (size == w * h * 2) { // We're in an unpacked raw
+ mRaw->createData();
// FIXME: seems fishy
if (s.getByteOrder() == getHostEndianness())
u.decodeRawUnpacked<12, Endianness::little>(w, h);
else
u.decode12BitRawUnpackedLeftAligned<Endianness::big>(w, h);
- } else if (size >= w*h*3/2) { // We're in one of those weird interlaced packed raws
+ return true;
+ }
+
+ if (size >
+ w * h * 3 / 2) { // We're in one of those weird interlaced packed raws
+ mRaw->createData();
u.decode12BitRaw<Endianness::big, true>(w, h);
- } else {
- ThrowRDE("Don't know how to handle the encoding in this file");
+ return true;
+ }
+
+ // Does not appear to be uncomporessed. Maybe it's compressed?
+ return false;
+}
+
+void OrfDecoder::parseCFA() {
+ if (!mRootIFD->hasEntryRecursive(EXIFCFAPATTERN))
+ ThrowRDE("No EXIFCFAPATTERN entry found!");
+
+ TiffEntry* CFA = mRootIFD->getEntryRecursive(EXIFCFAPATTERN);
+ if (CFA->type != TiffDataType::TIFF_UNDEFINED || CFA->count != 8) {
+ ThrowRDE("Bad EXIFCFAPATTERN entry (type %u, count %u).", CFA->type,
+ CFA->count);
+ }
+
+ iPoint2D cfaSize(CFA->getU16(0), CFA->getU16(1));
+ if (cfaSize != iPoint2D{2, 2})
+ ThrowRDE("Bad CFA size: (%i, %i)", cfaSize.x, cfaSize.y);
+
+ mRaw->cfa.setSize(cfaSize);
+
+ auto int2enum = [](uchar8 i) -> CFAColor {
+ switch (i) {
+ case 0:
+ return CFA_RED;
+ case 1:
+ return CFA_GREEN;
+ case 2:
+ return CFA_BLUE;
+ default:
+ ThrowRDE("Unexpected CFA color: %u", i);
+ }
+ };
+
+ for (int y = 0; y < cfaSize.y; y++) {
+ for (int x = 0; x < cfaSize.x; x++) {
+ uchar8 c1 = CFA->getByte(4 + x + y * cfaSize.x);
+ CFAColor c2 = int2enum(c1);
+ mRaw->cfa.setColorAt(iPoint2D(x, y), c2);
+ }
}
}
void OrfDecoder::decodeMetaDataInternal(const CameraMetaData* meta) {
int iso = 0;
- mRaw->cfa.setCFA(iPoint2D(2,2), CFA_RED, CFA_GREEN, CFA_GREEN, CFA_BLUE);
if (mRootIFD->hasEntryRecursive(ISOSPEEDRATINGS))
iso = mRootIFD->getEntryRecursive(ISOSPEEDRATINGS)->getU32();
+ parseCFA();
+
setMetaData(meta, "", iso);
if (mRootIFD->hasEntryRecursive(OLYMPUSREDMULTIPLIER) &&
diff --git a/src/external/rawspeed/src/librawspeed/decoders/OrfDecoder.h b/src/external/rawspeed/src/librawspeed/decoders/OrfDecoder.h
index 3a7a7d038..ba2554869 100644
--- a/src/external/rawspeed/src/librawspeed/decoders/OrfDecoder.h
+++ b/src/external/rawspeed/src/librawspeed/decoders/OrfDecoder.h
@@ -25,12 +25,11 @@
#include "common/RawImage.h" // for RawImage
#include "decoders/AbstractTiffDecoder.h" // for AbstractTiffDecoder
#include "io/ByteStream.h" // for ByteStream
-#include "tiff/TiffIFD.h" // for TiffRootIFDOwner
-#include <algorithm> // for move
+#include "tiff/TiffIFD.h" // for TiffRootIFD (ptr only)
+#include <utility> // for move
namespace rawspeed {
-class ByteStream;
class CameraMetaData;
class Buffer;
@@ -48,8 +47,10 @@ public:
void decodeMetaDataInternal(const CameraMetaData* meta) override;
private:
+ void parseCFA();
+
int getDecoderVersion() const override { return 3; }
- void decodeUncompressed(const ByteStream& s, uint32 w, uint32 h, uint32 size);
+ bool decodeUncompressed(const ByteStream& s, uint32 w, uint32 h, uint32 size);
};
} // namespace rawspeed
diff --git a/src/external/rawspeed/src/librawspeed/decoders/PefDecoder.cpp b/src/external/rawspeed/src/librawspeed/decoders/PefDecoder.cpp
index b68db8af9..2a4d3658f 100644
--- a/src/external/rawspeed/src/librawspeed/decoders/PefDecoder.cpp
+++ b/src/external/rawspeed/src/librawspeed/decoders/PefDecoder.cpp
@@ -20,16 +20,16 @@
*/
#include "decoders/PefDecoder.h"
-#include "common/Common.h" // for uint32, BitOrder::BitO...
+#include "common/Common.h" // for uint32, BitOrder_MSB
#include "common/Point.h" // for iPoint2D
-#include "decoders/RawDecoderException.h" // for RawDecoderException (p...
+#include "decoders/RawDecoderException.h" // for ThrowRDE
#include "decompressors/PentaxDecompressor.h" // for PentaxDecompressor
#include "io/ByteStream.h" // for ByteStream
-#include "io/IOException.h" // for IOException
-#include "metadata/ColorFilterArray.h" // for CFAColor::CFA_GREEN
-#include "tiff/TiffEntry.h" // for TiffEntry
+#include "metadata/ColorFilterArray.h" // for CFA_GREEN, CFA_BLUE
+#include "tiff/TiffEntry.h" // for TiffEntry, TIFF_UNDEFINED
#include "tiff/TiffIFD.h" // for TiffRootIFD, TiffIFD
-#include "tiff/TiffTag.h" // for TiffTag, TiffTag::ISOS...
+#include "tiff/TiffTag.h" // for TiffTag, ISOSPEEDRATINGS
+#include <array> // for array
#include <memory> // for unique_ptr
#include <string> // for operator==, string
diff --git a/src/external/rawspeed/src/librawspeed/decoders/PefDecoder.h b/src/external/rawspeed/src/librawspeed/decoders/PefDecoder.h
index 4a4893377..99b8f3e89 100644
--- a/src/external/rawspeed/src/librawspeed/decoders/PefDecoder.h
+++ b/src/external/rawspeed/src/librawspeed/decoders/PefDecoder.h
@@ -23,7 +23,7 @@
#include "common/RawImage.h" // for RawImage
#include "decoders/AbstractTiffDecoder.h" // for AbstractTiffDecoder
#include "tiff/TiffIFD.h" // for TiffRootIFDOwner
-#include <algorithm> // for move
+#include <utility> // for move
namespace rawspeed {
diff --git a/src/external/rawspeed/src/librawspeed/decoders/RafDecoder.cpp b/src/external/rawspeed/src/librawspeed/decoders/RafDecoder.cpp
index 01445b1df..519c58142 100644
--- a/src/external/rawspeed/src/librawspeed/decoders/RafDecoder.cpp
+++ b/src/external/rawspeed/src/librawspeed/decoders/RafDecoder.cpp
@@ -28,13 +28,15 @@
#include "io/Buffer.h" // for Buffer
#include "io/ByteStream.h" // for ByteStream
#include "io/Endianness.h" // for Endianness, getH...
+#include "metadata/BlackArea.h" // for BlackArea
#include "metadata/Camera.h" // for Camera, Hints
#include "metadata/CameraMetaData.h" // for CameraMetaData
#include "metadata/CameraSensorInfo.h" // for CameraSensorInfo
#include "metadata/ColorFilterArray.h" // for ColorFilterArray
#include "tiff/TiffEntry.h" // for TiffEntry
#include "tiff/TiffIFD.h" // for TiffRootIFD, Tif...
-#include "tiff/TiffTag.h" // for TiffTag::FUJI_RA...
+#include "tiff/TiffTag.h" // for FUJI_RAWIMAGEFUL...
+#include <array> // for array
#include <cassert> // for assert
#include <cstdio> // for size_t
#include <cstring> // for memcmp
@@ -45,10 +47,11 @@
namespace rawspeed {
bool RafDecoder::isRAF(const Buffer* input) {
- static const char magic[] = "FUJIFILMCCD-RAW ";
- static const size_t magic_size = sizeof(magic) - 1; // excluding \0
- const unsigned char* data = input->getData(0, magic_size);
- return 0 == memcmp(&data[0], magic, magic_size);
+ static const std::array<char, 16> magic = {{'F', 'U', 'J', 'I', 'F', 'I', 'L',
+ 'M', 'C', 'C', 'D', '-', 'R', 'A',
+ 'W', ' '}};
+ const unsigned char* data = input->getData(0, magic.size());
+ return 0 == memcmp(data, magic.data(), magic.size());
}
bool RafDecoder::isAppropriateDecoder(const TiffRootIFD* rootIFD,
diff --git a/src/external/rawspeed/src/librawspeed/decoders/RafDecoder.h b/src/external/rawspeed/src/librawspeed/decoders/RafDecoder.h
index 368ac313c..3821f37e6 100644
--- a/src/external/rawspeed/src/librawspeed/decoders/RafDecoder.h
+++ b/src/external/rawspeed/src/librawspeed/decoders/RafDecoder.h
@@ -24,7 +24,7 @@
#include "common/RawImage.h" // for RawImage
#include "decoders/AbstractTiffDecoder.h" // for AbstractTiffDecoder
#include "tiff/TiffIFD.h" // for TiffRootIFD (ptr only)
-#include <algorithm> // for move
+#include <utility> // for move
namespace rawspeed {
diff --git a/src/external/rawspeed/src/librawspeed/decoders/RawDecoder.cpp b/src/external/rawspeed/src/librawspeed/decoders/RawDecoder.cpp
index ee9786cdd..ee7a82677 100644
--- a/src/external/rawspeed/src/librawspeed/decoders/RawDecoder.cpp
+++ b/src/external/rawspeed/src/librawspeed/decoders/RawDecoder.cpp
@@ -19,15 +19,15 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "rawspeedconfig.h"
#include "decoders/RawDecoder.h"
-#include "common/Common.h" // for uint32, splitString
+#include "common/Common.h" // for uint32, roundUpD...
#include "common/Point.h" // for iPoint2D, iRecta...
-#include "decoders/RawDecoderException.h" // for ThrowRDE, RawDec...
+#include "decoders/RawDecoderException.h" // for ThrowRDE
#include "decompressors/UncompressedDecompressor.h" // for UncompressedDeco...
#include "io/Buffer.h" // for Buffer
#include "io/FileIOException.h" // for FileIOException
#include "io/IOException.h" // for IOException
+#include "metadata/BlackArea.h" // for BlackArea
#include "metadata/Camera.h" // for Camera, Hints
#include "metadata/CameraMetaData.h" // for CameraMetaData
#include "metadata/CameraSensorInfo.h" // for CameraSensorInfo
@@ -35,7 +35,9 @@
#include "parsers/TiffParserException.h" // for TiffParserException
#include "tiff/TiffEntry.h" // for TiffEntry
#include "tiff/TiffIFD.h" // for TiffIFD
-#include "tiff/TiffTag.h" // for TiffTag::STRIPOF...
+#include "tiff/TiffTag.h" // for BITSPERSAMPLE
+#include <array> // for array
+#include <cassert> // for assert
#include <string> // for string, basic_st...
#include <vector> // for vector
@@ -85,7 +87,7 @@ void RawDecoder::decodeUncompressed(const TiffIFD *rawIFD, BitOrder order) {
break;
default:
ThrowRDE("Unexpected bits per pixel: %u.", bitPerPixel);
- };
+ }
vector<RawSlice> slices;
slices.reserve(counts->count);
@@ -193,7 +195,11 @@ void RawDecoder::setMetaData(const CameraMetaData* meta, const string& make,
return;
}
- mRaw->cfa = cam->cfa;
+ // 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->metadata.canonical_make = cam->canonical_make;
mRaw->metadata.canonical_model = cam->canonical_model;
mRaw->metadata.canonical_alias = cam->canonical_alias;
@@ -222,7 +228,7 @@ void RawDecoder::setMetaData(const CameraMetaData* meta, const string& make,
if (mRaw->blackAreas.empty() && !sensor->mBlackLevelSeparate.empty()) {
auto cfaArea = mRaw->cfa.getSize().area();
if (mRaw->isCFA && cfaArea <= sensor->mBlackLevelSeparate.size()) {
- for (uint32 i = 0; i < cfaArea; i++) {
+ for (auto i = 0UL; i < cfaArea; i++) {
mRaw->blackLevelSeparate[i] = sensor->mBlackLevelSeparate[i];
}
} else if (!mRaw->isCFA && mRaw->getCpp() <= sensor->mBlackLevelSeparate.size()) {
diff --git a/src/external/rawspeed/src/librawspeed/decoders/Rw2Decoder.cpp b/src/external/rawspeed/src/librawspeed/decoders/Rw2Decoder.cpp
index 6a9c0e744..f6bace065 100644
--- a/src/external/rawspeed/src/librawspeed/decoders/Rw2Decoder.cpp
+++ b/src/external/rawspeed/src/librawspeed/decoders/Rw2Decoder.cpp
@@ -24,15 +24,17 @@
#include "common/Point.h" // for iPoint2D
#include "decoders/RawDecoderException.h" // for ThrowRDE
#include "decompressors/PanasonicDecompressor.h" // for PanasonicDecompr...
+#include "decompressors/PanasonicDecompressorV5.h" // for PanasonicDecompr...
#include "decompressors/UncompressedDecompressor.h" // for UncompressedDeco...
#include "io/Buffer.h" // for Buffer
#include "io/ByteStream.h" // for ByteStream
#include "io/Endianness.h" // for Endianness, Endi...
#include "metadata/Camera.h" // for Hints
-#include "metadata/ColorFilterArray.h" // for CFAColor::CFA_GREEN
+#include "metadata/ColorFilterArray.h" // for CFA_GREEN, Color...
#include "tiff/TiffEntry.h" // for TiffEntry
-#include "tiff/TiffIFD.h" // for TiffIFD, TiffRoo...
-#include "tiff/TiffTag.h" // for TiffTag, TiffTag...
+#include "tiff/TiffIFD.h" // for TiffRootIFD, Tif...
+#include "tiff/TiffTag.h" // for TiffTag, PANASON...
+#include <array> // for array
#include <cmath> // for fabs
#include <memory> // for unique_ptr
#include <string> // for string, operator==
@@ -76,7 +78,7 @@ RawImage Rw2Decoder::decodeRawInternal() {
if (offsets->count != 1) {
ThrowRDE("Multiple Strips found: %u", offsets->count);
}
- offset = offsets->getU32();
+ uint32 offset = offsets->getU32();
if (!mFile->isValid(offset))
ThrowRDE("Invalid image data offset, cannot decode.");
@@ -95,11 +97,10 @@ RawImage Rw2Decoder::decodeRawInternal() {
mRaw->createData();
u.decode12BitRaw<Endianness::little, false, true>(width, height);
} else {
- // It's using the new .RW2 decoding method
- load_flags = 0;
- // It's using the new .RW2 decoding method
+ uint32 section_split_offset = 0;
PanasonicDecompressor p(mRaw, ByteStream(mFile, offset),
- hints.has("zero_is_not_bad"), load_flags);
+ hints.has("zero_is_not_bad"),
+ section_split_offset);
mRaw->createData();
p.decompress();
}
@@ -112,18 +113,29 @@ RawImage Rw2Decoder::decodeRawInternal() {
ThrowRDE("Multiple Strips found: %u", offsets->count);
}
- offset = offsets->getU32();
+ uint32 offset = offsets->getU32();
- if (!mFile->isValid(offset))
- ThrowRDE("Invalid image data offset, cannot decode.");
+ ByteStream bs(mFile, offset);
+
+ bool v5Processing = raw->hasEntry(PANASONIC_RAWFORMAT) &&
+ raw->getEntry(PANASONIC_RAWFORMAT)->getU16() == 5;
+
+ rawspeed::ushort16 bitsPerSample = 12;
+ if (raw->hasEntry(PANASONIC_BITSPERSAMPLE)) {
+ bitsPerSample = raw->getEntry(PANASONIC_BITSPERSAMPLE)->getU16();
+ }
- // It's using the new .RW2 decoding method
- load_flags = 0x2008;
- // It's using the new .RW2 decoding method
- PanasonicDecompressor p(mRaw, ByteStream(mFile, offset),
- hints.has("zero_is_not_bad"), load_flags);
- mRaw->createData();
- p.decompress();
+ if (v5Processing) {
+ PanasonicDecompressorV5 v5(mRaw, bs, bitsPerSample);
+ mRaw->createData();
+ v5.decompress();
+ } else {
+ uint32 section_split_offset = 0x1FF8;
+ PanasonicDecompressor p(mRaw, bs, hints.has("zero_is_not_bad"),
+ section_split_offset);
+ mRaw->createData();
+ p.decompress();
+ }
}
return mRaw;
diff --git a/src/external/rawspeed/src/librawspeed/decoders/Rw2Decoder.h b/src/external/rawspeed/src/librawspeed/decoders/Rw2Decoder.h
index 5f5b4f999..cceb1a949 100644
--- a/src/external/rawspeed/src/librawspeed/decoders/Rw2Decoder.h
+++ b/src/external/rawspeed/src/librawspeed/decoders/Rw2Decoder.h
@@ -21,12 +21,11 @@
#pragma once
-#include "common/Common.h" // for uint32
#include "common/RawImage.h" // for RawImage
#include "decoders/AbstractTiffDecoder.h" // for AbstractTiffDecoder
-#include "tiff/TiffIFD.h" // for TiffRootIFDOwner
-#include <algorithm> // for move
+#include "tiff/TiffIFD.h" // for TiffRootIFD (ptr only)
#include <string> // for string
+#include <utility> // for move
namespace rawspeed {
@@ -46,12 +45,10 @@ public:
void checkSupportInternal(const CameraMetaData* meta) override;
protected:
- int getDecoderVersion() const override { return 2; }
+ int getDecoderVersion() const override { return 3; }
private:
std::string guessMode();
- uint32 offset = 0;
- uint32 load_flags = 0;
};
} // namespace rawspeed
diff --git a/src/external/rawspeed/src/librawspeed/decoders/SimpleTiffDecoder.h b/src/external/rawspeed/src/librawspeed/decoders/SimpleTiffDecoder.h
index fecf038ea..c4c85142a 100644
--- a/src/external/rawspeed/src/librawspeed/decoders/SimpleTiffDecoder.h
+++ b/src/external/rawspeed/src/librawspeed/decoders/SimpleTiffDecoder.h
@@ -25,7 +25,7 @@
#include "common/Common.h" // for uint32
#include "decoders/AbstractTiffDecoder.h" // for AbstractTiffDecoder
#include "tiff/TiffIFD.h" // for TiffIFD (ptr only), TiffRo...
-#include <algorithm> // for move
+#include <utility> // for move
namespace rawspeed {
diff --git a/src/external/rawspeed/src/librawspeed/decoders/SrwDecoder.cpp b/src/external/rawspeed/src/librawspeed/decoders/SrwDecoder.cpp
index 57e1e2449..ca73ed6f0 100644
--- a/src/external/rawspeed/src/librawspeed/decoders/SrwDecoder.cpp
+++ b/src/external/rawspeed/src/librawspeed/decoders/SrwDecoder.cpp
@@ -20,18 +20,20 @@
*/
#include "decoders/SrwDecoder.h"
-#include "common/Common.h" // for BitOrder::BitOrder_LSB
+#include "common/Common.h" // for uint32, BitOrder_LSB
#include "common/Point.h" // for iPoint2D
#include "decoders/RawDecoderException.h" // for ThrowRDE
#include "decompressors/SamsungV0Decompressor.h" // for SamsungV0Decompressor
#include "decompressors/SamsungV1Decompressor.h" // for SamsungV1Decompressor
#include "decompressors/SamsungV2Decompressor.h" // for SamsungV2Decompressor
+#include "io/Buffer.h" // for Buffer, DataBuffer
#include "io/ByteStream.h" // for ByteStream
+#include "io/Endianness.h" // for Endianness, Endiann...
#include "metadata/Camera.h" // for Hints
#include "metadata/CameraMetaData.h" // for CameraMetaData
-#include "tiff/TiffEntry.h" // for TiffEntry
+#include "tiff/TiffEntry.h" // for TiffEntry, TIFF_LONG
#include "tiff/TiffIFD.h" // for TiffRootIFD, TiffIFD
-#include "tiff/TiffTag.h" // for TiffTag::BITSPERSAMPLE
+#include "tiff/TiffTag.h" // for STRIPOFFSETS, BITSP...
#include <memory> // for unique_ptr
#include <sstream> // for operator<<, ostring...
#include <string> // for string, operator==
diff --git a/src/external/rawspeed/src/librawspeed/decoders/SrwDecoder.h b/src/external/rawspeed/src/librawspeed/decoders/SrwDecoder.h
index a1b540f9f..9510608c0 100644
--- a/src/external/rawspeed/src/librawspeed/decoders/SrwDecoder.h
+++ b/src/external/rawspeed/src/librawspeed/decoders/SrwDecoder.h
@@ -23,8 +23,8 @@
#include "common/RawImage.h" // for RawImage
#include "decoders/AbstractTiffDecoder.h" // for AbstractTiffDecoder
#include "tiff/TiffIFD.h" // for TiffIFD (ptr only), TiffRo...
-#include <algorithm> // for move
#include <string> // for string
+#include <utility> // for move
namespace rawspeed {
diff --git a/src/external/rawspeed/src/librawspeed/decoders/ThreefrDecoder.cpp b/src/external/rawspeed/src/librawspeed/decoders/ThreefrDecoder.cpp
index 7eb575a37..6ff7d82aa 100644
--- a/src/external/rawspeed/src/librawspeed/decoders/ThreefrDecoder.cpp
+++ b/src/external/rawspeed/src/librawspeed/decoders/ThreefrDecoder.cpp
@@ -24,13 +24,13 @@
#include "common/Point.h" // for iPoint2D
#include "decoders/RawDecoderException.h" // for ThrowRDE
#include "decompressors/HasselbladDecompressor.h" // for HasselbladDecompre...
+#include "io/Buffer.h" // for Buffer
#include "io/ByteStream.h" // for ByteStream
-#include "io/IOException.h" // for IOException
#include "metadata/Camera.h" // for Hints
-#include "metadata/ColorFilterArray.h" // for CFAColor::CFA_GREEN
+#include "metadata/ColorFilterArray.h" // for CFA_GREEN, CFA_BLUE
#include "tiff/TiffEntry.h" // for TiffEntry
#include "tiff/TiffIFD.h" // for TiffRootIFD, TiffIFD
-#include "tiff/TiffTag.h" // for TiffTag::ASSHOTNEU...
+#include "tiff/TiffTag.h" // for ASSHOTNEUTRAL, STR...
#include <memory> // for unique_ptr
#include <string> // for operator==, string
@@ -79,7 +79,7 @@ void ThreefrDecoder::decodeMetaDataInternal(const CameraMetaData* meta) {
if (wb->count == 3) {
for (uint32 i = 0; i < 3; i++) {
const float div = wb->getFloat(i);
- if (div == 0.0f)
+ if (div == 0.0F)
ThrowRDE("Can not decode WB, multiplier is zero/");
mRaw->metadata.wbCoeffs[i] = 1.0F / div;
diff --git a/src/external/rawspeed/src/librawspeed/decoders/ThreefrDecoder.h b/src/external/rawspeed/src/librawspeed/decoders/ThreefrDecoder.h
index fc3d03db4..beff7d0d2 100644
--- a/src/external/rawspeed/src/librawspeed/decoders/ThreefrDecoder.h
+++ b/src/external/rawspeed/src/librawspeed/decoders/ThreefrDecoder.h
@@ -24,7 +24,7 @@
#include "common/RawImage.h" // for RawImage
#include "decoders/AbstractTiffDecoder.h" // for AbstractTiffDecoder
#include "tiff/TiffIFD.h" // for TiffRootIFDOwner
-#include <algorithm> // for move
+#include <utility> // for move
namespace rawspeed {
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/AbstractDngDecompressor.cpp b/src/external/rawspeed/src/librawspeed/decompressors/AbstractDngDecompressor.cpp
index 8cfe1e17b..18173edc5 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/AbstractDngDecompressor.cpp
+++ b/src/external/rawspeed/src/librawspeed/decompressors/AbstractDngDecompressor.cpp
@@ -20,7 +20,7 @@
#include "rawspeedconfig.h" // for HAVE_JPEG, HAVE_...
#include "decompressors/AbstractDngDecompressor.h"
-#include "common/Common.h" // for BitOrder::BitOrd...
+#include "common/Common.h" // for BitOrder_LSB
#include "common/Point.h" // for iPoint2D
#include "common/RawImage.h" // for RawImageData
#include "decoders/RawDecoderException.h" // for RawDecoderException
@@ -28,11 +28,10 @@
#include "decompressors/JpegDecompressor.h" // for JpegDecompressor
#include "decompressors/LJpegDecompressor.h" // for LJpegDecompressor
#include "decompressors/UncompressedDecompressor.h" // for UncompressedDeco...
-#include "io/Buffer.h" // for Buffer (ptr only)
+#include "decompressors/VC5Decompressor.h" // for VC5Decompressor
#include "io/ByteStream.h" // for ByteStream
#include "io/Endianness.h" // for Endianness, Endi...
-#include "io/IOException.h" // for IOException
-#include "tiff/TiffIFD.h" // for getTiffByteOrder
+#include "io/IOException.h" // for IOException, Thr...
#include <cassert> // for assert
#include <cstdio> // for size_t
#include <limits> // for numeric_limits
@@ -111,7 +110,7 @@ void AbstractDngDecompressor::decompressThreaded(
/* Deflate compression */
} else if (compression == 8) {
#ifdef HAVE_ZLIB
- std::unique_ptr<unsigned char[]> uBuffer;
+ std::unique_ptr<unsigned char[]> uBuffer; // NOLINT
for (size_t i = t->start; i < t->end && i < slices.size(); i++) {
auto e = &slices[i];
@@ -130,6 +129,19 @@ void AbstractDngDecompressor::decompressThreaded(
"ZLIB is not present! Deflate compression will not be supported!"
ThrowRDE("deflate support is disabled.");
#endif
+ /* VC-5 */
+ } else if (compression == 9) {
+ for (size_t i = t->start; i < t->end && i < slices.size(); i++) {
+ auto e = &slices[i];
+ VC5Decompressor d(e->bs, mRaw);
+ try {
+ d.decode(e->offX, e->offY, e->width, e->height);
+ } catch (RawDecoderException& err) {
+ mRaw->setError(err.what());
+ } catch (IOException& err) {
+ mRaw->setError(err.what());
+ }
+ }
/* Lossy DNG */
} else if (compression == 0x884c) {
#ifdef HAVE_JPEG
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/AbstractDngDecompressor.h b/src/external/rawspeed/src/librawspeed/decompressors/AbstractDngDecompressor.h
index 44b6545ea..626ffeaa6 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/AbstractDngDecompressor.h
+++ b/src/external/rawspeed/src/librawspeed/decompressors/AbstractDngDecompressor.h
@@ -21,6 +21,7 @@
#pragma once
#include "common/Common.h" // for uint32
+#include "common/Point.h" // for iPoint2D
#include "decompressors/AbstractParallelizedDecompressor.h" // for Abstract...
#include "io/ByteStream.h" // for ByteStream
#include <cassert> // for assert
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/AbstractHuffmanTable.h b/src/external/rawspeed/src/librawspeed/decompressors/AbstractHuffmanTable.h
new file mode 100644
index 000000000..a62c1e9a3
--- /dev/null
+++ b/src/external/rawspeed/src/librawspeed/decompressors/AbstractHuffmanTable.h
@@ -0,0 +1,247 @@
+/*
+ RawSpeed - RAW file decoder.
+
+ Copyright (C) 2017 Axel Waggershauser
+ Copyright (C) 2017-2018 Roman Lebedev
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#pragma once
+
+#include "common/Common.h" // for uchar8, uint32, ushort16
+#include "decoders/RawDecoderException.h" // for ThrowRDE
+#include "io/Buffer.h" // for Buffer
+#include <algorithm> // for copy, adjacent_find, max_e...
+#include <cassert> // for assert
+#include <cstddef> // for size_t
+#include <functional> // for less, less_equal
+#include <iterator> // for back_insert_iterator, back...
+#include <numeric> // for accumulate
+#include <vector> // for vector, operator==
+
+namespace rawspeed {
+
+class AbstractHuffmanTable {
+public:
+ struct CodeSymbol final {
+ ushort16 code; // the code (bit pattern found inside the stream)
+ uchar8 code_len; // the code length in bits, valid values are 1..16
+
+ CodeSymbol() = default;
+
+ CodeSymbol(ushort16 code_, uchar8 code_len_)
+ : code(code_), code_len(code_len_) {
+ assert(code_len > 0);
+ assert(code_len <= 16);
+ assert(code <= ((1U << code_len) - 1U));
+ }
+
+ static bool HaveCommonPrefix(const CodeSymbol& symbol,
+ const CodeSymbol& partial) {
+ assert(partial.code_len <= symbol.code_len);
+
+ auto getNHighBits = [](const CodeSymbol& s, unsigned bits) -> ushort16 {
+ const auto shift = s.code_len - bits;
+ return s.code >> shift;
+ };
+
+ const auto s0 = getNHighBits(symbol, partial.code_len);
+ const auto s1 = partial.code;
+
+ return s0 == s1;
+ }
+ };
+
+protected:
+ inline size_t __attribute__((pure)) maxCodePlusDiffLength() const {
+ return nCodesPerLength.size() - 1 +
+ *(std::max_element(codeValues.cbegin(), codeValues.cend()));
+ }
+
+ // These two fields directly represent the contents of a JPEG DHT field
+
+ // 1. The number of codes there are per bit length, this is index 1 based.
+ // (there are always 0 codes of length 0)
+ std::vector<unsigned int> nCodesPerLength; // index is length of code
+
+ inline unsigned int __attribute__((pure)) maxCodesCount() const {
+ return std::accumulate(nCodesPerLength.begin(), nCodesPerLength.end(), 0U);
+ }
+
+ // 2. This is the actual huffman encoded data, i.e. the 'alphabet'. Each value
+ // is the number of bits following the code that encode the difference to the
+ // last pixel. Valid values are in the range 0..16.
+ // signExtended() is used to decode the difference bits to a signed int.
+ std::vector<uchar8> codeValues; // index is just sequential number
+
+ static void VerifyCodeSymbols(const std::vector<CodeSymbol>& symbols) {
+#ifndef NDEBUG
+ // The code symbols are ordered so that all the code values are strictly
+ // increasing and code lenghts are not decreasing.
+ const auto symbolSort = [](const CodeSymbol& lhs,
+ const CodeSymbol& rhs) -> bool {
+ return std::less<>()(lhs.code, rhs.code) &&
+ std::less_equal<>()(lhs.code_len, rhs.code_len);
+ };
+#endif
+ assert(std::adjacent_find(symbols.cbegin(), symbols.cend(),
+ [&symbolSort](const CodeSymbol& lhs,
+ const CodeSymbol& rhs) -> bool {
+ return !symbolSort(lhs, rhs);
+ }) == symbols.cend() &&
+ "all code symbols are globally ordered");
+
+ // No two symbols should have the same prefix (high bytes)
+ // Only analyze the lower triangular matrix, excluding diagonal
+ for (auto sId = 0UL; sId < symbols.size(); sId++) {
+ for (auto pId = 0UL; pId < sId; pId++)
+ assert(!CodeSymbol::HaveCommonPrefix(symbols[sId], symbols[pId]));
+ }
+ }
+
+ std::vector<CodeSymbol> generateCodeSymbols() const {
+ std::vector<CodeSymbol> symbols;
+
+ assert(!nCodesPerLength.empty());
+ assert(maxCodesCount() > 0);
+
+ const auto maxCodeLength = nCodesPerLength.size() - 1U;
+ assert(codeValues.size() == maxCodesCount());
+
+ // reserve all the memory. avoids lots of small allocs
+ symbols.reserve(maxCodesCount());
+
+ // Figure C.1: make table of Huffman code length for each symbol
+ // Figure C.2: generate the codes themselves
+ uint32 code = 0;
+ for (unsigned int l = 1; l <= maxCodeLength; ++l) {
+ for (unsigned int i = 0; i < nCodesPerLength[l]; ++i) {
+ assert(code <= 0xffff);
+
+ symbols.emplace_back(code, l);
+ code++;
+ }
+
+ code <<= 1;
+ }
+
+ assert(symbols.size() == maxCodesCount());
+ VerifyCodeSymbols(symbols);
+
+ return symbols;
+ }
+
+public:
+ bool operator==(const AbstractHuffmanTable& other) const {
+ return nCodesPerLength == other.nCodesPerLength &&
+ codeValues == other.codeValues;
+ }
+
+ uint32 setNCodesPerLength(const Buffer& data) {
+ assert(data.getSize() == 16);
+
+ nCodesPerLength.resize(17, 0);
+ std::copy(data.begin(), data.end(), &nCodesPerLength[1]);
+ assert(nCodesPerLength[0] == 0);
+
+ // trim empty entries from the codes per length table on the right
+ while (!nCodesPerLength.empty() && nCodesPerLength.back() == 0)
+ nCodesPerLength.pop_back();
+
+ if (nCodesPerLength.empty())
+ ThrowRDE("Codes-per-length table is empty");
+
+ assert(nCodesPerLength.back() > 0);
+
+ const auto count = maxCodesCount();
+ assert(count > 0);
+
+ if (count > 162)
+ ThrowRDE("Too big code-values table");
+
+ // We are at the Root node, len is 1, there are two possible child Nodes
+ unsigned maxCodes = 2;
+
+ for (auto codeLen = 1UL; codeLen < nCodesPerLength.size(); codeLen++) {
+ // we have codeLen bits. make sure that that code count can actually fit
+ // E.g. for len 1 we could have two codes: 0b0 and 0b1
+ // (but in that case there can be no other codes (with higher lenghts))
+ const auto maxCodesInCurrLen = (1U << codeLen);
+ const auto nCodes = nCodesPerLength[codeLen];
+ if (nCodes > maxCodesInCurrLen) {
+ ThrowRDE("Corrupt Huffman. Can never have %u codes in %lu-bit len",
+ nCodes, codeLen);
+ }
+
+ // Also, check that we actually can have this much leafs for this lenght
+ if (nCodes > maxCodes) {
+ ThrowRDE(
+ "Corrupt Huffman. Can only fit %u out of %u codes in %lu-bit len",
+ maxCodes, nCodes, codeLen);
+ }
+
+ // There are nCodes leafs on this level, and those can not be branches
+ maxCodes -= nCodes;
+ // On the next level, rest can be branches, and can have two child Nodes
+ maxCodes *= 2;
+ }
+
+ return count;
+ }
+
+ void setCodeValues(const Buffer& data) {
+ // spec says max 16 but Hasselblad ignores that -> allow 17
+ // Canon's old CRW really ignores this ...
+ assert(data.getSize() <= 162);
+ assert(data.getSize() == maxCodesCount());
+
+ codeValues.clear();
+ codeValues.reserve(maxCodesCount());
+ std::copy(data.begin(), data.end(), std::back_inserter(codeValues));
+ assert(codeValues.size() == maxCodesCount());
+
+ for (const auto cValue : codeValues) {
+ if (cValue > 16)
+ ThrowRDE("Corrupt Huffman. Code value %u is bigger than 16", cValue);
+ }
+ }
+
+ // WARNING: the caller should check that len != 0 before calling the function
+ inline static int __attribute__((const))
+ signExtended(uint32 diff, uint32 len) {
+ int32 ret = diff;
+#if 0
+#define _X(x) (1 << x) - 1
+ constexpr static int offset[16] = {
+ 0, _X(1), _X(2), _X(3), _X(4), _X(5), _X(6), _X(7),
+ _X(8), _X(9), _X(10), _X(11), _X(12), _X(13), _X(14), _X(15)};
+#undef _X
+ if ((diff & (1 << (len - 1))) == 0)
+ ret -= offset[len];
+#else
+ if ((diff & (1 << (len - 1))) == 0)
+ ret -= (1 << len) - 1;
+#endif
+ return ret;
+ }
+};
+
+inline bool operator==(const AbstractHuffmanTable::CodeSymbol& lhs,
+ const AbstractHuffmanTable::CodeSymbol& rhs) {
+ return lhs.code == rhs.code && lhs.code_len == rhs.code_len;
+}
+
+} // namespace rawspeed
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/AbstractLJpegDecompressor.cpp b/src/external/rawspeed/src/librawspeed/decompressors/AbstractLJpegDecompressor.cpp
index 442b6c9a7..a56c3056d 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/AbstractLJpegDecompressor.cpp
+++ b/src/external/rawspeed/src/librawspeed/decompressors/AbstractLJpegDecompressor.cpp
@@ -21,15 +21,18 @@
*/
#include "decompressors/AbstractLJpegDecompressor.h"
-#include "common/Common.h" // for uint32, make_unique, uchar8
-#include "common/Point.h" // for iPoint2D
-#include "decoders/RawDecoderException.h" // for ThrowRDE
-#include "decompressors/HuffmanTable.h" // for HuffmanTable
-#include "io/ByteStream.h" // for ByteStream
-#include <array> // for array
-#include <memory> // for unique_ptr, allocator
-#include <utility> // for move
-#include <vector> // for vector
+#include "common/Common.h" // for uint32, uchar8
+#include "common/Point.h" // for iPoint2D
+#include "decoders/RawDecoderException.h" // for ThrowRDE
+#include "decompressors/AbstractHuffmanTable.h" // for AbstractHuffmanTable
+#include "decompressors/HuffmanTable.h" // for HuffmanTable, Huffma...
+#include "io/ByteStream.h" // for ByteStream
+#include "io/Endianness.h" // for Endianness, Endianne...
+#include <array> // for array
+#include <cassert> // for assert
+#include <memory> // for unique_ptr, make_unique
+#include <utility> // for move
+#include <vector> // for vector
namespace rawspeed {
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/AbstractLJpegDecompressor.h b/src/external/rawspeed/src/librawspeed/decompressors/AbstractLJpegDecompressor.h
index 74a7941af..53a6d8d46 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/AbstractLJpegDecompressor.h
+++ b/src/external/rawspeed/src/librawspeed/decompressors/AbstractLJpegDecompressor.h
@@ -26,13 +26,10 @@
#include "decoders/RawDecoderException.h" // for ThrowRDE
#include "decompressors/AbstractDecompressor.h" // for AbstractDecompressor
#include "decompressors/HuffmanTable.h" // for HuffmanTable
-#include "io/Buffer.h" // for Buffer, Buffer::size_type
#include "io/ByteStream.h" // for ByteStream
-#include "io/Endianness.h" // for getHostEndianness, Endiannes...
-#include <array> // for array
-#include <memory> // for unique_ptr
-#include <utility> // for move
-#include <vector> // for vector
+#include <array> // for array
+#include <memory> // for unique_ptr
+#include <vector> // for vector
/*
* The following enum and two structs are stolen from the IJG JPEG library
@@ -118,20 +115,20 @@ struct JpegComponentInfo {
* These values are fixed over the whole image.
* They are read from the SOF marker.
*/
- uint32 componentId = -1; /* identifier for this component (0..255) */
+ uint32 componentId = ~0U; /* identifier for this component (0..255) */
/*
* Huffman table selector (0..3). The value may vary
* between scans. It is read from the SOS marker.
*/
- uint32 dcTblNo = -1;
- uint32 superH = -1; // Horizontal Supersampling
- uint32 superV = -1; // Vertical Supersampling
+ uint32 dcTblNo = ~0U;
+ uint32 superH = ~0U; // Horizontal Supersampling
+ uint32 superV = ~0U; // Vertical Supersampling
};
class SOFInfo {
public:
- JpegComponentInfo compInfo[4];
+ std::array<JpegComponentInfo, 4> compInfo;
uint32 w = 0; // Width
uint32 h = 0; // Height
uint32 cps = 0; // Components
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/AbstractParallelizedDecompressor.h b/src/external/rawspeed/src/librawspeed/decompressors/AbstractParallelizedDecompressor.h
index 36fbdffd8..d9dbd4d9e 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/AbstractParallelizedDecompressor.h
+++ b/src/external/rawspeed/src/librawspeed/decompressors/AbstractParallelizedDecompressor.h
@@ -73,7 +73,7 @@ public:
return nullptr;
}
- uint32 taskNo = -1;
+ uint32 taskNo = ~0U;
const uint32 tasksTotal;
uint32 start = 0;
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/BinaryHuffmanTree.h b/src/external/rawspeed/src/librawspeed/decompressors/BinaryHuffmanTree.h
new file mode 100644
index 000000000..3660e1247
--- /dev/null
+++ b/src/external/rawspeed/src/librawspeed/decompressors/BinaryHuffmanTree.h
@@ -0,0 +1,237 @@
+/*
+ RawSpeed - RAW file decoder.
+
+ Copyright (C) 2018 Roman Lebedev
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#pragma once
+
+#include <cassert> // for assert
+#include <initializer_list> // IWYU pragma: keep
+#include <memory> // for unique_ptr
+#include <vector> // for vector
+
+namespace rawspeed {
+
+template <typename T>
+class BinaryHuffmanTree final /* : public BinarySearchTree */ {
+public:
+ struct Branch;
+ struct Leaf;
+
+ struct Node {
+ enum class Type { Branch, Leaf };
+
+ explicit virtual operator Type() const = 0;
+
+ Branch& getAsBranch() {
+ assert(Node::Type::Branch == static_cast<Node::Type>(*this));
+ return static_cast<Branch&>(*this);
+ }
+
+ Leaf& getAsLeaf() {
+ assert(Node::Type::Leaf == static_cast<Node::Type>(*this));
+ return static_cast<Leaf&>(*this);
+ }
+
+ virtual ~Node() = default;
+ };
+
+ struct Branch final : public Node {
+ explicit operator typename Node::Type() const override {
+ return Node::Type::Branch;
+ }
+
+ std::unique_ptr<Node> zero;
+ std::unique_ptr<Node> one;
+
+ template <typename Lambda> bool forEachNode(Lambda l) const;
+ template <typename Lambda> bool forEachNode(Lambda l);
+
+ bool hasLeafs() const;
+
+ static bool pruneLeaflessBranches(std::unique_ptr<Node>* n);
+ };
+
+ struct Leaf final : public Node {
+ explicit operator typename Node::Type() const override {
+ return Node::Type::Leaf;
+ }
+
+ T value;
+
+ Leaf() = default;
+
+ explicit Leaf(T value_) : value(value_) {}
+ };
+
+ std::unique_ptr<Node> root;
+
+ std::vector<Branch*> getAllBranchesOfDepth(int depth);
+ std::vector<std::unique_ptr<Node>*> getAllVacantNodesAtDepth(int depth);
+ void pruneLeaflessBranches();
+};
+
+template <typename T>
+template <typename Lambda>
+bool BinaryHuffmanTree<T>::Branch::forEachNode(Lambda l) const {
+ bool done = false;
+ // NOTE: The order *IS* important! Left to right, zero to one!
+ for (const auto* node : {&zero, &one}) {
+ done = l(node);
+ if (done)
+ return done;
+ }
+ return done;
+}
+
+template <typename T>
+template <typename Lambda>
+bool BinaryHuffmanTree<T>::Branch::forEachNode(Lambda l) {
+ bool done = false;
+ // NOTE: The order *IS* important! Left to right, zero to one!
+ for (auto* node : {&zero, &one}) {
+ done = l(node);
+ if (done)
+ return done;
+ }
+ return done;
+}
+
+template <typename T> bool BinaryHuffmanTree<T>::Branch::hasLeafs() const {
+ return forEachNode([](const std::unique_ptr<Node>* n) {
+ assert(n);
+ if (!(*n)) // If the node is empty, then it certainly does not have leafs
+ return false;
+ return Node::Type::Leaf == static_cast<typename Node::Type>(**n);
+ });
+}
+
+template <typename T>
+bool BinaryHuffmanTree<T>::Branch::pruneLeaflessBranches(
+ std::unique_ptr<Node>* top) {
+ if (!top)
+ return false;
+
+ bool foundLeafs = false; // Any leafs in this branch?
+ (*top)->getAsBranch().forEachNode([&foundLeafs](std::unique_ptr<Node>* n) {
+ assert(n);
+ if (!(*n))
+ return false; // Nothing to do here, node is empty already, keep going.
+ switch (static_cast<typename Node::Type>(**n)) {
+ case Node::Type::Branch:
+ // Recurse. Any leafs in this branch?
+ if (Branch::pruneLeaflessBranches(n))
+ foundLeafs = true;
+ else
+ n->reset(); // Aha, dead branch, prune it!
+ break;
+ case Node::Type::Leaf:
+ foundLeafs = true; // Ok, this is a Leaf, great.
+ break;
+ }
+ return false; // keep going.
+ });
+
+ if (!foundLeafs)
+ top->reset();
+
+ return foundLeafs;
+}
+
+template <typename T>
+std::vector<typename BinaryHuffmanTree<T>::Branch*>
+BinaryHuffmanTree<T>::getAllBranchesOfDepth(int depth) {
+ assert(depth >= 0);
+
+ if (0 == depth) {
+ // The root (depth == 0) is is special, and is *always* a Branch.
+ if (!root)
+ root = std::make_unique<Branch>();
+ return {&root->getAsBranch()};
+ }
+
+ // Recursively get all branches of previous depth
+ auto prevBranches = getAllBranchesOfDepth(depth - 1);
+
+ // Early return in case of no branches on previous depth
+ if (prevBranches.empty())
+ return {};
+
+ // We will have at most twice as much branches as at the previous depth.
+ decltype(prevBranches) branches;
+ branches.reserve(2U * prevBranches.size());
+
+ for (const auto& prevBranch : prevBranches) {
+ assert(prevBranch);
+
+ prevBranch->forEachNode([&branches](std::unique_ptr<Node>* n) {
+ assert(n);
+ // If the Node is vacant, make it a branch.
+ // The user was supposed to create all the required Leafs before.
+ // We shall prune Leaf-less branches at the end
+ if (!(*n))
+ *n = std::make_unique<Branch>();
+ // If this is a branch, add it to the list.
+ if (Node::Type::Branch == static_cast<typename Node::Type>(**n))
+ branches.emplace_back(&((*n)->getAsBranch()));
+ return false; // keep going;
+ });
+ }
+ assert(branches.size() <= 2U * prevBranches.size());
+
+ return branches;
+}
+
+template <typename T>
+std::vector<std::unique_ptr<typename BinaryHuffmanTree<T>::Node>*>
+BinaryHuffmanTree<T>::getAllVacantNodesAtDepth(int depth) {
+ assert(depth > 0);
+
+ // Get all branches of previous depth
+ auto prevBranches = getAllBranchesOfDepth(depth - 1);
+
+ // Early return in case of no branches on previous depth
+ if (prevBranches.empty())
+ return {};
+
+ // We will have at most two nodes per each branch on the previous depth.
+ std::vector<std::unique_ptr<BinaryHuffmanTree<T>::Node>*> nodes;
+ nodes.reserve(2U * prevBranches.size());
+
+ for (const auto& prevBranch : prevBranches) {
+ assert(prevBranch);
+
+ auto& b = prevBranch->getAsBranch();
+
+ b.forEachNode([&nodes](std::unique_ptr<Node>* n) {
+ assert(n);
+ if (!(*n)) // If there is no node already, then record it.
+ nodes.emplace_back(n);
+ return false; // keep going;
+ });
+ }
+ assert(nodes.size() <= 2U * prevBranches.size());
+
+ return nodes;
+}
+
+template <typename T> void BinaryHuffmanTree<T>::pruneLeaflessBranches() {
+ Branch::pruneLeaflessBranches(&root);
+}
+
+} // namespace rawspeed
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/CMakeLists.txt b/src/external/rawspeed/src/librawspeed/decompressors/CMakeLists.txt
index 48b12413a..fa48ebaf8 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/CMakeLists.txt
+++ b/src/external/rawspeed/src/librawspeed/decompressors/CMakeLists.txt
@@ -2,11 +2,13 @@ FILE(GLOB SOURCES
"AbstractDecompressor.h"
"AbstractDngDecompressor.cpp"
"AbstractDngDecompressor.h"
+ "AbstractHuffmanTable.h"
"AbstractLJpegDecompressor.cpp"
"AbstractLJpegDecompressor.h"
"AbstractParallelizedDecompressor.cpp"
"AbstractParallelizedDecompressor.h"
"AbstractSamsungDecompressor.h"
+ "BinaryHuffmanTree.h"
"Cr2Decompressor.cpp"
"Cr2Decompressor.h"
"CrwDecompressor.cpp"
@@ -18,6 +20,10 @@ FILE(GLOB SOURCES
"HasselbladDecompressor.cpp"
"HasselbladDecompressor.h"
"HuffmanTable.h"
+ "HuffmanTableLUT.h"
+ "HuffmanTableLookup.h"
+ "HuffmanTableTree.h"
+ "HuffmanTableVector.h"
"JpegDecompressor.cpp"
"JpegDecompressor.h"
"KodakDecompressor.cpp"
@@ -30,8 +36,12 @@ FILE(GLOB SOURCES
"OlympusDecompressor.h"
"PanasonicDecompressor.cpp"
"PanasonicDecompressor.h"
+ "PanasonicDecompressorV5.cpp"
+ "PanasonicDecompressorV5.h"
"PentaxDecompressor.cpp"
"PentaxDecompressor.h"
+ "PhaseOneDecompressor.cpp"
+ "PhaseOneDecompressor.h"
"SamsungV0Decompressor.cpp"
"SamsungV0Decompressor.h"
"SamsungV1Decompressor.cpp"
@@ -44,6 +54,8 @@ FILE(GLOB SOURCES
"SonyArw2Decompressor.h"
"UncompressedDecompressor.cpp"
"UncompressedDecompressor.h"
+ "VC5Decompressor.cpp"
+ "VC5Decompressor.h"
)
target_sources(rawspeed PRIVATE
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/Cr2Decompressor.cpp b/src/external/rawspeed/src/librawspeed/decompressors/Cr2Decompressor.cpp
index e43a0ed54..bce287cfb 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/Cr2Decompressor.cpp
+++ b/src/external/rawspeed/src/librawspeed/decompressors/Cr2Decompressor.cpp
@@ -21,19 +21,21 @@
*/
#include "decompressors/Cr2Decompressor.h"
-#include "common/Common.h" // for uint32, unroll_loop, ushort16
-#include "common/Point.h" // for iPoint2D
+#include "common/Common.h" // for unroll_loop, uint32, ushort16
+#include "common/Point.h" // for iPoint2D, iPoint2D::area_type
#include "common/RawImage.h" // for RawImage, RawImageData
#include "decoders/RawDecoderException.h" // for ThrowRDE
-#include "io/BitPumpJPEG.h" // for BitPumpJPEG
-#include <algorithm> // for move, copy_n
+#include "io/BitPumpJPEG.h" // for BitPumpJPEG, BitStream<>::...
+#include <algorithm> // for copy_n
#include <cassert> // for assert
-#include <numeric> // for accumulate
+#include <initializer_list> // for initializer_list
using std::copy_n;
namespace rawspeed {
+class ByteStream;
+
Cr2Decompressor::Cr2Decompressor(const ByteStream& bs, const RawImage& img)
: AbstractLJpegDecompressor(bs, img) {
if (mRaw->getDataType() != TYPE_USHORT16)
@@ -206,6 +208,9 @@ void Cr2Decompressor::decodeN_X_Y()
if (X_S_F == 1) {
if (destX + sliceWidth > static_cast<unsigned>(mRaw->dim.x))
ThrowRDE("Bad slice width / frame size / image size combination.");
+ if (((sliceId + 1) == slicing.numSlices) &&
+ ((destX + sliceWidth) < static_cast<unsigned>(mRaw->dim.x)))
+ ThrowRDE("Unsufficient slices - do not fill the entire image");
} else {
// FIXME.
}
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/Cr2Decompressor.h b/src/external/rawspeed/src/librawspeed/decompressors/Cr2Decompressor.h
index 4607f3ed8..9165212c6 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/Cr2Decompressor.h
+++ b/src/external/rawspeed/src/librawspeed/decompressors/Cr2Decompressor.h
@@ -21,18 +21,15 @@
#pragma once
-#include "common/Common.h" // ushort16
+#include "common/Common.h" // for ushort16
#include "decoders/RawDecoderException.h" // for ThrowRDE
#include "decompressors/AbstractLJpegDecompressor.h" // for AbstractLJpegDe...
-#include "io/Buffer.h" // for Buffer, Buffer:...
-#include "io/ByteStream.h" // for ByteStream
#include <cassert> // for assert
namespace rawspeed {
+class ByteStream;
class RawImage;
-class Cr2Decompressor;
-// Decompresses Lossless JPEGs, with 2-4 components and optional X/Y subsampling
class Cr2Slicing {
int numSlices = 0;
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/CrwDecompressor.cpp b/src/external/rawspeed/src/librawspeed/decompressors/CrwDecompressor.cpp
index ce9ccd874..6457568cb 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/CrwDecompressor.cpp
+++ b/src/external/rawspeed/src/librawspeed/decompressors/CrwDecompressor.cpp
@@ -21,17 +21,16 @@
*/
#include "decompressors/CrwDecompressor.h"
-#include "common/Common.h" // for uint32, ushort16, uchar8
+#include "common/Common.h" // for uint32, uchar8, ushort16
#include "common/Point.h" // for iPoint2D
#include "common/RawImage.h" // for RawImage, RawImageData
-#include "decoders/RawDecoderException.h" // for RawDecoderException (ptr o...
+#include "decoders/RawDecoderException.h" // for ThrowRDE
#include "decompressors/HuffmanTable.h" // for HuffmanTable
#include "io/BitPumpJPEG.h" // for BitPumpJPEG, BitStream<>::...
#include "io/Buffer.h" // for Buffer
#include "io/ByteStream.h" // for ByteStream
-#include <algorithm> // for min
-#include <array> // for array
-#include <memory> // for make_unique
+#include <array> // for array, array<>::value_type
+#include <cassert> // for assert
using std::array;
@@ -85,32 +84,32 @@ CrwDecompressor::crw_hts CrwDecompressor::initHuffTables(uint32 table) {
ThrowRDE("Wrong table number: %u", table);
// NCodesPerLength
- static const uchar8 first_tree_ncpl[3][16] = {
+ static const std::array<std::array<uchar8, 16>, 3> first_tree_ncpl = {{
{0, 1, 4, 2, 3, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 2, 2, 3, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 6, 3, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- };
+ }};
- static const uchar8 first_tree_len[3][13] = {
+ static const std::array<std::array<uchar8, 13>, 3> first_tree_len = {{
{0x4, 0x3, 0x5, 0x6, 0x2, 0x7, 0x1, 0x8, 0x9, 0x0, 0xa, 0xb, 0xf},
{0x3, 0x2, 0x4, 0x1, 0x5, 0x0, 0x6, 0x7, 0x9, 0x8, 0xa, 0xb, 0xf},
{0x6, 0x5, 0x7, 0x4, 0x8, 0x3, 0x9, 0x2, 0x0, 0xa, 0x1, 0xb, 0xf},
- };
+ }};
- static const uchar8 first_tree_index[3][13] = {
+ static const std::array<std::array<uchar8, 13>, 3> first_tree_index = {{
{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf},
{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf},
{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf},
- };
+ }};
// NCodesPerLength
- static const uchar8 second_tree_ncpl[3][16] = {
+ static const std::array<std::array<uchar8, 16>, 3> second_tree_ncpl = {{
{0, 2, 2, 2, 1, 4, 2, 1, 2, 5, 1, 1, 0, 0, 0, 139},
{0, 2, 2, 1, 4, 1, 4, 1, 3, 3, 1, 0, 0, 0, 0, 140},
{0, 0, 6, 2, 1, 3, 3, 2, 5, 1, 2, 2, 8, 10, 0, 117},
- };
+ }};
- static const uchar8 second_tree_len[3][164] = {
+ static const std::array<std::array<uchar8, 164>, 3> second_tree_len = {{
{0x3, 0x4, 0x2, 0x5, 0x1, 0x6, 0x7, 0x8, 0x2, 0x3, 0x1, 0x4, 0x9, 0x5,
0x2, 0x0, 0x1, 0x6, 0xa, 0x0, 0x3, 0x7, 0x4, 0x1, 0x2, 0x8, 0x9, 0x3,
0x5, 0x1, 0x4, 0x2, 0x5, 0x1, 0x6, 0x7, 0x8, 0x9, 0x9, 0x6, 0xa, 0x9,
@@ -147,9 +146,9 @@ CrwDecompressor::crw_hts CrwDecompressor::initHuffTables(uint32 table) {
0x5, 0x2, 0x3, 0x5, 0x2, 0x4, 0x4, 0xa, 0x4, 0x5, 0x3, 0x2, 0x1, 0x5,
0x3, 0xa, 0x4, 0xa, 0x2, 0x1, 0x4, 0x1, 0x3, 0x3, 0xa, 0x3, 0x2, 0x2,
0x1, 0x3, 0x2, 0x1, 0x1, 0x3, 0x2, 0x1, 0xf, 0xf},
- };
+ }};
- static const uchar8 second_tree_index[3][164] = {
+ static const std::array<std::array<uchar8, 164>, 3> second_tree_index = {{
{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x1, 0x1, 0x1, 0x0, 0x1,
0x2, 0x0, 0x2, 0x1, 0x0, 0xf, 0x2, 0x1, 0x2, 0x3, 0x3, 0x1, 0x1, 0x3,
0x2, 0x4, 0x3, 0x4, 0x3, 0x5, 0x3, 0x3, 0x3, 0x2, 0x7, 0x2, 0x1, 0x3,
@@ -186,13 +185,17 @@ CrwDecompressor::crw_hts CrwDecompressor::initHuffTables(uint32 table) {
0x8, 0x6, 0xf, 0xc, 0xb, 0xa, 0x8, 0xb, 0x6, 0xa, 0xb, 0xd, 0x8, 0xe,
0xd, 0xa, 0xc, 0xc, 0xf, 0xb, 0xe, 0xd, 0x8, 0x6, 0xe, 0xc, 0xe, 0x8,
0xf, 0xa, 0xc, 0xa, 0xc, 0xe, 0xa, 0xe, 0xf, 0xf},
- };
+ }};
array<array<HuffmanTable, 2>, 2> mHuff = {{
- {{makeDecoder(first_tree_ncpl[table], first_tree_len[table]),
- makeDecoder(first_tree_ncpl[table], first_tree_index[table])}},
- {{makeDecoder(second_tree_ncpl[table], second_tree_len[table]),
- makeDecoder(second_tree_ncpl[table], second_tree_index[table])}},
+ {{makeDecoder(first_tree_ncpl[table].data(),
+ first_tree_len[table].data()),
+ makeDecoder(first_tree_ncpl[table].data(),
+ first_tree_index[table].data())}},
+ {{makeDecoder(second_tree_ncpl[table].data(),
+ second_tree_len[table].data()),
+ makeDecoder(second_tree_ncpl[table].data(),
+ second_tree_index[table].data())}},
}};
return mHuff;
@@ -224,6 +227,7 @@ inline void CrwDecompressor::decodeBlock(std::array<int, 64>* diffBuf,
continue;
int diff = lPump->getBits(len);
+ iPump->fill(len);
iPump->skipBits(len);
if (i >= 64)
@@ -255,7 +259,7 @@ void CrwDecompressor::decompress() {
BitPumpJPEG iPump(rawInput);
int carry = 0;
- int base[2];
+ std::array<int, 2> base;
uint32 j = 0;
ushort16* dest = nullptr;
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/CrwDecompressor.h b/src/external/rawspeed/src/librawspeed/decompressors/CrwDecompressor.h
index f67aca04e..2f10ff9e7 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/CrwDecompressor.h
+++ b/src/external/rawspeed/src/librawspeed/decompressors/CrwDecompressor.h
@@ -22,15 +22,13 @@
#pragma once
-#include "common/Common.h" // for uint32, uchar8
+#include "common/Common.h" // for uchar8, uint32
#include "common/RawImage.h" // for RawImage
#include "decompressors/AbstractDecompressor.h" // for AbstractDecompressor
#include "decompressors/HuffmanTable.h" // for HuffmanTable
#include "io/BitPumpJPEG.h" // for BitPumpJPEG
-#include "io/Buffer.h" // for Buffer
#include "io/ByteStream.h" // for ByteStream
#include <array> // for array
-#include <memory> // for unique_ptr
namespace rawspeed {
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/DeflateDecompressor.cpp b/src/external/rawspeed/src/librawspeed/decompressors/DeflateDecompressor.cpp
index 9553bd9f8..a996c856b 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/DeflateDecompressor.cpp
+++ b/src/external/rawspeed/src/librawspeed/decompressors/DeflateDecompressor.cpp
@@ -24,7 +24,6 @@
#include "decompressors/DeflateDecompressor.h"
#include "common/Common.h" // for uint32, ushort16
-#include "common/Point.h" // for iPoint2D
#include "decoders/RawDecoderException.h" // for ThrowRDE
#include "io/Endianness.h" // for getHostEndianness, Endiann...
#include <cassert> // for assert
@@ -40,7 +39,10 @@ static inline void decodeFPDeltaRow(unsigned char* src, unsigned char* dst,
unsigned int bytesps, int factor) {
// DecodeDeltaBytes
for (size_t col = factor; col < realTileWidth * bytesps; ++col) {
- src[col] += src[col - factor];
+ // Yes, this is correct, and is symmetrical with EncodeDeltaBytes in
+ // hdrmerge, and they both combined are lossless.
+ // This is indeed working in modulo-2^n arighmetics.
+ src[col] = static_cast<unsigned char>(src[col] + src[col - factor]);
}
// Reorder bytes into the image
// 16 and 32-bit versions depend on local architecture, 24-bit does not
@@ -184,13 +186,15 @@ static inline void expandFP24(unsigned char* dst, int width) {
}
}
-void DeflateDecompressor::decode(std::unique_ptr<unsigned char[]>* uBuffer,
- int tileWidthMax, int tileHeightMax, int width,
- int height, uint32 offX, uint32 offY) {
+void DeflateDecompressor::decode(
+ std::unique_ptr<unsigned char[]>* uBuffer, // NOLINT
+ int tileWidthMax, int tileHeightMax, int width, int height, uint32 offX,
+ uint32 offY) {
uLongf dstLen = sizeof(float) * tileWidthMax * tileHeightMax;
if (!uBuffer->get())
- *uBuffer = std::unique_ptr<unsigned char[]>(new unsigned char[dstLen]);
+ *uBuffer =
+ std::unique_ptr<unsigned char[]>(new unsigned char[dstLen]); // NOLINT
const auto cSize = input.getRemainSize();
const unsigned char* cBuffer = input.getData(cSize);
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/DeflateDecompressor.h b/src/external/rawspeed/src/librawspeed/decompressors/DeflateDecompressor.h
index 514110c3b..b2cc1a3d7 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/DeflateDecompressor.h
+++ b/src/external/rawspeed/src/librawspeed/decompressors/DeflateDecompressor.h
@@ -20,14 +20,13 @@
#pragma once
-#include "rawspeedconfig.h"
+#include "rawspeedconfig.h" // for HAVE_ZLIB
#ifdef HAVE_ZLIB
-#include "common/Common.h" // for getHostEndianness, uint32, Endianness::big
-#include "common/RawImage.h" // for RawImage
+#include "common/Common.h" // for uint32
+#include "common/RawImage.h" // for RawImage
#include "decompressors/AbstractDecompressor.h" // for AbstractDecompressor
-#include "io/Buffer.h" // for Buffer, Buffer::size_type
#include "io/ByteStream.h" // for ByteStream
#include <memory> // for unique_ptr
#include <utility> // for move
@@ -45,9 +44,9 @@ public:
int bps_)
: input(std::move(bs)), mRaw(img), predictor(predictor_), bps(bps_) {}
- void decode(std::unique_ptr<unsigned char[]>* uBuffer, int tileWidthMax,
- int tileHeightMax, int width, int height, uint32 offX,
- uint32 offY);
+ void decode(std::unique_ptr<unsigned char[]>* uBuffer, // NOLINT
+ int tileWidthMax, int tileHeightMax, int width, int height,
+ uint32 offX, uint32 offY);
};
} // namespace rawspeed
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/FujiDecompressor.cpp b/src/external/rawspeed/src/librawspeed/decompressors/FujiDecompressor.cpp
index 44459419a..1b1162047 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/FujiDecompressor.cpp
+++ b/src/external/rawspeed/src/librawspeed/decompressors/FujiDecompressor.cpp
@@ -22,16 +22,17 @@
*/
#include "decompressors/FujiDecompressor.h"
-#include "common/Common.h" // for roundUpDiv...
+#include "common/Common.h" // for ushort16
+#include "common/Point.h" // for iPoint2D
#include "common/RawImage.h" // for RawImage
#include "decoders/RawDecoderException.h" // for ThrowRDE
#include "decompressors/AbstractParallelizedDecompressor.h" // for RawDecom...
#include "io/Endianness.h" // for Endianness
-#include "metadata/ColorFilterArray.h" // for CFAColor...
+#include "metadata/ColorFilterArray.h" // for CFA_BLUE
#include <algorithm> // for fill, min
-#include <cstdlib> // for abs
+#include <cmath> // for abs
+#include <cstdlib> // for abs, size_t
#include <cstring> // for memcpy
-// IWYU pragma: no_include <bits/std_abs.h>
namespace rawspeed {
@@ -172,9 +173,9 @@ template <typename T>
void FujiDecompressor::copy_line(fuji_compressed_block* info,
const FujiStrip& strip, int cur_line,
T&& idx) const {
- ushort16* lineBufB[3];
- ushort16* lineBufG[6];
- ushort16* lineBufR[3];
+ std::array<ushort16*, 3> lineBufB;
+ std::array<ushort16*, 6> lineBufG;
+ std::array<ushort16*, 3> lineBufR;
for (int i = 0; i < 3; i++) {
lineBufR[i] = info->linebuf[_R2 + i] + 1;
@@ -233,7 +234,8 @@ void FujiDecompressor::copy_line_to_bayer(fuji_compressed_block* info,
copy_line(info, strip, cur_line, index);
}
-void FujiDecompressor::fuji_zerobits(BitPumpMSB* pump, int* count) const {
+inline void FujiDecompressor::fuji_zerobits(BitPumpMSB* pump,
+ int* count) const {
uchar8 zero = 0;
*count = 0;
@@ -265,12 +267,10 @@ FujiDecompressor::bitDiff(int value1, int value2) const {
}
template <typename T1, typename T2>
-int FujiDecompressor::fuji_decode_sample(T1&& func_0, T2&& func_1,
- fuji_compressed_block* info,
- BitPumpMSB* pump, ushort16* line_buf,
- int* pos, int_pair* grads) const {
+void FujiDecompressor::fuji_decode_sample(
+ T1&& func_0, T2&& func_1, fuji_compressed_block* info, BitPumpMSB* pump,
+ ushort16* line_buf, int* pos, std::array<int_pair, 41>* grads) const {
int interp_val = 0;
- int errcnt = 0;
int sample = 0;
int code = 0;
@@ -284,7 +284,7 @@ int FujiDecompressor::fuji_decode_sample(T1&& func_0, T2&& func_1,
fuji_zerobits(pump, &sample);
if (sample < common_info.max_bits - common_info.raw_bits - 1) {
- int decBits = bitDiff(grads[gradient].value1, grads[gradient].value2);
+ int decBits = bitDiff((*grads)[gradient].value1, (*grads)[gradient].value2);
code = pump->getBits(decBits);
code += sample << decBits;
} else {
@@ -293,7 +293,7 @@ int FujiDecompressor::fuji_decode_sample(T1&& func_0, T2&& func_1,
}
if (code < 0 || code >= common_info.total_values) {
- errcnt++;
+ ThrowRDE("fuji_decode_sample");
}
if (code & 1) {
@@ -302,14 +302,14 @@ int FujiDecompressor::fuji_decode_sample(T1&& func_0, T2&& func_1,
code /= 2;
}
- grads[gradient].value1 += std::abs(code);
+ (*grads)[gradient].value1 += std::abs(code);
- if (grads[gradient].value2 == common_info.min_value) {
- grads[gradient].value1 >>= 1;
- grads[gradient].value2 >>= 1;
+ if ((*grads)[gradient].value2 == common_info.min_value) {
+ (*grads)[gradient].value1 >>= 1;
+ (*grads)[gradient].value2 >>= 1;
}
- grads[gradient].value2++;
+ (*grads)[gradient].value2++;
interp_val = func_1(grad, interp_val, code);
@@ -326,19 +326,16 @@ int FujiDecompressor::fuji_decode_sample(T1&& func_0, T2&& func_1,
}
*pos += 2;
-
- return errcnt;
}
#define fuji_quant_gradient(v1, v2) \
(9 * ci.q_table[ci.q_point[4] + (v1)] + ci.q_table[ci.q_point[4] + (v2)])
-int FujiDecompressor::fuji_decode_sample_even(fuji_compressed_block* info,
- BitPumpMSB* pump,
- ushort16* line_buf, int* pos,
- int_pair* grads) const {
+void FujiDecompressor::fuji_decode_sample_even(
+ fuji_compressed_block* info, BitPumpMSB* pump, ushort16* line_buf, int* pos,
+ std::array<int_pair, 41>* grads) const {
const auto& ci = common_info;
- return fuji_decode_sample(
+ fuji_decode_sample(
[&ci](const ushort16* line_buf_cur, int* interp_val, int* grad,
int* gradient) {
int Rb = line_buf_cur[-2 - ci.line_width];
@@ -376,12 +373,11 @@ int FujiDecompressor::fuji_decode_sample_even(fuji_compressed_block* info,
info, pump, line_buf, pos, grads);
}
-int FujiDecompressor::fuji_decode_sample_odd(fuji_compressed_block* info,
- BitPumpMSB* pump,
- ushort16* line_buf, int* pos,
- int_pair* grads) const {
+void FujiDecompressor::fuji_decode_sample_odd(
+ fuji_compressed_block* info, BitPumpMSB* pump, ushort16* line_buf, int* pos,
+ std::array<int_pair, 41>* grads) const {
const auto& ci = common_info;
- return fuji_decode_sample(
+ fuji_decode_sample(
[&ci](const ushort16* line_buf_cur, int* interp_val, int* grad,
int* gradient) {
int Ra = line_buf_cur[-1];
@@ -436,26 +432,26 @@ void FujiDecompressor::fuji_decode_interpolation_even(int line_width,
*pos += 2;
}
-void FujiDecompressor::fuji_extend_generic(ushort16* linebuf[_ltotal],
- int line_width, int start,
- int end) const {
+void FujiDecompressor::fuji_extend_generic(
+ std::array<ushort16*, _ltotal> linebuf, int line_width, int start,
+ int end) const {
for (int i = start; i <= end; i++) {
linebuf[i][0] = linebuf[i - 1][1];
linebuf[i][line_width + 1] = linebuf[i - 1][line_width];
}
}
-void FujiDecompressor::fuji_extend_red(ushort16* linebuf[_ltotal],
+void FujiDecompressor::fuji_extend_red(std::array<ushort16*, _ltotal> linebuf,
int line_width) const {
fuji_extend_generic(linebuf, line_width, _R2, _R4);
}
-void FujiDecompressor::fuji_extend_green(ushort16* linebuf[_ltotal],
+void FujiDecompressor::fuji_extend_green(std::array<ushort16*, _ltotal> linebuf,
int line_width) const {
fuji_extend_generic(linebuf, line_width, _G2, _G7);
}
-void FujiDecompressor::fuji_extend_blue(ushort16* linebuf[_ltotal],
+void FujiDecompressor::fuji_extend_blue(std::array<ushort16*, _ltotal> linebuf,
int line_width) const {
fuji_extend_generic(linebuf, line_width, _B2, _B4);
}
@@ -477,8 +473,6 @@ void FujiDecompressor::xtrans_decode_block(fuji_compressed_block* info,
ColorPos g;
ColorPos b;
- int errcnt = 0;
-
const int line_width = common_info.line_width;
// FIXME: GCC5 sucks.
@@ -492,10 +486,10 @@ void FujiDecompressor::xtrans_decode_block(fuji_compressed_block* info,
even_func(c0, c1, grad, c0_pos, c1_pos);
if (g.even > 8) {
- errcnt += fuji_decode_sample_odd(info, pump, info->linebuf[c0] + 1,
- &c0_pos.odd, info->grad_odd[grad]);
- errcnt += fuji_decode_sample_odd(info, pump, info->linebuf[c1] + 1,
- &c1_pos.odd, info->grad_odd[grad]);
+ fuji_decode_sample_odd(info, pump, info->linebuf[c0] + 1, &c0_pos.odd,
+ &(info->grad_odd[grad]));
+ fuji_decode_sample_odd(info, pump, info->linebuf[c1] + 1, &c1_pos.odd,
+ &(info->grad_odd[grad]));
}
}
};
@@ -505,8 +499,8 @@ void FujiDecompressor::xtrans_decode_block(fuji_compressed_block* info,
ColorPos& c1_pos) {
fuji_decode_interpolation_even(line_width, info->linebuf[c0] + 1,
&c0_pos.even);
- errcnt += fuji_decode_sample_even(info, pump, info->linebuf[c1] + 1,
- &c1_pos.even, info->grad_even[grad]);
+ fuji_decode_sample_even(info, pump, info->linebuf[c1] + 1, &c1_pos.even,
+ &(info->grad_even[grad]));
},
_R2, _G2, 0, r, g);
@@ -518,8 +512,8 @@ void FujiDecompressor::xtrans_decode_block(fuji_compressed_block* info,
pass(
[&](_xt_lines c0, _xt_lines c1, int grad, ColorPos& c0_pos,
ColorPos& c1_pos) {
- errcnt += fuji_decode_sample_even(info, pump, info->linebuf[c0] + 1,
- &c0_pos.even, info->grad_even[grad]);
+ fuji_decode_sample_even(info, pump, info->linebuf[c0] + 1, &c0_pos.even,
+ &(info->grad_even[grad]));
fuji_decode_interpolation_even(line_width, info->linebuf[c1] + 1,
&c1_pos.even);
},
@@ -535,9 +529,8 @@ void FujiDecompressor::xtrans_decode_block(fuji_compressed_block* info,
[&](_xt_lines c0, _xt_lines c1, int grad, ColorPos& c0_pos,
ColorPos& c1_pos) {
if (c0_pos.even & 3) {
- errcnt +=
- fuji_decode_sample_even(info, pump, info->linebuf[c0] + 1,
- &c0_pos.even, info->grad_even[grad]);
+ fuji_decode_sample_even(info, pump, info->linebuf[c0] + 1,
+ &c0_pos.even, &(info->grad_even[grad]));
} else {
fuji_decode_interpolation_even(line_width, info->linebuf[c0] + 1,
&c0_pos.even);
@@ -557,16 +550,15 @@ void FujiDecompressor::xtrans_decode_block(fuji_compressed_block* info,
pass(
[&](_xt_lines c0, _xt_lines c1, int grad, ColorPos& c0_pos,
ColorPos& c1_pos) {
- errcnt += fuji_decode_sample_even(info, pump, info->linebuf[c0] + 1,
- &c0_pos.even, info->grad_even[grad]);
+ fuji_decode_sample_even(info, pump, info->linebuf[c0] + 1, &c0_pos.even,
+ &(info->grad_even[grad]));
if ((c1_pos.even & 3) == 2) {
fuji_decode_interpolation_even(line_width, info->linebuf[c1] + 1,
&c1_pos.even);
} else {
- errcnt +=
- fuji_decode_sample_even(info, pump, info->linebuf[c1] + 1,
- &c1_pos.even, info->grad_even[grad]);
+ fuji_decode_sample_even(info, pump, info->linebuf[c1] + 1,
+ &c1_pos.even, &(info->grad_even[grad]));
}
},
_G5, _B3, 0, g, b);
@@ -584,13 +576,12 @@ void FujiDecompressor::xtrans_decode_block(fuji_compressed_block* info,
fuji_decode_interpolation_even(line_width, info->linebuf[c0] + 1,
&c0_pos.even);
} else {
- errcnt +=
- fuji_decode_sample_even(info, pump, info->linebuf[c0] + 1,
- &c0_pos.even, info->grad_even[grad]);
+ fuji_decode_sample_even(info, pump, info->linebuf[c0] + 1,
+ &c0_pos.even, &(info->grad_even[grad]));
}
- errcnt += fuji_decode_sample_even(info, pump, info->linebuf[c1] + 1,
- &c1_pos.even, info->grad_even[grad]);
+ fuji_decode_sample_even(info, pump, info->linebuf[c1] + 1, &c1_pos.even,
+ &(info->grad_even[grad]));
},
_R4, _G6, 1, r, g);
@@ -607,9 +598,8 @@ void FujiDecompressor::xtrans_decode_block(fuji_compressed_block* info,
&c0_pos.even);
if (c1_pos.even & 3) {
- errcnt +=
- fuji_decode_sample_even(info, pump, info->linebuf[c1] + 1,
- &c1_pos.even, info->grad_even[grad]);
+ fuji_decode_sample_even(info, pump, info->linebuf[c1] + 1,
+ &c1_pos.even, &(info->grad_even[grad]));
} else {
fuji_decode_interpolation_even(line_width, info->linebuf[c1] + 1,
&c1_pos.even);
@@ -619,9 +609,6 @@ void FujiDecompressor::xtrans_decode_block(fuji_compressed_block* info,
fuji_extend_green(info->linebuf, line_width);
fuji_extend_blue(info->linebuf, line_width);
-
- if (errcnt)
- ThrowRDE("xtrans_decode_block");
}
void FujiDecompressor::fuji_bayer_decode_block(fuji_compressed_block* info,
@@ -641,25 +628,23 @@ void FujiDecompressor::fuji_bayer_decode_block(fuji_compressed_block* info,
ColorPos g;
ColorPos b;
- int errcnt = 0;
-
const int line_width = common_info.line_width;
auto pass = [&](_xt_lines c0, _xt_lines c1, int grad, ColorPos& c0_pos,
ColorPos& c1_pos) {
while (g.even < line_width || g.odd < line_width) {
if (g.even < line_width) {
- errcnt += fuji_decode_sample_even(info, pump, info->linebuf[c0] + 1,
- &c0_pos.even, info->grad_even[grad]);
- errcnt += fuji_decode_sample_even(info, pump, info->linebuf[c1] + 1,
- &c1_pos.even, info->grad_even[grad]);
+ fuji_decode_sample_even(info, pump, info->linebuf[c0] + 1, &c0_pos.even,
+ &(info->grad_even[grad]));
+ fuji_decode_sample_even(info, pump, info->linebuf[c1] + 1, &c1_pos.even,
+ &(info->grad_even[grad]));
}
if (g.even > 8) {
- errcnt += fuji_decode_sample_odd(info, pump, info->linebuf[c0] + 1,
- &c0_pos.odd, info->grad_odd[grad]);
- errcnt += fuji_decode_sample_odd(info, pump, info->linebuf[c1] + 1,
- &c1_pos.odd, info->grad_odd[grad]);
+ fuji_decode_sample_odd(info, pump, info->linebuf[c0] + 1, &c0_pos.odd,
+ &(info->grad_odd[grad]));
+ fuji_decode_sample_odd(info, pump, info->linebuf[c1] + 1, &c1_pos.odd,
+ &(info->grad_odd[grad]));
}
}
};
@@ -703,9 +688,6 @@ void FujiDecompressor::fuji_bayer_decode_block(fuji_compressed_block* info,
b.reset();
pass_GB(_G7, _B4, 2);
-
- if (errcnt)
- ThrowRDE("fuji decode bayer block");
}
void FujiDecompressor::fuji_decode_strip(
@@ -719,9 +701,9 @@ void FujiDecompressor::fuji_decode_strip(
int b;
};
- const i_pair mtable[6] = {{_R0, _R3}, {_R1, _R4}, {_G0, _G6},
- {_G1, _G7}, {_B0, _B3}, {_B1, _B4}};
- const i_pair ztable[3] = {{_R2, 3}, {_G2, 6}, {_B2, 3}};
+ const std::array<i_pair, 6> mtable = {
+ {{_R0, _R3}, {_R1, _R4}, {_G0, _G6}, {_G1, _G7}, {_B0, _B3}, {_B1, _B4}}};
+ const std::array<i_pair, 3> ztable = {{{_R2, 3}, {_G2, 6}, {_B2, 3}}};
for (int cur_line = 0; cur_line < strip.height(); cur_line++) {
if (header.raw_type == 16) {
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/FujiDecompressor.h b/src/external/rawspeed/src/librawspeed/decompressors/FujiDecompressor.h
index 1955e9036..f4a0d9f27 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/FujiDecompressor.h
+++ b/src/external/rawspeed/src/librawspeed/decompressors/FujiDecompressor.h
@@ -26,9 +26,9 @@
#include "io/BitPumpMSB.h" // for BitPumpMSB
#include "io/ByteStream.h" // for ByteStream
#include "metadata/ColorFilterArray.h" // for CFAColor
-#include <algorithm> // for move
#include <array> // for array
#include <cassert> // for assert
+#include <utility> // for move
#include <vector> // for vector
namespace rawspeed {
@@ -115,7 +115,7 @@ protected:
explicit fuji_compressed_params(const FujiDecompressor& d);
std::vector<char> q_table; /* quantization table */
- int q_point[5]; /* quantization points */
+ std::array<int, 5> q_point; /* quantization points */
int max_bits;
int min_value;
int raw_bits;
@@ -158,10 +158,12 @@ protected:
void reset(const fuji_compressed_params* params);
- int_pair grad_even[3][41]; // tables of gradients
- int_pair grad_odd[3][41];
+ // tables of gradients
+ std::array<std::array<int_pair, 41>, 3> grad_even;
+ std::array<std::array<int_pair, 41>, 3> grad_odd;
+
std::vector<ushort16> linealloc;
- ushort16* linebuf[_ltotal];
+ std::array<ushort16*, _ltotal> linebuf;
};
private:
@@ -183,27 +185,30 @@ private:
void copy_line_to_bayer(fuji_compressed_block* info, const FujiStrip& strip,
int cur_line) const;
- void fuji_zerobits(BitPumpMSB* pump, int* count) const;
+ inline void fuji_zerobits(BitPumpMSB* pump, int* count) const;
int bitDiff(int value1, int value2) const;
template <typename T1, typename T2>
- int fuji_decode_sample(T1&& func_0, T2&& func_1, fuji_compressed_block* info,
- BitPumpMSB* pump, ushort16* line_buf, int* pos,
- int_pair* grads) const;
- int fuji_decode_sample_even(fuji_compressed_block* info, BitPumpMSB* pump,
+ void fuji_decode_sample(T1&& func_0, T2&& func_1, fuji_compressed_block* info,
+ BitPumpMSB* pump, ushort16* line_buf, int* pos,
+ std::array<int_pair, 41>* grads) const;
+ void fuji_decode_sample_even(fuji_compressed_block* info, BitPumpMSB* pump,
+ ushort16* line_buf, int* pos,
+ std::array<int_pair, 41>* grads) const;
+ void fuji_decode_sample_odd(fuji_compressed_block* info, BitPumpMSB* pump,
ushort16* line_buf, int* pos,
- int_pair* grads) const;
- int fuji_decode_sample_odd(fuji_compressed_block* info, BitPumpMSB* pump,
- ushort16* line_buf, int* pos,
- int_pair* grads) const;
+ std::array<int_pair, 41>* grads) const;
void fuji_decode_interpolation_even(int line_width, ushort16* line_buf,
int* pos) const;
- void fuji_extend_generic(ushort16* linebuf[_ltotal], int line_width,
- int start, int end) const;
- void fuji_extend_red(ushort16* linebuf[_ltotal], int line_width) const;
- void fuji_extend_green(ushort16* linebuf[_ltotal], int line_width) const;
- void fuji_extend_blue(ushort16* linebuf[_ltotal], int line_width) const;
+ void fuji_extend_generic(std::array<ushort16*, _ltotal> linebuf,
+ int line_width, int start, int end) const;
+ void fuji_extend_red(std::array<ushort16*, _ltotal> linebuf,
+ int line_width) const;
+ void fuji_extend_green(std::array<ushort16*, _ltotal> linebuf,
+ int line_width) const;
+ void fuji_extend_blue(std::array<ushort16*, _ltotal> linebuf,
+ int line_width) const;
void xtrans_decode_block(fuji_compressed_block* info,
BitPumpMSB* pump, int cur_line) const;
void fuji_bayer_decode_block(fuji_compressed_block* info,
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/HasselbladDecompressor.cpp b/src/external/rawspeed/src/librawspeed/decompressors/HasselbladDecompressor.cpp
index 11a74cf2e..ff0e345cf 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/HasselbladDecompressor.cpp
+++ b/src/external/rawspeed/src/librawspeed/decompressors/HasselbladDecompressor.cpp
@@ -41,7 +41,7 @@ HasselbladDecompressor::HasselbladDecompressor(const ByteStream& bs,
// FIXME: could be wrong. max "active pixels" - "100 MP"
if (mRaw->dim.x == 0 || mRaw->dim.y == 0 || mRaw->dim.x % 2 != 0 ||
- mRaw->dim.x > 11600 || mRaw->dim.y > 8700) {
+ mRaw->dim.x > 12000 || mRaw->dim.y > 8816) {
ThrowRDE("Unexpected image dimensions found: (%u; %u)", mRaw->dim.x,
mRaw->dim.y);
}
@@ -82,8 +82,10 @@ void HasselbladDecompressor::decodeScan() {
int len2 = ht[0]->decodeLength(bitStream);
p1 += getBits(&bitStream, len1);
p2 += getBits(&bitStream, len2);
- dest[x] = p1;
- dest[x+1] = p2;
+ // NOTE: this is rather unusual and weird, but appears to be correct.
+ // clampBits(p, 16) results in completely garbled images.
+ dest[x] = ushort16(p1);
+ dest[x + 1] = ushort16(p2);
}
}
input.skipBytes(bitStream.getBufferPosition());
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/HasselbladDecompressor.h b/src/external/rawspeed/src/librawspeed/decompressors/HasselbladDecompressor.h
index 03535d3cb..47ad90945 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/HasselbladDecompressor.h
+++ b/src/external/rawspeed/src/librawspeed/decompressors/HasselbladDecompressor.h
@@ -23,11 +23,10 @@
#include "decompressors/AbstractLJpegDecompressor.h" // for AbstractLJpegDe...
#include "io/BitPumpMSB32.h" // for BitPumpMSB32
-#include "io/Buffer.h" // for Buffer, Buffer:...
-#include "io/ByteStream.h" // for ByteStream
namespace rawspeed {
+class ByteStream;
class RawImage;
class HasselbladDecompressor final : public AbstractLJpegDecompressor
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/HuffmanTable.h b/src/external/rawspeed/src/librawspeed/decompressors/HuffmanTable.h
index 260df3814..6f54bcac1 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/HuffmanTable.h
+++ b/src/external/rawspeed/src/librawspeed/decompressors/HuffmanTable.h
@@ -1,8 +1,7 @@
/*
RawSpeed - RAW file decoder.
- Copyright (C) 2017 Axel Waggershauser
- Copyright (C) 2017 Roman Lebedev
+ Copyright (C) 2018 Roman Lebedev
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -21,346 +20,20 @@
#pragma once
-#include "common/Common.h" // for ushort16, uchar8, int32
-#include "decoders/RawDecoderException.h" // for ThrowRDE
-#include "io/Buffer.h" // for Buffer
-#include <algorithm> // for copy
-#include <cassert> // for assert
-#include <cstddef> // for size_t
-#include <iterator> // for distance
-#include <numeric> // for accumulate
-#include <vector> // for vector, allocator, operator==
+// IWYU pragma: begin_exports
-/*
-* The following code is inspired by the IJG JPEG library.
-*
-* Copyright (C) 1991, 1992, Thomas G. Lane.
-* Part of the Independent JPEG Group's software.
-* See the file Copyright for more details.
-*
-* Copyright (c) 1993 Brian C. Smith, The Regents of the University
-* of California
-* All rights reserved.
-*
-* Copyright (c) 1994 Kongji Huang and Brian C. Smith.
-* Cornell University
-* All rights reserved.
-*
-* Permission to use, copy, modify, and distribute this software and its
-* documentation for any purpose, without fee, and without written agreement is
-* hereby granted, provided that the above copyright notice and the following
-* two paragraphs appear in all copies of this software.
-*
-* IN NO EVENT SHALL CORNELL UNIVERSITY BE LIABLE TO ANY PARTY FOR
-* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
-* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF CORNELL
-* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*
-* CORNELL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
-* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
-* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
-* ON AN "AS IS" BASIS, AND CORNELL UNIVERSITY HAS NO OBLIGATION TO
-* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
-*/
-
-namespace rawspeed {
-
-class HuffmanTable final {
- // private fields calculated from codesPerBits and codeValues
- // they are index '1' based, so we can directly lookup the value
- // for code length l without decrementing
- std::vector<ushort16> maxCodeOL; // index is length of code
- std::vector<ushort16> codeOffsetOL; // index is length of code
-
- // The code can be compiled with two different decode lookup table layouts.
- // The idea is that different CPU architectures may perform better with
- // one or the other, depending on the relative performance of their arithmetic
- // core vs their memory access. For an Intel Core i7, the big table is better.
-#if 1
- // lookup table containing 3 fields: payload:16|flag:8|len:8
- // The payload may be the fully decoded diff or the length of the diff.
- // The len field contains the number of bits, this lookup consumed.
- // A lookup value of 0 means the code was too big to fit into the table.
- // The optimal LookupDepth is also likely to depend on the CPU architecture.
- static constexpr unsigned PayloadShift = 16;
- static constexpr unsigned FlagMask = 0x100;
- static constexpr unsigned LenMask = 0xff;
- static constexpr unsigned LookupDepth = 11;
- std::vector<int32> decodeLookup;
-#else
- // lookup table containing 2 fields: payload:4|len:4
- // the payload is the length of the diff, len is the length of the code
- static constexpr unsigned LookupDepth = 15;
- static constexpr unsigned PayloadShift = 4;
- static constexpr unsigned FlagMask = 0;
- static constexpr unsigned LenMask = 0x0f;
- std::vector<uchar8> decodeLookup;
-#endif
-
- bool fullDecode = true;
- bool fixDNGBug16 = false;
-
- inline size_t __attribute__((pure)) maxCodePlusDiffLength() const {
- return nCodesPerLength.size() - 1 +
- *(std::max_element(codeValues.cbegin(), codeValues.cend()));
- }
-
- // These two fields directly represent the contents of a JPEG DHT field
-
- // 1. The number of codes there are per bit length, this is index 1 based.
- // (there are always 0 codes of length 0)
- std::vector<unsigned int> nCodesPerLength; // index is length of code
- inline unsigned int __attribute__((pure)) maxCodesCount() const {
- return std::accumulate(nCodesPerLength.begin(), nCodesPerLength.end(), 0U);
- }
-
- // 2. This is the actual huffman encoded data, i.e. the 'alphabet'. Each value
- // is the number of bits following the code that encode the difference to the
- // last pixel. Valid values are in the range 0..16.
- // signExtended() is used to decode the difference bits to a signed int.
- std::vector<uchar8> codeValues; // index is just sequential number
-
-public:
- bool operator==(const HuffmanTable& other) const {
- return nCodesPerLength == other.nCodesPerLength
- && codeValues == other.codeValues;
- }
-
- uint32 setNCodesPerLength(const Buffer& data) {
- assert(data.getSize() == 16);
-
- nCodesPerLength.resize(17, 0);
- std::copy(data.begin(), data.end(), &nCodesPerLength[1]);
- assert(nCodesPerLength[0] == 0);
-
- // trim empty entries from the codes per length table on the right
- while (!nCodesPerLength.empty() && nCodesPerLength.back() == 0)
- nCodesPerLength.pop_back();
-
- if (nCodesPerLength.empty())
- ThrowRDE("Codes-per-length table is empty");
-
- assert(nCodesPerLength.back() > 0);
-
- const auto count = maxCodesCount();
- assert(count > 0);
-
- if (count > 162)
- ThrowRDE("Too big code-values table");
-
- for (auto codeLen = 1U; codeLen < nCodesPerLength.size(); codeLen++) {
- // we have codeLen bits. make sure that that code count can actually fit
- const auto nCodes = nCodesPerLength[codeLen];
- if (nCodes > ((1U << codeLen) - 1U)) {
- ThrowRDE("Corrupt Huffman. Can not have %u codes in %u-bit len", nCodes,
- codeLen);
- }
- }
-
- return count;
- }
-
- void setCodeValues(const Buffer& data) {
- // spec says max 16 but Hasselblad ignores that -> allow 17
- // Canon's old CRW really ignores this ...
- assert(data.getSize() <= 162);
- assert(data.getSize() == maxCodesCount());
-
- codeValues.clear();
- codeValues.reserve(maxCodesCount());
- std::copy(data.begin(), data.end(), std::back_inserter(codeValues));
- assert(codeValues.size() == maxCodesCount());
-
- for (const auto cValue : codeValues) {
- if (cValue > 16)
- ThrowRDE("Corrupt Huffman. Code value %u is bigger than 16", cValue);
- }
- }
-
- void setup(bool fullDecode_, bool fixDNGBug16_) {
- this->fullDecode = fullDecode_;
- this->fixDNGBug16 = fixDNGBug16_;
-
- // store the code lengths in bits, valid values are 0..16
- std::vector<uchar8> code_len; // index is just sequential number
- // store the codes themselves (bit patterns found inside the stream)
- std::vector<ushort16> codes; // index is just sequential number
-
- assert(!nCodesPerLength.empty());
- assert(maxCodesCount() > 0);
+#include "decompressors/HuffmanTableLUT.h" // for HuffmanTableLUT
+// #include "decompressors/HuffmanTableLookup.h" // for HuffmanTableLookup
+// #include "decompressors/HuffmanTableTree.h" // for HuffmanTableTree
+// #include "decompressors/HuffmanTableVector.h" // for HuffmanTableVector
- unsigned int maxCodeLength = nCodesPerLength.size() - 1U;
- assert(codeValues.size() == maxCodesCount());
+// IWYU pragma: end_exports
- assert(maxCodePlusDiffLength() <= 32U);
-
- // reserve all the memory. avoids lots of small allocs
- code_len.reserve(maxCodesCount());
- codes.reserve(maxCodesCount());
-
- // Figure C.1: make table of Huffman code length for each symbol
- // Figure C.2: generate the codes themselves
- uint32 code = 0;
- for (unsigned int l = 1; l <= maxCodeLength; ++l) {
- assert(nCodesPerLength[l] <= ((1U << l) - 1U));
-
- for (unsigned int i = 0; i < nCodesPerLength[l]; ++i) {
- if (code > 0xffff) {
- ThrowRDE("Corrupt Huffman: code value overflow on len = %u, %u-th "
- "code out of %u\n",
- l, i, nCodesPerLength[l]);
- }
-
- code_len.push_back(l);
- codes.push_back(code);
- code++;
- }
- code <<= 1;
- }
-
- assert(code_len.size() == maxCodesCount());
- assert(codes.size() == maxCodesCount());
-
- // Figure F.15: generate decoding tables
- codeOffsetOL.resize(maxCodeLength + 1UL, 0xffff);
- maxCodeOL.resize(maxCodeLength + 1UL);
- int code_index = 0;
- for (unsigned int l = 1U; l <= maxCodeLength; l++) {
- if (nCodesPerLength[l]) {
- codeOffsetOL[l] = codes[code_index] - code_index;
- code_index += nCodesPerLength[l];
- maxCodeOL[l] = codes[code_index - 1];
- }
- }
-
- // Generate lookup table for fast decoding lookup.
- // See definition of decodeLookup above
- decodeLookup.resize(1 << LookupDepth);
- for (size_t i = 0; i < codes.size(); i++) {
- uchar8 code_l = code_len[i];
- if (code_l > static_cast<int>(LookupDepth))
- break;
-
- ushort16 ll = codes[i] << (LookupDepth - code_l);
- ushort16 ul = ll | ((1 << (LookupDepth - code_l)) - 1);
- ushort16 diff_l = codeValues[i];
- for (ushort16 c = ll; c <= ul; c++) {
- if (!(c < decodeLookup.size()))
- ThrowRDE("Corrupt Huffman");
-
- if (!FlagMask || !fullDecode || diff_l + code_l > LookupDepth) {
- // lookup bit depth is too small to fit both the encoded length
- // and the final difference value.
- // -> store only the length and do a normal sign extension later
- decodeLookup[c] = diff_l << PayloadShift | code_l;
- } else {
- // diff_l + code_l <= lookupDepth
- // The table bit depth is large enough to store both.
- decodeLookup[c] = (code_l + diff_l) | FlagMask;
-
- if (diff_l) {
- uint32 diff = (c >> (LookupDepth - code_l - diff_l)) & ((1 << diff_l) - 1);
- decodeLookup[c] |= static_cast<uint32>(signExtended(diff, diff_l))
- << PayloadShift;
- }
- }
- }
- }
- }
-
- // WARNING: the caller should check that len != 0 before calling the function
- inline static int __attribute__((const))
- signExtended(uint32 diff, uint32 len) {
- int32 ret = diff;
-#if 0
-#define _X(x) (1<<x)-1
- constexpr static int offset[16] = {
- 0, _X(1), _X(2), _X(3), _X(4), _X(5), _X(6), _X(7),
- _X(8), _X(9), _X(10), _X(11), _X(12), _X(13), _X(14), _X(15)};
-#undef _X
- if ((diff & (1 << (len - 1))) == 0)
- ret -= offset[len];
-#else
- if ((diff & (1 << (len - 1))) == 0)
- ret -= (1 << len) - 1;
-#endif
- return ret;
- }
-
- template<typename BIT_STREAM> inline int decodeLength(BIT_STREAM& bs) const {
- assert(!fullDecode);
- return decode<BIT_STREAM, false>(bs);
- }
-
- template<typename BIT_STREAM> inline int decodeNext(BIT_STREAM& bs) const {
- assert(fullDecode);
- return decode<BIT_STREAM, true>(bs);
- }
-
- // The bool template paraeter is to enable two versions:
- // one returning only the length of the of diff bits (see Hasselblad),
- // one to return the fully decoded diff.
- // All ifs depending on this bool will be optimized out by the compiler
- template<typename BIT_STREAM, bool FULL_DECODE> inline int decode(BIT_STREAM& bs) const {
- assert(FULL_DECODE == fullDecode);
-
- // 32 is the absolute maximum combined length of code + diff
- // assertion maxCodePlusDiffLength() <= 32U is already checked in setup()
- bs.fill(32);
-
- // for processors supporting bmi2 instructions, using maxCodePlusDiffLength()
- // might be benifitial
-
- uint32 code = bs.peekBitsNoFill(LookupDepth);
- assert(code < decodeLookup.size());
- int val = decodeLookup[code];
- int len = val & LenMask;
- assert(len >= 0);
- assert(len <= 16);
-
- // if the code is invalid (bitstream corrupted) len will be 0
- bs.skipBitsNoFill(len);
- if (FULL_DECODE && val & FlagMask) {
- // if the flag bit is set, the payload is the already sign extended difference
- return val >> PayloadShift;
- }
-
- if (len) {
- // if the flag bit is not set but len != 0, the payload is the number of bits to sign extend and return
- const int l_diff = val >> PayloadShift;
- assert((FULL_DECODE && (len + l_diff <= 32)) || !FULL_DECODE);
- return FULL_DECODE ? signExtended(bs.getBitsNoFill(l_diff), l_diff) : l_diff;
- }
-
- uint32 code_l = LookupDepth;
- bs.skipBitsNoFill(code_l);
- while (code_l < maxCodeOL.size() && code > maxCodeOL[code_l]) {
- uint32 temp = bs.getBitsNoFill(1);
- code = (code << 1) | temp;
- code_l++;
- }
-
- if (code_l >= maxCodeOL.size() || code > maxCodeOL[code_l])
- ThrowRDE("bad Huffman code: %u (len: %u)", code, code_l);
-
- if (code < codeOffsetOL[code_l])
- ThrowRDE("likely corrupt Huffman code: %u (len: %u)", code, code_l);
-
- int diff_l = codeValues[code - codeOffsetOL[code_l]];
-
- if (!FULL_DECODE)
- return diff_l;
-
- if (diff_l == 16) {
- if (fixDNGBug16)
- bs.skipBits(16);
- return -32768;
- }
+namespace rawspeed {
- assert(FULL_DECODE);
- assert((diff_l && (len + code_l + diff_l <= 32)) || !diff_l);
- return diff_l ? signExtended(bs.getBitsNoFill(diff_l), diff_l) : 0;
- }
-};
+using HuffmanTable = HuffmanTableLUT;
+// using HuffmanTable = HuffmanTableLookup;
+// using HuffmanTable = HuffmanTableTree;
+// using HuffmanTable = HuffmanTableVector;
} // namespace rawspeed
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/HuffmanTableLUT.h b/src/external/rawspeed/src/librawspeed/decompressors/HuffmanTableLUT.h
new file mode 100644
index 000000000..45c7c31c5
--- /dev/null
+++ b/src/external/rawspeed/src/librawspeed/decompressors/HuffmanTableLUT.h
@@ -0,0 +1,257 @@
+/*
+ RawSpeed - RAW file decoder.
+
+ Copyright (C) 2017 Axel Waggershauser
+ Copyright (C) 2017-2018 Roman Lebedev
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#pragma once
+
+#include "common/Common.h" // for uint32, ushort16, int32
+#include "decoders/RawDecoderException.h" // for ThrowRDE
+#include "decompressors/AbstractHuffmanTable.h" // for AbstractHuffmanTable
+#include "io/BitStream.h" // for BitStreamTraits
+#include <cassert> // for assert
+#include <cstddef> // for size_t
+#include <memory> // for allocator_traits<>::...
+#include <vector> // for vector
+
+/*
+* The following code is inspired by the IJG JPEG library.
+*
+* Copyright (C) 1991, 1992, Thomas G. Lane.
+* Part of the Independent JPEG Group's software.
+* See the file Copyright for more details.
+*
+* Copyright (c) 1993 Brian C. Smith, The Regents of the University
+* of California
+* All rights reserved.
+*
+* Copyright (c) 1994 Kongji Huang and Brian C. Smith.
+* Cornell University
+* All rights reserved.
+*
+* Permission to use, copy, modify, and distribute this software and its
+* documentation for any purpose, without fee, and without written agreement is
+* hereby granted, provided that the above copyright notice and the following
+* two paragraphs appear in all copies of this software.
+*
+* IN NO EVENT SHALL CORNELL UNIVERSITY BE LIABLE TO ANY PARTY FOR
+* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF CORNELL
+* UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* CORNELL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+* ON AN "AS IS" BASIS, AND CORNELL UNIVERSITY HAS NO OBLIGATION TO
+* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+*/
+
+namespace rawspeed {
+
+class HuffmanTableLUT final : public AbstractHuffmanTable {
+ // private fields calculated from codesPerBits and codeValues
+ // they are index '1' based, so we can directly lookup the value
+ // for code length l without decrementing
+ std::vector<uint32> maxCodeOL; // index is length of code
+ std::vector<ushort16> codeOffsetOL; // index is length of code
+
+ // The code can be compiled with two different decode lookup table layouts.
+ // The idea is that different CPU architectures may perform better with
+ // one or the other, depending on the relative performance of their arithmetic
+ // core vs their memory access. For an Intel Core i7, the big table is better.
+#if 1
+ // lookup table containing 3 fields: payload:16|flag:8|len:8
+ // The payload may be the fully decoded diff or the length of the diff.
+ // The len field contains the number of bits, this lookup consumed.
+ // A lookup value of 0 means the code was too big to fit into the table.
+ // The optimal LookupDepth is also likely to depend on the CPU architecture.
+ static constexpr unsigned PayloadShift = 16;
+ static constexpr unsigned FlagMask = 0x100;
+ static constexpr unsigned LenMask = 0xff;
+ static constexpr unsigned LookupDepth = 11;
+ std::vector<int32> decodeLookup;
+#else
+ // lookup table containing 2 fields: payload:4|len:4
+ // the payload is the length of the diff, len is the length of the code
+ static constexpr unsigned LookupDepth = 15;
+ static constexpr unsigned PayloadShift = 4;
+ static constexpr unsigned FlagMask = 0;
+ static constexpr unsigned LenMask = 0x0f;
+ std::vector<uchar8> decodeLookup;
+#endif
+
+ bool fullDecode = true;
+ bool fixDNGBug16 = false;
+
+public:
+ void setup(bool fullDecode_, bool fixDNGBug16_) {
+ this->fullDecode = fullDecode_;
+ this->fixDNGBug16 = fixDNGBug16_;
+
+ assert(!nCodesPerLength.empty());
+ assert(maxCodesCount() > 0);
+
+ unsigned int maxCodeLength = nCodesPerLength.size() - 1U;
+ assert(codeValues.size() == maxCodesCount());
+
+ assert(maxCodePlusDiffLength() <= 32U);
+
+ // Figure C.1: make table of Huffman code length for each symbol
+ // Figure C.2: generate the codes themselves
+ const auto symbols = generateCodeSymbols();
+ assert(symbols.size() == maxCodesCount());
+
+ // Figure F.15: generate decoding tables
+ codeOffsetOL.resize(maxCodeLength + 1UL, 0xFFFF);
+ maxCodeOL.resize(maxCodeLength + 1UL, 0xFFFFFFFF);
+ int code_index = 0;
+ for (unsigned int l = 1U; l <= maxCodeLength; l++) {
+ if (nCodesPerLength[l]) {
+ codeOffsetOL[l] = symbols[code_index].code - code_index;
+ code_index += nCodesPerLength[l];
+ maxCodeOL[l] = symbols[code_index - 1].code;
+ }
+ }
+
+ // Generate lookup table for fast decoding lookup.
+ // See definition of decodeLookup above
+ decodeLookup.resize(1 << LookupDepth);
+ for (size_t i = 0; i < symbols.size(); i++) {
+ uchar8 code_l = symbols[i].code_len;
+ if (code_l > static_cast<int>(LookupDepth))
+ break;
+
+ ushort16 ll = symbols[i].code << (LookupDepth - code_l);
+ ushort16 ul = ll | ((1 << (LookupDepth - code_l)) - 1);
+ ushort16 diff_l = codeValues[i];
+ for (ushort16 c = ll; c <= ul; c++) {
+ if (!(c < decodeLookup.size()))
+ ThrowRDE("Corrupt Huffman");
+
+ if (!FlagMask || !fullDecode || diff_l + code_l > LookupDepth) {
+ // lookup bit depth is too small to fit both the encoded length
+ // and the final difference value.
+ // -> store only the length and do a normal sign extension later
+ decodeLookup[c] = diff_l << PayloadShift | code_l;
+ } else {
+ // diff_l + code_l <= lookupDepth
+ // The table bit depth is large enough to store both.
+ decodeLookup[c] = (code_l + diff_l) | FlagMask;
+
+ if (diff_l) {
+ uint32 diff = (c >> (LookupDepth - code_l - diff_l)) & ((1 << diff_l) - 1);
+ decodeLookup[c] |= static_cast<int32>(
+ static_cast<uint32>(signExtended(diff, diff_l))
+ << PayloadShift);
+ }
+ }
+ }
+ }
+ }
+
+ template<typename BIT_STREAM> inline int decodeLength(BIT_STREAM& bs) const {
+ static_assert(BitStreamTraits<BIT_STREAM>::canUseWithHuffmanTable,
+ "This BitStream specialization is not marked as usable here");
+ assert(!fullDecode);
+ return decode<BIT_STREAM, false>(bs);
+ }
+
+ template<typename BIT_STREAM> inline int decodeNext(BIT_STREAM& bs) const {
+ static_assert(BitStreamTraits<BIT_STREAM>::canUseWithHuffmanTable,
+ "This BitStream specialization is not marked as usable here");
+ assert(fullDecode);
+ return decode<BIT_STREAM, true>(bs);
+ }
+
+ // The bool template paraeter is to enable two versions:
+ // one returning only the length of the of diff bits (see Hasselblad),
+ // one to return the fully decoded diff.
+ // All ifs depending on this bool will be optimized out by the compiler
+ template<typename BIT_STREAM, bool FULL_DECODE> inline int decode(BIT_STREAM& bs) const {
+ static_assert(BitStreamTraits<BIT_STREAM>::canUseWithHuffmanTable,
+ "This BitStream specialization is not marked as usable here");
+ assert(FULL_DECODE == fullDecode);
+
+ // 32 is the absolute maximum combined length of code + diff
+ // assertion maxCodePlusDiffLength() <= 32U is already checked in setup()
+ bs.fill(32);
+
+ // for processors supporting bmi2 instructions, using maxCodePlusDiffLength()
+ // might be benifitial
+
+ uint32 code = bs.peekBitsNoFill(LookupDepth);
+ assert(code < decodeLookup.size());
+ auto val = static_cast<unsigned>(decodeLookup[code]);
+ int len = val & LenMask;
+ assert(len >= 0);
+ assert(len <= 16);
+
+ // if the code is invalid (bitstream corrupted) len will be 0
+ bs.skipBitsNoFill(len);
+ if (FULL_DECODE && val & FlagMask) {
+ // if the flag bit is set, the payload is the already sign extended difference
+ return static_cast<int>(val) >> PayloadShift;
+ }
+
+ if (len) {
+ // if the flag bit is not set but len != 0, the payload is the number of bits to sign extend and return
+ const int l_diff = static_cast<int>(val) >> PayloadShift;
+ assert((FULL_DECODE && (len + l_diff <= 32)) || !FULL_DECODE);
+ if (FULL_DECODE && l_diff == 16) {
+ if (fixDNGBug16)
+ bs.skipBits(16);
+ return -32768;
+ }
+ return FULL_DECODE ? signExtended(bs.getBitsNoFill(l_diff), l_diff) : l_diff;
+ }
+
+ uint32 code_l = LookupDepth;
+ bs.skipBitsNoFill(code_l);
+ while (code_l < maxCodeOL.size() &&
+ (0xFFFFFFFF == maxCodeOL[code_l] || code > maxCodeOL[code_l])) {
+ uint32 temp = bs.getBitsNoFill(1);
+ code = (code << 1) | temp;
+ code_l++;
+ }
+
+ if (code_l >= maxCodeOL.size() ||
+ (0xFFFFFFFF == maxCodeOL[code_l] || code > maxCodeOL[code_l]))
+ ThrowRDE("bad Huffman code: %u (len: %u)", code, code_l);
+
+ if (code < codeOffsetOL[code_l])
+ ThrowRDE("likely corrupt Huffman code: %u (len: %u)", code, code_l);
+
+ int diff_l = codeValues[code - codeOffsetOL[code_l]];
+
+ if (!FULL_DECODE)
+ return diff_l;
+
+ if (diff_l == 16) {
+ if (fixDNGBug16)
+ bs.skipBits(16);
+ return -32768;
+ }
+
+ assert(FULL_DECODE);
+ assert((diff_l && (len + code_l + diff_l <= 32)) || !diff_l);
+ return diff_l ? signExtended(bs.getBitsNoFill(diff_l), diff_l) : 0;
+ }
+};
+
+} // namespace rawspeed
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/HuffmanTableLookup.h b/src/external/rawspeed/src/librawspeed/decompressors/HuffmanTableLookup.h
new file mode 100644
index 000000000..df8408ccf
--- /dev/null
+++ b/src/external/rawspeed/src/librawspeed/decompressors/HuffmanTableLookup.h
@@ -0,0 +1,171 @@
+/*
+ RawSpeed - RAW file decoder.
+
+ Copyright (C) 2017 Axel Waggershauser
+ Copyright (C) 2017-2018 Roman Lebedev
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#pragma once
+
+#include "common/Common.h" // for uint32, ushort16
+#include "decoders/RawDecoderException.h" // for ThrowRDE
+#include "decompressors/AbstractHuffmanTable.h" // for AbstractHuffmanTable
+#include "io/BitStream.h" // for BitStreamTraits
+#include <cassert> // for assert
+#include <memory> // for allocator_traits<>::...
+#include <vector> // for vector
+
+/*
+ * The following code is inspired by the IJG JPEG library.
+ *
+ * Copyright (C) 1991, 1992, Thomas G. Lane.
+ * Part of the Independent JPEG Group's software.
+ * See the file Copyright for more details.
+ *
+ * Copyright (c) 1993 Brian C. Smith, The Regents of the University
+ * of California
+ * All rights reserved.
+ *
+ * Copyright (c) 1994 Kongji Huang and Brian C. Smith.
+ * Cornell University
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose, without fee, and without written agreement is
+ * hereby granted, provided that the above copyright notice and the following
+ * two paragraphs appear in all copies of this software.
+ *
+ * IN NO EVENT SHALL CORNELL UNIVERSITY BE LIABLE TO ANY PARTY FOR
+ * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
+ * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF CORNELL
+ * UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * CORNELL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND CORNELL UNIVERSITY HAS NO OBLIGATION TO
+ * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+namespace rawspeed {
+
+class HuffmanTableLookup final : public AbstractHuffmanTable {
+ // private fields calculated from codesPerBits and codeValues
+ // they are index '1' based, so we can directly lookup the value
+ // for code length l without decrementing
+ std::vector<uint32> maxCodeOL; // index is length of code
+ std::vector<ushort16> codeOffsetOL; // index is length of code
+
+ bool fullDecode = true;
+ bool fixDNGBug16 = false;
+
+public:
+ void setup(bool fullDecode_, bool fixDNGBug16_) {
+ this->fullDecode = fullDecode_;
+ this->fixDNGBug16 = fixDNGBug16_;
+
+ assert(!nCodesPerLength.empty());
+ assert(maxCodesCount() > 0);
+
+ unsigned int maxCodeLength = nCodesPerLength.size() - 1U;
+ assert(codeValues.size() == maxCodesCount());
+
+ assert(maxCodePlusDiffLength() <= 32U);
+
+ // Figure C.1: make table of Huffman code length for each symbol
+ // Figure C.2: generate the codes themselves
+ const auto symbols = generateCodeSymbols();
+ assert(symbols.size() == maxCodesCount());
+
+ // Figure F.15: generate decoding tables
+ codeOffsetOL.resize(maxCodeLength + 1UL, 0xFFFF);
+ maxCodeOL.resize(maxCodeLength + 1UL, 0xFFFFFFFF);
+ int code_index = 0;
+ for (unsigned int l = 1U; l <= maxCodeLength; l++) {
+ if (nCodesPerLength[l]) {
+ codeOffsetOL[l] = symbols[code_index].code - code_index;
+ code_index += nCodesPerLength[l];
+ maxCodeOL[l] = symbols[code_index - 1].code;
+ }
+ }
+ }
+
+ template <typename BIT_STREAM> inline int decodeLength(BIT_STREAM& bs) const {
+ static_assert(BitStreamTraits<BIT_STREAM>::canUseWithHuffmanTable,
+ "This BitStream specialization is not marked as usable here");
+ assert(!fullDecode);
+ return decode<BIT_STREAM, false>(bs);
+ }
+
+ template <typename BIT_STREAM> inline int decodeNext(BIT_STREAM& bs) const {
+ static_assert(BitStreamTraits<BIT_STREAM>::canUseWithHuffmanTable,
+ "This BitStream specialization is not marked as usable here");
+ assert(fullDecode);
+ return decode<BIT_STREAM, true>(bs);
+ }
+
+ // The bool template paraeter is to enable two versions:
+ // one returning only the length of the of diff bits (see Hasselblad),
+ // one to return the fully decoded diff.
+ // All ifs depending on this bool will be optimized out by the compiler
+ template <typename BIT_STREAM, bool FULL_DECODE>
+ inline int decode(BIT_STREAM& bs) const {
+ static_assert(BitStreamTraits<BIT_STREAM>::canUseWithHuffmanTable,
+ "This BitStream specialization is not marked as usable here");
+ assert(FULL_DECODE == fullDecode);
+
+ // 32 is the absolute maximum combined length of code + diff
+ // assertion maxCodePlusDiffLength() <= 32U is already checked in setup()
+ bs.fill(32);
+
+ // for processors supporting bmi2 instructions, using
+ // maxCodePlusDiffLength() might be benifitial
+
+ uint32 code = 0;
+ uint32 code_l = 0;
+ while (code_l < maxCodeOL.size() &&
+ (0xFFFFFFFF == maxCodeOL[code_l] || code > maxCodeOL[code_l])) {
+ uint32 temp = bs.getBitsNoFill(1);
+ code = (code << 1) | temp;
+ code_l++;
+ }
+
+ if (code_l >= maxCodeOL.size() ||
+ (0xFFFFFFFF == maxCodeOL[code_l] || code > maxCodeOL[code_l]))
+ ThrowRDE("bad Huffman code: %u (len: %u)", code, code_l);
+
+ if (code < codeOffsetOL[code_l])
+ ThrowRDE("likely corrupt Huffman code: %u (len: %u)", code, code_l);
+
+ int diff_l = codeValues[code - codeOffsetOL[code_l]];
+
+ if (!FULL_DECODE)
+ return diff_l;
+
+ if (diff_l == 16) {
+ if (fixDNGBug16)
+ bs.skipBits(16);
+ return -32768;
+ }
+
+ assert(FULL_DECODE);
+ assert((diff_l && (code_l + diff_l <= 32)) || !diff_l);
+ return diff_l ? signExtended(bs.getBitsNoFill(diff_l), diff_l) : 0;
+ }
+};
+
+} // namespace rawspeed
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/HuffmanTableTree.h b/src/external/rawspeed/src/librawspeed/decompressors/HuffmanTableTree.h
new file mode 100644
index 000000000..0dd0088e4
--- /dev/null
+++ b/src/external/rawspeed/src/librawspeed/decompressors/HuffmanTableTree.h
@@ -0,0 +1,165 @@
+/*
+ RawSpeed - RAW file decoder.
+
+ Copyright (C) 2017 Axel Waggershauser
+ Copyright (C) 2018 Roman Lebedev
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#pragma once
+
+#include "decoders/RawDecoderException.h" // for ThrowRDE
+#include "decompressors/AbstractHuffmanTable.h" // for AbstractHuffmanTable...
+#include "decompressors/BinaryHuffmanTree.h" // IWYU pragma: export
+#include "io/BitStream.h" // for BitStreamTraits
+#include <algorithm> // for for_each
+#include <cassert> // for assert
+#include <initializer_list> // for initializer_list
+#include <iterator> // for advance, next
+#include <memory> // for unique_ptr, make_unique
+#include <vector> // for vector, vector<>::co...
+
+namespace rawspeed {
+
+class HuffmanTableTree final : public AbstractHuffmanTable {
+ using ValueType = decltype(codeValues)::value_type;
+
+ BinaryHuffmanTree<ValueType> tree;
+
+ bool fullDecode = true;
+ bool fixDNGBug16 = false;
+
+protected:
+ template <typename BIT_STREAM>
+ inline ValueType getValue(BIT_STREAM& bs) const {
+ static_assert(BitStreamTraits<BIT_STREAM>::canUseWithHuffmanTable,
+ "This BitStream specialization is not marked as usable here");
+ CodeSymbol partial;
+
+ const auto* top = &(tree.root->getAsBranch());
+
+ // Read bits until either find the code or detect the uncorrect code
+ for (partial.code = 0, partial.code_len = 1;; ++partial.code_len) {
+ assert(partial.code_len <= 16);
+
+ // Read one more bit
+ const bool bit = bs.getBits(1);
+
+ partial.code <<= 1;
+ partial.code |= bit;
+
+ // What is the last bit, which we have just read?
+
+ // NOTE: The order *IS* important! Left to right, zero to one!
+ const auto& newNode = !bit ? top->zero : top->one;
+
+ if (!newNode) {
+ // Got nothing in this direction.
+ ThrowRDE("bad Huffman code: %u (len: %u)", partial.code,
+ partial.code_len);
+ }
+
+ if (static_cast<decltype(tree)::Node::Type>(*newNode) ==
+ decltype(tree)::Node::Type::Leaf) {
+ // Ok, great, hit a Leaf. This is it.
+ return newNode->getAsLeaf().value;
+ }
+
+ // Else, this is a branch, continue looking.
+ top = &(newNode->getAsBranch());
+ }
+
+ // We have either returned the found symbol, or thrown on uncorrect symbol.
+ __builtin_unreachable();
+ }
+
+public:
+ void setup(bool fullDecode_, bool fixDNGBug16_) {
+ this->fullDecode = fullDecode_;
+ this->fixDNGBug16 = fixDNGBug16_;
+
+ assert(!nCodesPerLength.empty());
+ assert(maxCodesCount() > 0);
+ assert(codeValues.size() == maxCodesCount());
+
+ auto currValue = codeValues.cbegin();
+ for (auto codeLen = 1UL; codeLen < nCodesPerLength.size(); codeLen++) {
+ const auto nCodesForCurrLen = nCodesPerLength[codeLen];
+
+ auto nodes = tree.getAllVacantNodesAtDepth(codeLen);
+ if (nodes.size() < nCodesForCurrLen) {
+ ThrowRDE("Got too many (%u) codes for len %lu, can only have %zu codes",
+ nCodesForCurrLen, codeLen, nodes.size());
+ }
+
+ // Make first nCodesForCurrLen nodes Leafs
+ std::for_each(nodes.cbegin(), std::next(nodes.cbegin(), nCodesForCurrLen),
+ [&currValue](auto* node) {
+ *node =
+ std::make_unique<decltype(tree)::Leaf>(*currValue);
+ std::advance(currValue, 1);
+ });
+ }
+
+ assert(codeValues.cend() == currValue);
+
+ // And get rid of all the branches that do not lead to Leafs.
+ // It is crucial to detect degenerate codes at the earliest.
+ tree.pruneLeaflessBranches();
+ }
+
+ template <typename BIT_STREAM> inline int decodeLength(BIT_STREAM& bs) const {
+ static_assert(BitStreamTraits<BIT_STREAM>::canUseWithHuffmanTable,
+ "This BitStream specialization is not marked as usable here");
+ assert(!fullDecode);
+ return decode<BIT_STREAM, false>(bs);
+ }
+
+ template <typename BIT_STREAM> inline int decodeNext(BIT_STREAM& bs) const {
+ static_assert(BitStreamTraits<BIT_STREAM>::canUseWithHuffmanTable,
+ "This BitStream specialization is not marked as usable here");
+ assert(fullDecode);
+ return decode<BIT_STREAM, true>(bs);
+ }
+
+ // The bool template paraeter is to enable two versions:
+ // one returning only the length of the of diff bits (see Hasselblad),
+ // one to return the fully decoded diff.
+ // All ifs depending on this bool will be optimized out by the compiler
+ template <typename BIT_STREAM, bool FULL_DECODE>
+ inline int decode(BIT_STREAM& bs) const {
+ static_assert(BitStreamTraits<BIT_STREAM>::canUseWithHuffmanTable,
+ "This BitStream specialization is not marked as usable here");
+ assert(FULL_DECODE == fullDecode);
+
+ const auto codeValue = getValue(bs);
+
+ const int diff_l = codeValue;
+
+ if (!FULL_DECODE)
+ return diff_l;
+
+ if (diff_l == 16) {
+ if (fixDNGBug16)
+ bs.skipBits(16);
+ return -32768;
+ }
+
+ return diff_l ? signExtended(bs.getBits(diff_l), diff_l) : 0;
+ }
+};
+
+} // namespace rawspeed
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/HuffmanTableVector.h b/src/external/rawspeed/src/librawspeed/decompressors/HuffmanTableVector.h
new file mode 100644
index 000000000..3a1c8824a
--- /dev/null
+++ b/src/external/rawspeed/src/librawspeed/decompressors/HuffmanTableVector.h
@@ -0,0 +1,155 @@
+/*
+ RawSpeed - RAW file decoder.
+
+ Copyright (C) 2017 Axel Waggershauser
+ Copyright (C) 2018 Roman Lebedev
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#pragma once
+
+#include "decoders/RawDecoderException.h" // for ThrowRDE
+#include "decompressors/AbstractHuffmanTable.h" // for AbstractHuffmanTable...
+#include "io/BitStream.h" // for BitStreamTraits
+#include <cassert> // for assert
+#include <utility> // for make_pair, pair
+#include <vector> // for vector
+
+namespace rawspeed {
+
+class HuffmanTableVector final : public AbstractHuffmanTable {
+ std::vector<CodeSymbol> symbols;
+
+ bool fullDecode = true;
+ bool fixDNGBug16 = false;
+
+ // Given this code len, which code id is the minimal?
+ std::vector<unsigned int> extrCodeIdForLen; // index is length of code
+
+protected:
+ template <typename BIT_STREAM>
+ inline std::pair<CodeSymbol, unsigned> getSymbol(BIT_STREAM& bs) const {
+ static_assert(BitStreamTraits<BIT_STREAM>::canUseWithHuffmanTable,
+ "This BitStream specialization is not marked as usable here");
+
+ CodeSymbol partial;
+ unsigned long codeId;
+
+ // Read bits until either find the code or detect the uncorrect code
+ for (partial.code = 0, partial.code_len = 1;; ++partial.code_len) {
+ assert(partial.code_len <= 16);
+
+ // Read one more bit
+ const bool bit = bs.getBits(1);
+
+ partial.code <<= 1;
+ partial.code |= bit;
+
+ // Given global ordering and the code length, we know the code id range.
+ for (codeId = extrCodeIdForLen[partial.code_len];
+ codeId < extrCodeIdForLen[1U + partial.code_len]; codeId++) {
+ const CodeSymbol& symbol = symbols[codeId];
+ if (symbol == partial) // yay, found?
+ return std::make_pair(symbol, codeId);
+ }
+
+ // Ok, but does any symbol have this same prefix?
+ bool haveCommonPrefix = false;
+ for (; codeId < symbols.size(); codeId++) {
+ const CodeSymbol& symbol = symbols[codeId];
+ haveCommonPrefix |= CodeSymbol::HaveCommonPrefix(symbol, partial);
+ if (haveCommonPrefix)
+ break;
+ }
+
+ // If no symbols have this prefix, then the code is invalid.
+ if (!haveCommonPrefix) {
+ ThrowRDE("bad Huffman code: %u (len: %u)", partial.code,
+ partial.code_len);
+ }
+ }
+
+ // We have either returned the found symbol, or thrown on uncorrect symbol.
+ __builtin_unreachable();
+ }
+
+public:
+ void setup(bool fullDecode_, bool fixDNGBug16_) {
+ this->fullDecode = fullDecode_;
+ this->fixDNGBug16 = fixDNGBug16_;
+
+ assert(!nCodesPerLength.empty());
+ assert(maxCodesCount() > 0);
+ assert(codeValues.size() == maxCodesCount());
+
+ // Figure C.1: make table of Huffman code length for each symbol
+ // Figure C.2: generate the codes themselves
+ symbols = generateCodeSymbols();
+ assert(symbols.size() == maxCodesCount());
+
+ extrCodeIdForLen.reserve(1U + nCodesPerLength.size());
+ extrCodeIdForLen.resize(2); // for len 0 and 1, the min code id is always 0
+ for (auto codeLen = 1UL; codeLen < nCodesPerLength.size(); codeLen++) {
+ auto minCodeId = extrCodeIdForLen.back();
+ minCodeId += nCodesPerLength[codeLen];
+ extrCodeIdForLen.emplace_back(minCodeId);
+ }
+ assert(extrCodeIdForLen.size() == 1U + nCodesPerLength.size());
+ }
+
+ template <typename BIT_STREAM> inline int decodeLength(BIT_STREAM& bs) const {
+ static_assert(BitStreamTraits<BIT_STREAM>::canUseWithHuffmanTable,
+ "This BitStream specialization is not marked as usable here");
+ assert(!fullDecode);
+ return decode<BIT_STREAM, false>(bs);
+ }
+
+ template <typename BIT_STREAM> inline int decodeNext(BIT_STREAM& bs) const {
+ static_assert(BitStreamTraits<BIT_STREAM>::canUseWithHuffmanTable,
+ "This BitStream specialization is not marked as usable here");
+ assert(fullDecode);
+ return decode<BIT_STREAM, true>(bs);
+ }
+
+ // The bool template paraeter is to enable two versions:
+ // one returning only the length of the of diff bits (see Hasselblad),
+ // one to return the fully decoded diff.
+ // All ifs depending on this bool will be optimized out by the compiler
+ template <typename BIT_STREAM, bool FULL_DECODE>
+ inline int decode(BIT_STREAM& bs) const {
+ static_assert(BitStreamTraits<BIT_STREAM>::canUseWithHuffmanTable,
+ "This BitStream specialization is not marked as usable here");
+ assert(FULL_DECODE == fullDecode);
+
+ const auto got = getSymbol(bs);
+ const unsigned codeId = got.second;
+
+ const int diff_l = codeValues[codeId];
+
+ if (!FULL_DECODE)
+ return diff_l;
+
+ if (diff_l == 16) {
+ if (fixDNGBug16)
+ bs.skipBits(16);
+ return -32768;
+ }
+
+ return diff_l ? signExtended(bs.getBits(diff_l), diff_l) : 0;
+ }
+};
+
+} // namespace rawspeed
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/JpegDecompressor.cpp b/src/external/rawspeed/src/librawspeed/decompressors/JpegDecompressor.cpp
index 63d56b50d..13fabb6cb 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/JpegDecompressor.cpp
+++ b/src/external/rawspeed/src/librawspeed/decompressors/JpegDecompressor.cpp
@@ -96,9 +96,10 @@ static void jpeg_mem_src_int(j_decompress_ptr cinfo,
#endif
[[noreturn]] METHODDEF(void) my_error_throw(j_common_ptr cinfo) {
- char buf[JMSG_LENGTH_MAX] = {0};
- (*cinfo->err->format_message)(cinfo, buf);
- ThrowRDE("JPEG decoder error: %s", buf);
+ std::array<char, JMSG_LENGTH_MAX> buf;
+ buf.fill(0);
+ (*cinfo->err->format_message)(cinfo, buf.data());
+ ThrowRDE("JPEG decoder error: %s", buf.data());
}
struct JpegDecompressor::JpegDecompressStruct : jpeg_decompress_struct {
@@ -130,9 +131,11 @@ void JpegDecompressor::decode(uint32 offX,
ThrowRDE("Component count doesn't match");
int row_stride = dinfo.output_width * dinfo.output_components;
- unique_ptr<uchar8[], decltype(&alignedFree)> complete_buffer(
- alignedMallocArray<uchar8, 16>(dinfo.output_height, row_stride),
- &alignedFree);
+ unique_ptr<uchar8[], // NOLINT
+ decltype(&alignedFree)>
+ complete_buffer(
+ alignedMallocArray<uchar8, 16>(dinfo.output_height, row_stride),
+ &alignedFree);
while (dinfo.output_scanline < dinfo.output_height) {
buffer[0] = static_cast<JSAMPROW>(
&complete_buffer[static_cast<size_t>(dinfo.output_scanline) *
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/JpegDecompressor.h b/src/external/rawspeed/src/librawspeed/decompressors/JpegDecompressor.h
index ed1ddfd27..114c6ed89 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/JpegDecompressor.h
+++ b/src/external/rawspeed/src/librawspeed/decompressors/JpegDecompressor.h
@@ -27,9 +27,8 @@
#include "common/Common.h" // for uint32
#include "common/RawImage.h" // for RawImage
#include "decompressors/AbstractDecompressor.h" // for AbstractDecompressor
-#include "io/Buffer.h" // for Buffer, Buffer::size_type
#include "io/ByteStream.h" // for ByteStream
-#include "io/Endianness.h" // for getHostEndianness
+#include "io/Endianness.h" // for Endianness, Endianne...
#include <utility> // for move
namespace rawspeed {
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/KodakDecompressor.cpp b/src/external/rawspeed/src/librawspeed/decompressors/KodakDecompressor.cpp
index 81388f8e3..7d19a5603 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/KodakDecompressor.cpp
+++ b/src/external/rawspeed/src/librawspeed/decompressors/KodakDecompressor.cpp
@@ -20,23 +20,24 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "rawspeedconfig.h"
#include "decompressors/KodakDecompressor.h"
-#include "common/RawImage.h" // for RawImage
-#include "decoders/RawDecoderException.h" // for RawDecoderException (ptr o...
+#include "common/Point.h" // for iPoint2D
+#include "common/RawImage.h" // for RawImage, RawImageData
+#include "decoders/RawDecoderException.h" // for ThrowRDE
#include "decompressors/HuffmanTable.h" // for HuffmanTable
#include "io/ByteStream.h" // for ByteStream
#include <algorithm> // for min
#include <array> // for array
#include <cassert> // for assert
+#include <utility> // for move
namespace rawspeed {
constexpr int KodakDecompressor::segment_size;
KodakDecompressor::KodakDecompressor(const RawImage& img, ByteStream bs,
- bool uncorrectedRawValues_)
- : mRaw(img), input(std::move(bs)),
+ int bps_, bool uncorrectedRawValues_)
+ : mRaw(img), input(std::move(bs)), bps(bps_),
uncorrectedRawValues(uncorrectedRawValues_) {
if (mRaw->getCpp() != 1 || mRaw->getDataType() != TYPE_USHORT16 ||
mRaw->getBpp() != 2)
@@ -47,6 +48,9 @@ KodakDecompressor::KodakDecompressor(const RawImage& img, ByteStream bs,
ThrowRDE("Unexpected image dimensions found: (%u; %u)", mRaw->dim.x,
mRaw->dim.y);
+ if (bps != 10 && bps != 12)
+ ThrowRDE("Unexpected bits per sample: %i", bps);
+
// Lower estimate: this decompressor requires *at least* half a byte
// per output pixel
input.check(mRaw->dim.area() / 2ULL);
@@ -83,6 +87,7 @@ KodakDecompressor::decodeSegment(const uint32 bsize) {
}
for (uint32 i = 0; i < bsize; i++) {
uint32 len = blen[i];
+ assert(len < 16);
if (bits < len) {
for (uint32 j = 0; j < 32; j += 8) {
@@ -95,9 +100,8 @@ KodakDecompressor::decodeSegment(const uint32 bsize) {
uint32 diff = static_cast<uint32>(bitbuf) & (0xffff >> (16 - len));
bitbuf >>= len;
bits -= len;
- diff = len != 0 ? HuffmanTable::signExtended(diff, len) : diff;
- out[i] = diff;
+ out[i] = len != 0 ? HuffmanTable::signExtended(diff, len) : int(diff);
}
return out;
@@ -116,15 +120,15 @@ void KodakDecompressor::decompress() {
const segment buf = decodeSegment(len);
- std::array<uint32, 2> pred;
+ std::array<int, 2> pred;
pred.fill(0);
for (uint32 i = 0; i < len; i++) {
pred[i & 1] += buf[i];
- ushort16 value = pred[i & 1];
- if (value > 1023)
- ThrowRDE("Value out of bounds %d", value);
+ int value = pred[i & 1];
+ if (unsigned(value) >= (1U << bps))
+ ThrowRDE("Value out of bounds %d (bps = %i)", value, bps);
if (uncorrectedRawValues)
dest[x + i] = value;
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/KodakDecompressor.h b/src/external/rawspeed/src/librawspeed/decompressors/KodakDecompressor.h
index 9b89edc12..14bc4f0bf 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/KodakDecompressor.h
+++ b/src/external/rawspeed/src/librawspeed/decompressors/KodakDecompressor.h
@@ -33,15 +33,16 @@ namespace rawspeed {
class KodakDecompressor final : public AbstractDecompressor {
RawImage mRaw;
ByteStream input;
+ int bps;
bool uncorrectedRawValues;
static constexpr int segment_size = 256; // pixels
- using segment = std::array<ushort16, segment_size>;
+ using segment = std::array<short16, segment_size>;
segment decodeSegment(uint32 bsize);
public:
- KodakDecompressor(const RawImage& img, ByteStream bs,
+ KodakDecompressor(const RawImage& img, ByteStream bs, int bps,
bool uncorrectedRawValues_);
void decompress();
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/LJpegDecompressor.cpp b/src/external/rawspeed/src/librawspeed/decompressors/LJpegDecompressor.cpp
index fc037af73..69572bf16 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/LJpegDecompressor.cpp
+++ b/src/external/rawspeed/src/librawspeed/decompressors/LJpegDecompressor.cpp
@@ -20,12 +20,13 @@
*/
#include "decompressors/LJpegDecompressor.h"
-#include "common/Common.h" // for uint32, unroll_loop, ushort16
+#include "common/Common.h" // for unroll_loop, uint32, ushort16
#include "common/Point.h" // for iPoint2D
#include "common/RawImage.h" // for RawImage, RawImageData
#include "decoders/RawDecoderException.h" // for ThrowRDE
-#include "io/BitPumpJPEG.h" // for BitPumpJPEG
-#include <algorithm> // for min, copy_n
+#include "io/BitPumpJPEG.h" // for BitPumpJPEG, BitStream<>::...
+#include <algorithm> // for copy_n
+#include <cassert> // for assert
using std::copy_n;
@@ -94,38 +95,62 @@ void LJpegDecompressor::decodeScan()
if ((mRaw->getCpp() * (mRaw->dim.x - offX)) < frame.cps)
ThrowRDE("Got less pixels than the components per sample");
- const auto tilePixelBlocks = mRaw->getCpp() * w;
- if (tilePixelBlocks % frame.cps != 0) {
- ThrowRDE("Tile component width (%u) is not multiple of LJpeg CPS (%u)",
- tilePixelBlocks, frame.cps);
- }
+ // How many output pixels are we expected to produce, as per DNG tiling?
+ const auto tileRequiredWidth = mRaw->getCpp() * w;
- wBlocks = tilePixelBlocks / frame.cps;
- if (frame.w < wBlocks || frame.h < h) {
+ // How many full pixel blocks do we need to consume for that?
+ const auto blocksToConsume = roundUpDivision(tileRequiredWidth, frame.cps);
+ if (frame.w < blocksToConsume || frame.h < h) {
ThrowRDE("LJpeg frame (%u, %u) is smaller than expected (%u, %u)",
- frame.cps * frame.w, frame.h, tilePixelBlocks, h);
+ frame.cps * frame.w, frame.h, tileRequiredWidth, h);
}
- switch (frame.cps) {
- case 2:
- decodeN<2>();
- break;
- case 3:
- decodeN<3>();
- break;
- case 4:
- decodeN<4>();
- break;
- default:
- ThrowRDE("Unsupported number of components: %u", frame.cps);
+ // How many full pixel blocks will we produce?
+ fullBlocks = tileRequiredWidth / frame.cps; // Truncating division!
+ // Do we need to also produce part of a block?
+ trailingPixels = tileRequiredWidth % frame.cps;
+
+ if (trailingPixels == 0) {
+ switch (frame.cps) {
+ case 1:
+ decodeN<1>();
+ break;
+ case 2:
+ decodeN<2>();
+ break;
+ case 3:
+ decodeN<3>();
+ break;
+ case 4:
+ decodeN<4>();
+ break;
+ default:
+ ThrowRDE("Unsupported number of components: %u", frame.cps);
+ }
+ } else /* trailingPixels != 0 */ {
+ // FIXME: using different function just for one tile likely causes
+ // i-cache misses and whatnot. Need to check how not splitting it into
+ // two different functions affects performance of the normal case.
+ switch (frame.cps) {
+ // Naturally can't happen for CPS=1.
+ case 2:
+ decodeN<2, /*WeirdWidth=*/true>();
+ break;
+ case 3:
+ decodeN<3, /*WeirdWidth=*/true>();
+ break;
+ case 4:
+ decodeN<4, /*WeirdWidth=*/true>();
+ break;
+ default:
+ ThrowRDE("Unsupported number of components: %u", frame.cps);
+ }
}
}
// N_COMP == number of components (2, 3 or 4)
-template <int N_COMP>
-void LJpegDecompressor::decodeN()
-{
+template <int N_COMP, bool WeirdWidth> void LJpegDecompressor::decodeN() {
assert(mRaw->getCpp() > 0);
assert(N_COMP > 0);
assert(N_COMP >= mRaw->getCpp());
@@ -160,14 +185,38 @@ void LJpegDecompressor::decodeN()
// the predictor for the next line is the start of this line
predNext = dest;
- // For x, we first process all pixels within the image buffer ...
- for (unsigned x = 0; x < wBlocks; ++x) {
+ unsigned x = 0;
+
+ // For x, we first process all full pixel blocks within the image buffer ...
+ for (; x < fullBlocks; ++x) {
unroll_loop<N_COMP>([&](int i) {
*dest++ = pred[i] += ht[i]->decodeNext(bitStream);
});
}
+
+ // Sometimes we also need to consume one more block, and produce part of it.
+ if /*constexpr*/ (WeirdWidth) {
+ // FIXME: evaluate i-cache implications due to this being compile-time.
+ static_assert(N_COMP > 1 || !WeirdWidth,
+ "can't want part of 1-pixel-wide block");
+ // Some rather esoteric DNG's have odd dimensions, e.g. width % 2 = 1.
+ // We may end up needing just part of last N_COMP pixels.
+ assert(trailingPixels > 0);
+ assert(trailingPixels < N_COMP);
+ unsigned c = 0;
+ for (; c < trailingPixels; ++c) {
+ *dest++ = pred[c] += ht[c]->decodeNext(bitStream);
+ }
+ // Discard the rest of the block.
+ assert(c < N_COMP);
+ for (; c < N_COMP; ++c) {
+ ht[c]->decodeNext(bitStream);
+ }
+ ++x; // We did just process one more block.
+ }
+
// ... and discard the rest.
- for (unsigned x = wBlocks; x < frame.w; ++x) {
+ for (; x < frame.w; ++x) {
unroll_loop<N_COMP>([&](int i) {
ht[i]->decodeNext(bitStream);
});
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/LJpegDecompressor.h b/src/external/rawspeed/src/librawspeed/decompressors/LJpegDecompressor.h
index 41e51c1e5..d2783a85b 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/LJpegDecompressor.h
+++ b/src/external/rawspeed/src/librawspeed/decompressors/LJpegDecompressor.h
@@ -22,11 +22,10 @@
#include "common/Common.h" // for uint32
#include "decompressors/AbstractLJpegDecompressor.h" // for AbstractLJpegDe...
-#include "io/Buffer.h" // for Buffer, Buffer:...
-#include "io/ByteStream.h" // for ByteStream
namespace rawspeed {
+class ByteStream;
class RawImage;
// Decompresses Lossless JPEGs, with 2-4 components
@@ -34,20 +33,21 @@ class RawImage;
class LJpegDecompressor final : public AbstractLJpegDecompressor
{
void decodeScan() override;
- template<int N_COMP> void decodeN();
+ template <int N_COMP, bool WeirdWidth = false> void decodeN();
uint32 offX = 0;
uint32 offY = 0;
uint32 w = 0;
uint32 h = 0;
- uint32 wBlocks = 0;
+ uint32 fullBlocks = 0;
+ uint32 trailingPixels = 0;
public:
LJpegDecompressor(const ByteStream& bs, const RawImage& img);
void decode(uint32 offsetX, uint32 offsetY, uint32 width, uint32 height,
- bool fixDng16Bug);
+ bool fixDng16Bug_);
};
} // namespace rawspeed
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/NikonDecompressor.cpp b/src/external/rawspeed/src/librawspeed/decompressors/NikonDecompressor.cpp
index d8c0d7962..f07a60f81 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/NikonDecompressor.cpp
+++ b/src/external/rawspeed/src/librawspeed/decompressors/NikonDecompressor.cpp
@@ -19,44 +19,352 @@
*/
#include "decompressors/NikonDecompressor.h"
-#include "common/Common.h" // for uint32, ushort16, clampBits
+#include "common/Common.h" // for uint32, clampBits, ushort16
#include "common/Point.h" // for iPoint2D
-#include "common/RawImage.h" // for RawImage, RawImageData, RawI...
+#include "common/RawImage.h" // for RawImage, RawImageData
#include "decoders/RawDecoderException.h" // for ThrowRDE
#include "decompressors/HuffmanTable.h" // for HuffmanTable
-#include "io/BitPumpMSB.h" // for BitPumpMSB, BitStream<>::fil...
+#include "io/BitPumpMSB.h" // for BitPumpMSB, BitStream<>::f...
#include "io/Buffer.h" // for Buffer
#include "io/ByteStream.h" // for ByteStream
-#include <cstdio> // for size_t, NULL
-#include <vector> // for vector, allocator
+#include <cassert> // for assert
+#include <cstdio> // for size_t
+#include <vector> // for vector
namespace rawspeed {
-const uchar8 NikonDecompressor::nikon_tree[][2][16] = {
- {/* 12-bit lossy */
- {0, 1, 5, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0},
- {5, 4, 3, 6, 2, 7, 1, 0, 8, 9, 11, 10, 12}},
- {/* 12-bit lossy after split */
- {0, 1, 5, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0},
- {0x39, 0x5a, 0x38, 0x27, 0x16, 5, 4, 3, 2, 1, 0, 11, 12, 12}},
- {/* 12-bit lossless */
- {0, 1, 4, 2, 3, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {5, 4, 6, 3, 7, 2, 8, 1, 9, 0, 10, 11, 12}},
- {/* 14-bit lossy */
- {0, 1, 4, 3, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0},
- {5, 6, 4, 7, 8, 3, 9, 2, 1, 0, 10, 11, 12, 13, 14}},
- {/* 14-bit lossy after split */
- {0, 1, 5, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0},
- {8, 0x5c, 0x4b, 0x3a, 0x29, 7, 6, 5, 4, 3, 2, 1, 0, 13, 14}},
- {/* 14-bit lossless */
- {0, 1, 4, 2, 2, 3, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0},
- {7, 6, 8, 5, 9, 4, 10, 3, 11, 12, 2, 0, 1, 13, 14}},
+const std::array<std::array<std::array<uchar8, 16>, 2>, 6>
+ NikonDecompressor::nikon_tree = {{
+ {{/* 12-bit lossy */
+ {0, 1, 5, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0},
+ {5, 4, 3, 6, 2, 7, 1, 0, 8, 9, 11, 10, 12}}},
+ {{/* 12-bit lossy after split */
+ {0, 1, 5, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0},
+ {0x39, 0x5a, 0x38, 0x27, 0x16, 5, 4, 3, 2, 1, 0, 11, 12, 12}}},
+ {{/* 12-bit lossless */
+ {0, 1, 4, 2, 3, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {5, 4, 6, 3, 7, 2, 8, 1, 9, 0, 10, 11, 12}}},
+ {{/* 14-bit lossy */
+ {0, 1, 4, 3, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0},
+ {5, 6, 4, 7, 8, 3, 9, 2, 1, 0, 10, 11, 12, 13, 14}}},
+ {{/* 14-bit lossy after split */
+ {0, 1, 5, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0},
+ {8, 0x5c, 0x4b, 0x3a, 0x29, 7, 6, 5, 4, 3, 2, 1, 0, 13, 14}}},
+ {{/* 14-bit lossless */
+ {0, 1, 4, 2, 2, 3, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0},
+ {7, 6, 8, 5, 9, 4, 10, 3, 11, 12, 2, 0, 1, 13, 14}}},
+ }};
+
+namespace {
+
+const std::array<uint32, 32> bitMask = {
+ {0xffffffff, 0x7fffffff, 0x3fffffff, 0x1fffffff, 0x0fffffff, 0x07ffffff,
+ 0x03ffffff, 0x01ffffff, 0x00ffffff, 0x007fffff, 0x003fffff, 0x001fffff,
+ 0x000fffff, 0x0007ffff, 0x0003ffff, 0x0001ffff, 0x0000ffff, 0x00007fff,
+ 0x00003fff, 0x00001fff, 0x00000fff, 0x000007ff, 0x000003ff, 0x000001ff,
+ 0x000000ff, 0x0000007f, 0x0000003f, 0x0000001f, 0x0000000f, 0x00000007,
+ 0x00000003, 0x00000001}};
+
+class NikonLASDecompressor {
+ bool mUseBigtable = true;
+ bool mDNGCompatible = false;
+
+ struct HuffmanTable {
+ /*
+ * These two fields directly represent the contents of a JPEG DHT
+ * marker
+ */
+ std::array<uint32, 17> bits;
+ std::array<uint32, 256> huffval;
+
+ /*
+ * The remaining fields are computed from the above to allow more
+ * efficient coding and decoding. These fields should be considered
+ * private to the Huffman compression & decompression modules.
+ */
+
+ std::array<ushort16, 17> mincode;
+ std::array<int, 18> maxcode;
+ std::array<short, 17> valptr;
+ std::array<uint32, 256> numbits;
+ std::vector<int> bigTable;
+ bool initialized;
+ } dctbl1;
+
+ void createHuffmanTable() {
+ int p;
+ int i;
+ int l;
+ int lastp;
+ int si;
+ std::array<char, 257> huffsize;
+ std::array<ushort16, 257> huffcode;
+ ushort16 code;
+ int size;
+ int value;
+ int ll;
+ int ul;
+
+ /*
+ * Figure C.1: make table of Huffman code length for each symbol
+ * Note that this is in code-length order.
+ */
+ p = 0;
+ for (l = 1; l <= 16; l++) {
+ for (i = 1; i <= static_cast<int>(dctbl1.bits[l]); i++) {
+ huffsize[p++] = static_cast<char>(l);
+ if (p > 256)
+ ThrowRDE("LJpegDecompressor::createHuffmanTable: Code length too "
+ "long. Corrupt data.");
+ }
+ }
+ huffsize[p] = 0;
+ lastp = p;
+
+ /*
+ * Figure C.2: generate the codes themselves
+ * Note that this is in code-length order.
+ */
+ code = 0;
+ si = huffsize[0];
+ p = 0;
+ while (huffsize[p]) {
+ while ((static_cast<int>(huffsize[p])) == si) {
+ huffcode[p++] = code;
+ code++;
+ }
+ code <<= 1;
+ si++;
+ if (p > 256)
+ ThrowRDE("createHuffmanTable: Code length too long. Corrupt data.");
+ }
+
+ /*
+ * Figure F.15: generate decoding tables
+ */
+ dctbl1.mincode[0] = 0;
+ dctbl1.maxcode[0] = 0;
+ p = 0;
+ for (l = 1; l <= 16; l++) {
+ if (dctbl1.bits[l]) {
+ dctbl1.valptr[l] = p;
+ dctbl1.mincode[l] = huffcode[p];
+ p += dctbl1.bits[l];
+ dctbl1.maxcode[l] = huffcode[p - 1];
+ } else {
+ dctbl1.valptr[l] =
+ 0xff; // This check must be present to avoid crash on junk
+ dctbl1.maxcode[l] = -1;
+ }
+ if (p > 256)
+ ThrowRDE("createHuffmanTable: Code length too long. Corrupt data.");
+ }
+
+ /*
+ * We put in this value to ensure HuffDecode terminates.
+ */
+ dctbl1.maxcode[17] = 0xFFFFFL;
+
+ /*
+ * Build the numbits, value lookup tables.
+ * These table allow us to gather 8 bits from the bits stream,
+ * and immediately lookup the size and value of the huffman codes.
+ * If size is zero, it means that more than 8 bits are in the huffman
+ * code (this happens about 3-4% of the time).
+ */
+ dctbl1.numbits.fill(0);
+ for (p = 0; p < lastp; p++) {
+ size = huffsize[p];
+ if (size <= 8) {
+ value = dctbl1.huffval[p];
+ code = huffcode[p];
+ ll = code << (8 - size);
+ if (size < 8) {
+ ul = ll | bitMask[24 + size];
+ } else {
+ ul = ll;
+ }
+ if (ul > 256 || ll > ul)
+ ThrowRDE("createHuffmanTable: Code length too long. Corrupt data.");
+ for (i = ll; i <= ul; i++) {
+ dctbl1.numbits[i] = size | (value << 4);
+ }
+ }
+ }
+ if (mUseBigtable)
+ createBigTable();
+ dctbl1.initialized = true;
+ }
+
+ /************************************
+ * Bitable creation
+ *
+ * This is expanding the concept of fast lookups
+ *
+ * A complete table for 14 arbitrary bits will be
+ * created that enables fast lookup of number of bits used,
+ * and final delta result.
+ * Hit rate is about 90-99% for typical LJPEGS, usually about 98%
+ *
+ ************************************/
+
+ void createBigTable() {
+ const uint32 bits =
+ 14; // HuffDecode functions must be changed, if this is modified.
+ const uint32 size = 1 << bits;
+ int rv = 0;
+ int temp;
+ uint32 l;
+
+ dctbl1.bigTable.resize(size);
+ for (uint32 i = 0; i < size; i++) {
+ ushort16 input = i << 2; // Calculate input value
+ int code = input >> 8; // Get 8 bits
+ uint32 val = dctbl1.numbits[code];
+ l = val & 15;
+ if (l) {
+ rv = val >> 4;
+ } else {
+ l = 8;
+ while (code > dctbl1.maxcode[l]) {
+ temp = input >> (15 - l) & 1;
+ code = (code << 1) | temp;
+ l++;
+ }
+
+ /*
+ * With garbage input we may reach the sentinel value l = 17.
+ */
+
+ if (l > 16 || dctbl1.valptr[l] == 0xff) {
+ dctbl1.bigTable[i] = 0xff;
+ continue;
+ }
+ rv = dctbl1.huffval[dctbl1.valptr[l] + (code - dctbl1.mincode[l])];
+ }
+
+ if (rv == 16) {
+ if (mDNGCompatible)
+ dctbl1.bigTable[i] = (-(32768 << 8)) | (16 + l);
+ else
+ dctbl1.bigTable[i] = (-(32768 << 8)) | l;
+ continue;
+ }
+
+ if (rv + l > bits) {
+ dctbl1.bigTable[i] = 0xff;
+ continue;
+ }
+
+ if (rv) {
+ int x = input >> (16 - l - rv) & ((1 << rv) - 1);
+ if ((x & (1 << (rv - 1))) == 0)
+ x -= (1 << rv) - 1;
+ dctbl1.bigTable[i] =
+ static_cast<int>((static_cast<unsigned>(x) << 8) | (l + rv));
+ } else {
+ dctbl1.bigTable[i] = l;
+ }
+ }
+ }
+
+public:
+ uint32 setNCodesPerLength(const Buffer& data) {
+ uint32 acc = 0;
+ for (uint32 i = 0; i < 16; i++) {
+ dctbl1.bits[i + 1] = data[i];
+ acc += dctbl1.bits[i + 1];
+ }
+ dctbl1.bits[0] = 0;
+ return acc;
+ }
+
+ void setCodeValues(const Buffer& data) {
+ for (uint32 i = 0; i < data.getSize(); i++)
+ dctbl1.huffval[i] = data[i];
+ }
+
+ void setup(bool fullDecode_, bool fixDNGBug16_) { createHuffmanTable(); }
+
+ /*
+ *--------------------------------------------------------------
+ *
+ * HuffDecode --
+ *
+ * Taken from Figure F.16: extract next coded symbol from
+ * input stream. This should becode a macro.
+ *
+ * Results:
+ * Next coded symbol
+ *
+ * Side effects:
+ * Bitstream is parsed.
+ *
+ *--------------------------------------------------------------
+ */
+ int decodeNext(BitPumpMSB& bits) { // NOLINT: google-runtime-references
+ int rv;
+ int l;
+ int temp;
+ int code;
+ unsigned val;
+
+ bits.fill();
+ code = bits.peekBitsNoFill(14);
+ val = static_cast<unsigned>(dctbl1.bigTable[code]);
+ if ((val & 0xff) != 0xff) {
+ bits.skipBitsNoFill(val & 0xff);
+ return static_cast<int>(val) >> 8;
+ }
+ rv = 0;
+ code = bits.peekBitsNoFill(8);
+ val = dctbl1.numbits[code];
+ l = val & 15;
+ if (l) {
+ bits.skipBitsNoFill(l);
+ rv = static_cast<int>(val) >> 4;
+ } else {
+ bits.skipBits(8);
+ l = 8;
+ while (code > dctbl1.maxcode[l]) {
+ temp = bits.getBitsNoFill(1);
+ code = (code << 1) | temp;
+ l++;
+ }
+
+ if (l > 16) {
+ ThrowRDE("Corrupt JPEG data: bad Huffman code:%u\n", l);
+ } else {
+ rv = dctbl1.huffval[dctbl1.valptr[l] + (code - dctbl1.mincode[l])];
+ }
+ }
+
+ if (rv == 16)
+ return -32768;
+
+ /*
+ * Section F.2.2.1: decode the difference and
+ * Figure F.12: extend sign bit
+ */
+ uint32 len = rv & 15;
+ uint32 shl = rv >> 4;
+ int diff = ((bits.getBits(len - shl) << 1) + 1) << shl >> 1;
+ if ((diff & (1 << (len - 1))) == 0)
+ diff -= (1 << len) - !shl;
+ return diff;
+ }
};
+} // namespace
+
std::vector<ushort16> NikonDecompressor::createCurve(ByteStream* metadata,
uint32 bitsPS, uint32 v0,
uint32 v1, uint32* split) {
+ // Nikon Z7 12/14 bit compressed hack.
+ if (v0 == 68 && v1 == 64)
+ bitsPS -= 2;
+
// 'curve' will hold a peace wise linearly interpolated function.
// there are 'csize' segments, each is 'step' values long.
// the very last value is not part of the used table but necessary
@@ -73,7 +381,7 @@ std::vector<ushort16> NikonDecompressor::createCurve(ByteStream* metadata,
if (csize > 1)
step = curve.size() / (csize - 1);
- if (v0 == 68 && v1 == 32 && step > 0) {
+ if (v0 == 68 && (v1 == 32 || v1 == 64) && step > 0) {
if ((csize - 1) * step != curve.size() - 1)
ThrowRDE("Bad curve segment count (%u)", csize);
@@ -114,15 +422,18 @@ std::vector<ushort16> NikonDecompressor::createCurve(ByteStream* metadata,
return curve;
}
-HuffmanTable NikonDecompressor::createHuffmanTable(uint32 huffSelect) {
- HuffmanTable ht;
- uint32 count = ht.setNCodesPerLength(Buffer(nikon_tree[huffSelect][0], 16));
- ht.setCodeValues(Buffer(nikon_tree[huffSelect][1], count));
+template <typename Huffman>
+Huffman NikonDecompressor::createHuffmanTable(uint32 huffSelect) {
+ Huffman ht;
+ uint32 count =
+ ht.setNCodesPerLength(Buffer(nikon_tree[huffSelect][0].data(), 16));
+ ht.setCodeValues(Buffer(nikon_tree[huffSelect][1].data(), count));
ht.setup(true, false);
return ht;
}
-NikonDecompressor::NikonDecompressor(const RawImage& raw, uint32 bitsPS_)
+NikonDecompressor::NikonDecompressor(const RawImage& raw, ByteStream metadata,
+ uint32 bitsPS_)
: mRaw(raw), bitsPS(bitsPS_) {
if (mRaw->getCpp() != 1 || mRaw->getDataType() != TYPE_USHORT16 ||
mRaw->getBpp() != 2)
@@ -140,18 +451,9 @@ NikonDecompressor::NikonDecompressor(const RawImage& raw, uint32 bitsPS_)
default:
ThrowRDE("Invalid bpp found: %u", bitsPS);
}
-}
-
-void NikonDecompressor::decompress(ByteStream metadata, const ByteStream& data,
- bool uncorrectedRawValues) {
- const iPoint2D& size = mRaw->dim;
uint32 v0 = metadata.getByte();
uint32 v1 = metadata.getByte();
- uint32 huffSelect = 0;
- uint32 split = 0;
- int pUp1[2];
- int pUp2[2];
writeLog(DEBUG_PRIO_EXTRA, "Nef version v0:%u, v1:%u", v0, v1);
@@ -168,33 +470,36 @@ void NikonDecompressor::decompress(ByteStream metadata, const ByteStream& data,
pUp2[0] = metadata.getU16();
pUp2[1] = metadata.getU16();
- HuffmanTable ht = createHuffmanTable(huffSelect);
+ curve = createCurve(&metadata, bitsPS, v0, v1, &split);
- auto curve = createCurve(&metadata, bitsPS, v0, v1, &split);
- RawImageCurveGuard curveHandler(&mRaw, curve, uncorrectedRawValues);
+ // If the 'split' happens outside of the image, it does not actually happen.
+ if (split >= static_cast<unsigned>(mRaw->dim.y))
+ split = 0;
+}
+
+template <typename Huffman>
+void NikonDecompressor::decompress(BitPumpMSB* bits, int start_y, int end_y) {
+ Huffman ht = createHuffmanTable<Huffman>(huffSelect);
- BitPumpMSB bits(data);
uchar8* draw = mRaw->getData();
uint32 pitch = mRaw->pitch;
int pLeft1 = 0;
int pLeft2 = 0;
- uint32 random = bits.peekBits(24);
- //allow gcc to devirtualize the calls below
+
+ // allow gcc to devirtualize the calls below
auto* rawdata = reinterpret_cast<RawImageDataU16*>(mRaw.get());
+ const iPoint2D& size = mRaw->dim;
assert(size.x % 2 == 0);
assert(size.x >= 2);
- for (uint32 y = 0; y < static_cast<unsigned>(size.y); y++) {
- if (split && y == split) {
- ht = createHuffmanTable(huffSelect + 1);
- }
+ for (uint32 y = start_y; y < static_cast<uint32>(end_y); y++) {
auto* dest =
reinterpret_cast<ushort16*>(&draw[y * pitch]); // Adjust destination
- pUp1[y&1] += ht.decodeNext(bits);
- pUp2[y&1] += ht.decodeNext(bits);
- pLeft1 = pUp1[y&1];
- pLeft2 = pUp2[y&1];
+ pUp1[y & 1] += ht.decodeNext(*bits);
+ pUp2[y & 1] += ht.decodeNext(*bits);
+ pLeft1 = pUp1[y & 1];
+ pLeft2 = pUp2[y & 1];
rawdata->setWithLookUp(clampBits(pLeft1, 15),
reinterpret_cast<uchar8*>(dest + 0), &random);
@@ -204,8 +509,8 @@ void NikonDecompressor::decompress(ByteStream metadata, const ByteStream& data,
dest += 2;
for (uint32 x = 2; x < static_cast<uint32>(size.x); x += 2) {
- pLeft1 += ht.decodeNext(bits);
- pLeft2 += ht.decodeNext(bits);
+ pLeft1 += ht.decodeNext(*bits);
+ pLeft2 += ht.decodeNext(*bits);
rawdata->setWithLookUp(clampBits(pLeft1, 15),
reinterpret_cast<uchar8*>(dest + 0), &random);
@@ -217,4 +522,23 @@ void NikonDecompressor::decompress(ByteStream metadata, const ByteStream& data,
}
}
+void NikonDecompressor::decompress(const ByteStream& data,
+ bool uncorrectedRawValues) {
+ RawImageCurveGuard curveHandler(&mRaw, curve, uncorrectedRawValues);
+
+ BitPumpMSB bits(data);
+
+ random = bits.peekBits(24);
+
+ assert(split == 0 || split < static_cast<unsigned>(mRaw->dim.y));
+
+ if (!split) {
+ decompress<HuffmanTable>(&bits, 0, mRaw->dim.y);
+ } else {
+ decompress<HuffmanTable>(&bits, 0, split);
+ huffSelect += 1;
+ decompress<NikonLASDecompressor>(&bits, split, mRaw->dim.y);
+ }
+}
+
} // namespace rawspeed
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/NikonDecompressor.h b/src/external/rawspeed/src/librawspeed/decompressors/NikonDecompressor.h
index 6fde227a5..cfa1bb0e5 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/NikonDecompressor.h
+++ b/src/external/rawspeed/src/librawspeed/decompressors/NikonDecompressor.h
@@ -20,36 +20,45 @@
#pragma once
-#include "common/Common.h" // for uint32
+#include "common/Common.h" // for uint32, ushort16
#include "common/RawImage.h" // for RawImage
#include "decompressors/AbstractDecompressor.h" // for AbstractDecompressor
+#include "io/BitPumpMSB.h" // for BitPumpMSB
#include <vector> // for vector
namespace rawspeed {
-class iPoint2D;
-
-class RawImage;
-
class ByteStream;
-class HuffmanTable;
-
class NikonDecompressor final : public AbstractDecompressor {
RawImage mRaw;
uint32 bitsPS;
+ uint32 huffSelect = 0;
+ uint32 split = 0;
+
+ std::array<int, 2> pUp1;
+ std::array<int, 2> pUp2;
+
+ std::vector<ushort16> curve;
+
+ uint32 random;
+
public:
- NikonDecompressor(const RawImage& raw, uint32 bitsPS);
+ NikonDecompressor(const RawImage& raw, ByteStream metadata, uint32 bitsPS);
- void decompress(ByteStream metadata, const ByteStream& data,
- bool uncorrectedRawValues);
+ void decompress(const ByteStream& data, bool uncorrectedRawValues);
private:
- static const uchar8 nikon_tree[][2][16];
+ static const std::array<std::array<std::array<uchar8, 16>, 2>, 6> nikon_tree;
static std::vector<ushort16> createCurve(ByteStream* metadata, uint32 bitsPS,
uint32 v0, uint32 v1, uint32* split);
- static HuffmanTable createHuffmanTable(uint32 huffSelect);
+
+ template <typename Huffman>
+ void decompress(BitPumpMSB* bits, int start_y, int end_y);
+
+ template <typename Huffman>
+ static Huffman createHuffmanTable(uint32 huffSelect);
};
} // namespace rawspeed
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/OlympusDecompressor.cpp b/src/external/rawspeed/src/librawspeed/decompressors/OlympusDecompressor.cpp
index 3a8cc3399..5f6ceb680 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/OlympusDecompressor.cpp
+++ b/src/external/rawspeed/src/librawspeed/decompressors/OlympusDecompressor.cpp
@@ -21,20 +21,19 @@
*/
#include "decompressors/OlympusDecompressor.h"
-#include "common/Common.h" // for uchar8
-#include "common/Point.h" // for iPoint2D
-#include "common/RawImage.h" // for RawImage
-#include "decoders/RawDecoderException.h" // for ThrowRDE
-#include "decompressors/AbstractDecompressor.h" // for RawDecom...
-#include "decompressors/HuffmanTable.h" // for HuffmanTable
-#include "io/BitPumpMSB.h" // for BitPumpMSB
-#include <algorithm> // for move
-#include <algorithm> // for min
-#include <array> // for array
-#include <cmath> // for signbit
-#include <cstdlib> // for abs
-#include <memory> // for unique_ptr
-#include <type_traits> // for enable_if, is_integer
+#include "common/Common.h" // for uint32, ushort16, uchar8
+#include "common/Point.h" // for iPoint2D
+#include "common/RawImage.h" // for RawImage, RawImageData
+#include "decoders/RawDecoderException.h" // for ThrowRDE
+#include "io/BitPumpMSB.h" // for BitPumpMSB
+#include "io/ByteStream.h" // for ByteStream
+#include <algorithm> // for min
+#include <array> // for array, array<>::value_type
+#include <cassert> // for assert
+#include <cmath> // for abs
+#include <cstdlib> // for abs
+#include <memory> // for unique_ptr
+#include <type_traits> // for enable_if_t, is_integral
namespace {
@@ -90,7 +89,7 @@ void OlympusDecompressor::decompress(ByteStream input) const {
int pitch = mRaw->pitch;
/* Build a table to quickly look up "high" value */
- std::unique_ptr<char[]> bittable(new char[4096]);
+ std::unique_ptr<char[]> bittable(new char[4096]); // NOLINT
for (i = 0; i < 4096; i++) {
int b = i;
@@ -146,9 +145,10 @@ void OlympusDecompressor::decompress(ByteStream input) const {
nw[c] = pred;
}
}
- dest[x] = pred + ((diff * 4) | low);
// Set predictor
- left[c] = dest[x];
+ left[c] = pred + ((diff * 4) | low);
+ // Set the pixel
+ dest[x] = left[c];
} else {
// Have local variables for values used several tiles
// (having a "ushort16 *dst_up" that caches dest[-pitch+((int)x)] is
@@ -166,10 +166,11 @@ void OlympusDecompressor::decompress(ByteStream input) const {
} else
pred = std::abs(leftMinusNw) > std::abs(upMinusNw) ? left[c] : up;
- dest[x] = pred + ((diff * 4) | low);
// Set predictors
- left[c] = dest[x];
+ left[c] = pred + ((diff * 4) | low);
nw[c] = up;
+ // Set the pixel
+ dest[x] = left[c];
}
// ODD PIXELS
@@ -208,7 +209,10 @@ void OlympusDecompressor::decompress(ByteStream input) const {
nw[c] = pred;
}
}
- dest[x] = left[c] = pred + ((diff * 4) | low);
+ // Set predictor
+ left[c] = pred + ((diff * 4) | low);
+ // Set the pixel
+ dest[x] = left[c];
} else {
int up = dest[-pitch + (static_cast<int>(x))];
int leftMinusNw = left[c] - nw[c];
@@ -224,8 +228,11 @@ void OlympusDecompressor::decompress(ByteStream input) const {
} else
pred = std::abs(leftMinusNw) > std::abs(upMinusNw) ? left[c] : up;
- dest[x] = left[c] = pred + ((diff * 4) | low);
+ // Set predictors
+ left[c] = pred + ((diff * 4) | low);
nw[c] = up;
+ // Set the pixel
+ dest[x] = left[c];
}
border = y_border;
}
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/OlympusDecompressor.h b/src/external/rawspeed/src/librawspeed/decompressors/OlympusDecompressor.h
index bb9ebc1b6..c52561394 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/OlympusDecompressor.h
+++ b/src/external/rawspeed/src/librawspeed/decompressors/OlympusDecompressor.h
@@ -22,11 +22,10 @@
#include "common/RawImage.h" // for RawImage
#include "decompressors/AbstractDecompressor.h" // for AbstractDecompressor
-#include "io/ByteStream.h" // for ByteStream
namespace rawspeed {
-class RawImage;
+class ByteStream;
class OlympusDecompressor final : public AbstractDecompressor {
RawImage mRaw;
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/PanasonicDecompressor.cpp b/src/external/rawspeed/src/librawspeed/decompressors/PanasonicDecompressor.cpp
index c7c982f13..a1dd4cd34 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/PanasonicDecompressor.cpp
+++ b/src/external/rawspeed/src/librawspeed/decompressors/PanasonicDecompressor.cpp
@@ -3,7 +3,7 @@
Copyright (C) 2009-2014 Klaus Post
Copyright (C) 2014 Pedro Côrte-Real
- Copyright (C) 2017 Roman Lebedev
+ Copyright (C) 2017-2018 Roman Lebedev
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -21,153 +21,230 @@
*/
#include "decompressors/PanasonicDecompressor.h"
-#include "common/Mutex.h" // for MutexLocker
-#include "common/Point.h" // for iPoint2D
-#include "common/RawImage.h" // for RawImage, RawImageData
-#include <algorithm> // for min, move
-#include <cstring> // for memcpy
-#include <vector> // for vector
+#include "common/Mutex.h" // for MutexLocker
+#include "common/Point.h" // for iPoint2D
+#include "common/RawImage.h" // for RawImage, RawImageData
+#include "decoders/RawDecoderException.h" // for ThrowRDE
+#include "io/Buffer.h" // for Buffer, Buffer::size_type
+#include <algorithm> // for generate_n, min
+#include <array> // for array
+#include <cassert> // for assert
+#include <cstddef> // for size_t
+#include <iterator> // for back_insert_iterator, back...
+#include <limits> // for numeric_limits
+#include <memory> // for allocator_traits<>::value_...
+#include <utility> // for move
+#include <vector> // for vector
namespace rawspeed {
+constexpr uint32 PanasonicDecompressor::BlockSize;
+
PanasonicDecompressor::PanasonicDecompressor(const RawImage& img,
const ByteStream& input_,
bool zero_is_not_bad,
- uint32 load_flags_)
+ uint32 section_split_offset_)
: AbstractParallelizedDecompressor(img), zero_is_bad(!zero_is_not_bad),
- load_flags(load_flags_) {
+ section_split_offset(section_split_offset_) {
if (mRaw->getCpp() != 1 || mRaw->getDataType() != TYPE_USHORT16 ||
mRaw->getBpp() != 2)
ThrowRDE("Unexpected component count / data type");
- if (!mRaw->dim.hasPositiveArea() || mRaw->dim.x % 14 != 0) {
+ if (!mRaw->dim.hasPositiveArea() || mRaw->dim.x % PixelsPerPacket != 0) {
ThrowRDE("Unexpected image dimensions found: (%i; %i)", mRaw->dim.x,
mRaw->dim.y);
}
- /*
- * Normally, we would check the image dimensions against some hardcoded
- * threshold. That is being done as poor man's attempt to catch
- * obviously-invalid raws, and avoid OOM's during fuzzing. However, there is
- * a better solution - actually check the size of input buffer to try and
- * guess whether the image size is valid or not. And in this case, we can do
- * that, because the compression rate is static and known.
- */
- // if (width > 5488 || height > 3912)
- // ThrowRDE("Too large image size: (%u; %u)", width, height);
-
- if (BufSize < load_flags)
- ThrowRDE("Bad load_flags: %u, less than BufSize (%u)", load_flags, BufSize);
+ if (BlockSize < section_split_offset)
+ ThrowRDE("Bad section_split_offset: %u, less than BlockSize (%u)",
+ section_split_offset, BlockSize);
// Naive count of bytes that given pixel count requires.
- // Do division first, because we know the remainder is always zero,
- // and the next multiplication won't overflow.
- assert(mRaw->dim.area() % 7ULL == 0ULL);
- const auto rawBytesNormal = (mRaw->dim.area() / 7ULL) * 8ULL;
- // If load_flags is zero, than that size is the size we need to read.
- // But if it is not, then we need to round up to multiple of BufSize, because
- // of splitting&rotation of each BufSize's slice in half at load_flags bytes.
+ assert(mRaw->dim.area() % PixelsPerPacket == 0);
+ const auto bytesTotal = (mRaw->dim.area() / PixelsPerPacket) * BytesPerPacket;
+ assert(bytesTotal > 0);
+
+ // If section_split_offset is zero, then that we need to read the normal
+ // amount of bytes. But if it is not, then we need to round up to multiple of
+ // BlockSize, because of splitting&rotation of each BlockSize's slice in half
+ // at section_split_offset bytes.
const auto bufSize =
- load_flags == 0 ? rawBytesNormal : roundUp(rawBytesNormal, BufSize);
+ section_split_offset == 0 ? bytesTotal : roundUp(bytesTotal, BlockSize);
+
+ if (bufSize > std::numeric_limits<ByteStream::size_type>::max())
+ ThrowRDE("Raw dimensions require input buffer larger than supported");
+
input = input_.peekStream(bufSize);
+
+ chopInputIntoBlocks();
}
-struct PanasonicDecompressor::PanaBitpump {
- ByteStream input;
+void PanasonicDecompressor::chopInputIntoBlocks() {
+ auto pixelToCoordinate = [width = mRaw->dim.x](unsigned pixel) -> iPoint2D {
+ return iPoint2D(pixel % width, pixel / width);
+ };
+
+ // If section_split_offset == 0, last block may not be full.
+ const auto blocksTotal = roundUpDivision(input.getRemainSize(), BlockSize);
+ assert(blocksTotal > 0);
+ assert(blocksTotal * PixelsPerBlock >= mRaw->dim.area());
+ blocks.reserve(blocksTotal);
+
+ unsigned currPixel = 0;
+ std::generate_n(std::back_inserter(blocks), blocksTotal,
+ [input = &input, &currPixel, pixelToCoordinate]() -> Block {
+ assert(input->getRemainSize() != 0);
+ const auto blockSize =
+ std::min(input->getRemainSize(), BlockSize);
+ assert(blockSize > 0);
+ assert(blockSize % BytesPerPacket == 0);
+ const auto packets = blockSize / BytesPerPacket;
+ assert(packets > 0);
+ const auto pixels = packets * PixelsPerPacket;
+ assert(pixels > 0);
+
+ ByteStream bs = input->getStream(blockSize);
+ iPoint2D beginCoord = pixelToCoordinate(currPixel);
+ currPixel += pixels;
+ iPoint2D endCoord = pixelToCoordinate(currPixel);
+ return {std::move(bs), beginCoord, endCoord};
+ });
+ assert(blocks.size() == blocksTotal);
+ assert(currPixel >= mRaw->dim.area());
+ assert(input.getRemainSize() == 0);
+
+ // Clamp the end coordinate for the last block.
+ blocks.back().endCoord = mRaw->dim;
+ blocks.back().endCoord.y -= 1;
+}
+
+class PanasonicDecompressor::ProxyStream {
+ ByteStream block;
+ const uint32 section_split_offset;
std::vector<uchar8> buf;
+
int vbits = 0;
- uint32 load_flags;
- PanaBitpump(ByteStream input_, int load_flags_)
- : input(std::move(input_)), load_flags(load_flags_) {
+ void parseBlock() {
+ assert(buf.empty());
+ assert(block.getRemainSize() <= BlockSize);
+ assert(section_split_offset <= BlockSize);
+
+ Buffer FirstSection = block.getBuffer(section_split_offset);
+ Buffer SecondSection = block.getBuffer(block.getRemainSize());
+
+ // get one more byte, so the return statement of getBits does not have
+ // to special case for accessing the last byte
+ buf.reserve(BlockSize + 1UL);
+
+ // First copy the second section. This makes it the first section.
+ buf.insert(buf.end(), SecondSection.begin(), SecondSection.end());
+ // Now append the original 1'st section right after the new 1'st section.
+ buf.insert(buf.end(), FirstSection.begin(), FirstSection.end());
+
+ assert(block.getRemainSize() == 0);
+
// get one more byte, so the return statement of getBits does not have
// to special case for accessing the last byte
- buf.resize(BufSize + 1UL);
+ buf.emplace_back(0);
}
- void skipBytes(int bytes) {
- int blocks = (bytes / BufSize) * BufSize;
- input.skipBytes(blocks);
- for (int i = blocks; i < bytes; i++)
- (void)getBits(8);
+public:
+ ProxyStream(ByteStream block_, int section_split_offset_)
+ : block(std::move(block_)), section_split_offset(section_split_offset_) {
+ parseBlock();
}
uint32 getBits(int nbits) {
- if (!vbits) {
- /* On truncated files this routine will just return just for the truncated
- * part of the file. Since there is no chance of affecting output buffer
- * size we allow the decoder to decode this
- */
- assert(BufSize >= load_flags);
- auto size = std::min(input.getRemainSize(), BufSize - load_flags);
- memcpy(buf.data() + load_flags, input.getData(size), size);
-
- size = std::min(input.getRemainSize(), load_flags);
- if (size != 0)
- memcpy(buf.data(), input.getData(size), size);
- }
vbits = (vbits - nbits) & 0x1ffff;
int byte = vbits >> 3 ^ 0x3ff0;
return (buf[byte] | buf[byte + 1UL] << 8) >> (vbits & 7) & ~(-(1 << nbits));
}
};
-void PanasonicDecompressor::decompressThreaded(
- const RawDecompressorThread* t) const {
- PanaBitpump bits(input, load_flags);
+void PanasonicDecompressor::processPixelPacket(
+ ProxyStream* bits, int y, ushort16* dest, int xbegin,
+ std::vector<uint32>* zero_pos) const {
+ int sh = 0;
- /* 9 + 1/7 bits per pixel */
- bits.skipBytes(8 * mRaw->dim.x * t->start / 7);
+ std::array<int, 2> pred;
+ pred.fill(0);
- assert(mRaw->dim.x % 14 == 0);
- const auto blocks = mRaw->dim.x / 14;
+ std::array<int, 2> nonz;
+ nonz.fill(0);
- std::vector<uint32> zero_pos;
- for (uint32 y = t->start; y < t->end; y++) {
- int sh = 0;
-
- auto* dest = reinterpret_cast<ushort16*>(mRaw->getData(0, y));
- for (int block = 0; block < blocks; block++) {
- std::array<int, 2> pred;
- pred.fill(0);
-
- std::array<int, 2> nonz;
- nonz.fill(0);
-
- int u = 0;
-
- for (int x = 0; x < 14; x++) {
- const int c = x & 1;
-
- if (u == 2) {
- sh = 4 >> (3 - bits.getBits(2));
- u = -1;
- }
-
- if (nonz[c]) {
- int j = bits.getBits(8);
- if (j) {
- pred[c] -= 0x80 << sh;
- if (pred[c] < 0 || sh == 4)
- pred[c] &= ~(-(1 << sh));
- pred[c] += j << sh;
- }
- } else {
- nonz[c] = bits.getBits(8);
- if (nonz[c] || x > 11)
- pred[c] = nonz[c] << 4 | bits.getBits(4);
- }
-
- *dest = pred[c];
-
- if (zero_is_bad && 0 == pred[c])
- zero_pos.push_back((y << 16) | (14 * block + x));
-
- u++;
- dest++;
+ int u = 0;
+
+ for (int p = 0; p < PixelsPerPacket; p++) {
+ const int c = p & 1;
+
+ if (u == 2) {
+ sh = 4 >> (3 - bits->getBits(2));
+ u = -1;
+ }
+
+ if (nonz[c]) {
+ int j = bits->getBits(8);
+ if (j) {
+ pred[c] -= 0x80 << sh;
+ if (pred[c] < 0 || sh == 4)
+ pred[c] &= ~(-(1 << sh));
+ pred[c] += j << sh;
}
+ } else {
+ nonz[c] = bits->getBits(8);
+ if (nonz[c] || p > 11)
+ pred[c] = nonz[c] << 4 | bits->getBits(4);
+ }
+
+ *dest = pred[c];
+
+ if (zero_is_bad && 0 == pred[c])
+ zero_pos->push_back((y << 16) | (xbegin + p));
+
+ u++;
+ dest++;
+ }
+}
+
+void PanasonicDecompressor::processBlock(const Block& block,
+ std::vector<uint32>* zero_pos) const {
+ ProxyStream bits(block.bs, section_split_offset);
+
+ for (int y = block.beginCoord.y; y <= block.endCoord.y; y++) {
+ int x = 0;
+ // First row may not begin at the first column.
+ if (block.beginCoord.y == y)
+ x = block.beginCoord.x;
+
+ int endx = mRaw->dim.x;
+ // Last row may end before the last column.
+ if (block.endCoord.y == y)
+ endx = block.endCoord.x;
+
+ auto* dest = reinterpret_cast<ushort16*>(mRaw->getData(x, y));
+
+ assert(x % PixelsPerPacket == 0);
+ assert(endx % PixelsPerPacket == 0);
+
+ for (; x < endx;) {
+ processPixelPacket(&bits, y, dest, x, zero_pos);
+
+ x += PixelsPerPacket;
+ dest += PixelsPerPacket;
}
}
+}
+
+void PanasonicDecompressor::decompressThreaded(
+ const RawDecompressorThread* t) const {
+ std::vector<uint32> zero_pos;
+
+ assert(!blocks.empty());
+ assert(t->start < t->end);
+ assert(t->end <= blocks.size());
+ for (size_t i = t->start; i < t->end; i++)
+ processBlock(blocks[i], &zero_pos);
if (zero_is_bad && !zero_pos.empty()) {
MutexLocker guard(&mRaw->mBadPixelMutex);
@@ -176,4 +253,9 @@ void PanasonicDecompressor::decompressThreaded(
}
}
+void PanasonicDecompressor::decompress() const {
+ assert(!blocks.empty());
+ startThreading(blocks.size());
+}
+
} // namespace rawspeed
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/PanasonicDecompressor.h b/src/external/rawspeed/src/librawspeed/decompressors/PanasonicDecompressor.h
index 27480d489..68ef1f020 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/PanasonicDecompressor.h
+++ b/src/external/rawspeed/src/librawspeed/decompressors/PanasonicDecompressor.h
@@ -1,7 +1,7 @@
/*
RawSpeed - RAW file decoder.
- Copyright (C) 2017 Roman Lebedev
+ Copyright (C) 2017-2018 Roman Lebedev
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -21,33 +21,70 @@
#pragma once
#include "common/Common.h" // for uint32
+#include "common/Point.h" // for iPoint2D
#include "decompressors/AbstractParallelizedDecompressor.h" // for Abstract...
#include "io/ByteStream.h" // for ByteStream
+#include <utility> // for move
+#include <vector> // for vector
namespace rawspeed {
class RawImage;
class PanasonicDecompressor final : public AbstractParallelizedDecompressor {
- static constexpr uint32 BufSize = 0x4000;
- struct PanaBitpump;
+ static constexpr uint32 BlockSize = 0x4000;
- void decompressThreaded(const RawDecompressorThread* t) const final;
+ static constexpr int PixelsPerPacket = 14;
+
+ static constexpr uint32 BytesPerPacket = 16;
+
+ static constexpr uint32 PacketsPerBlock = BlockSize / BytesPerPacket;
+
+ static constexpr uint32 PixelsPerBlock = PixelsPerPacket * PacketsPerBlock;
+
+ class ProxyStream;
ByteStream input;
bool zero_is_bad;
// The RW2 raw image buffer is split into sections of BufSize bytes.
- // If load_flags is 0, then last section is not nessesairly full.
- // If load_flags is not 0, then each section has two parts:
- // bytes: [0..load_flags-1][load_flags..BufSize-1]
+ // If section_split_offset is 0, then the last section is not neccesarily
+ // full. If section_split_offset is not 0, then each section has two parts:
+ // bytes: [0..section_split_offset-1][section_split_offset..BufSize-1]
// pixels: [a..b][0..a-1]
// I.e. these two parts need to be swapped around.
- uint32 load_flags;
+ uint32 section_split_offset;
+
+ struct Block {
+ ByteStream bs;
+ iPoint2D beginCoord;
+ // The rectangle is an incorrect representation. All the rows
+ // between the first and last one span the entire width of the image.
+ iPoint2D endCoord;
+
+ Block() = default;
+ Block(ByteStream&& bs_, iPoint2D beginCoord_, iPoint2D endCoord_)
+ : bs(std::move(bs_)), beginCoord(beginCoord_), endCoord(endCoord_) {}
+ };
+
+ // If really wanted, this vector could be avoided,
+ // and each Block computed on-the-fly
+ std::vector<Block> blocks;
+
+ void chopInputIntoBlocks();
+
+ void processPixelPacket(ProxyStream* bits, int y, ushort16* dest, int xbegin,
+ std::vector<uint32>* zero_pos) const;
+
+ void processBlock(const Block& block, std::vector<uint32>* zero_pos) const;
+
+ void decompressThreaded(const RawDecompressorThread* t) const final;
public:
PanasonicDecompressor(const RawImage& img, const ByteStream& input_,
- bool zero_is_not_bad, uint32 load_flags_);
+ bool zero_is_not_bad, uint32 section_split_offset_);
+
+ void decompress() const final;
};
} // namespace rawspeed
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/PanasonicDecompressorV5.cpp b/src/external/rawspeed/src/librawspeed/decompressors/PanasonicDecompressorV5.cpp
new file mode 100644
index 000000000..a1518a545
--- /dev/null
+++ b/src/external/rawspeed/src/librawspeed/decompressors/PanasonicDecompressorV5.cpp
@@ -0,0 +1,255 @@
+/*
+ RawSpeed - RAW file decoder.
+
+ Copyright (C) 2018 Alexey Danilchenko
+ Copyright (C) 2018 Stefan Hoffmeister
+ Copyright (C) 2018 Roman Lebedev
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "decompressors/PanasonicDecompressorV5.h"
+#include "common/Point.h" // for iPoint2D
+#include "common/RawImage.h" // for RawImage, RawImageData
+#include "decoders/RawDecoderException.h" // for ThrowRDE
+#include "io/BitPumpLSB.h" // for BitPumpLSB
+#include "io/Buffer.h" // for Buffer, DataBuffer
+#include <algorithm> // for generate_n
+#include <cassert> // for assert
+#include <iterator> // for back_insert_iterator, back...
+#include <memory> // for allocator_traits<>::value_...
+#include <utility> // for move
+#include <vector> // for vector
+
+namespace rawspeed {
+
+struct PanasonicDecompressorV5::PacketDsc {
+ int bps;
+ int pixelsPerPacket;
+
+ constexpr PacketDsc();
+ explicit constexpr PacketDsc(int bps_)
+ : bps(bps_),
+ pixelsPerPacket(PanasonicDecompressorV5::bitsPerPacket / bps) {
+ // NOTE: the division is truncating. There may be some padding bits left.
+ }
+};
+
+constexpr PanasonicDecompressorV5::PacketDsc
+ PanasonicDecompressorV5::TwelveBitPacket =
+ PanasonicDecompressorV5::PacketDsc(/*bps=*/12);
+constexpr PanasonicDecompressorV5::PacketDsc
+ PanasonicDecompressorV5::FourteenBitPacket =
+ PanasonicDecompressorV5::PacketDsc(/*bps=*/14);
+
+PanasonicDecompressorV5::PanasonicDecompressorV5(const RawImage& img,
+ const ByteStream& input_,
+ uint32 bps_)
+ : AbstractParallelizedDecompressor(img), bps(bps_) {
+ if (mRaw->getCpp() != 1 || mRaw->getDataType() != TYPE_USHORT16 ||
+ mRaw->getBpp() != 2)
+ ThrowRDE("Unexpected component count / data type");
+
+ const PacketDsc* dsc = nullptr;
+ switch (bps) {
+ case 12:
+ dsc = &TwelveBitPacket;
+ break;
+ case 14:
+ dsc = &FourteenBitPacket;
+ break;
+ default:
+ ThrowRDE("Unsupported bps: %u", bps);
+ }
+
+ if (!mRaw->dim.hasPositiveArea() || mRaw->dim.x % dsc->pixelsPerPacket != 0) {
+ ThrowRDE("Unexpected image dimensions found: (%i; %i)", mRaw->dim.x,
+ mRaw->dim.y);
+ }
+
+ // How many pixel packets does the specified pixel count require?
+ assert(mRaw->dim.area() % dsc->pixelsPerPacket == 0);
+ const auto numPackets = mRaw->dim.area() / dsc->pixelsPerPacket;
+ assert(numPackets > 0);
+
+ // And how many blocks that would be? Last block may not be full, pad it.
+ numBlocks = roundUpDivision(numPackets, PacketsPerBlock);
+ assert(numBlocks > 0);
+
+ // How many full blocks does the input contain? This is truncating division.
+ const auto haveBlocks = input_.getRemainSize() / BlockSize;
+
+ // Does the input contain enough blocks?
+ if (haveBlocks < numBlocks)
+ ThrowRDE("Unsufficient count of input blocks for a given image");
+
+ // We only want those blocks we need, no extras.
+ input = input_.peekStream(numBlocks, BlockSize);
+
+ chopInputIntoBlocks(*dsc);
+}
+
+void PanasonicDecompressorV5::chopInputIntoBlocks(const PacketDsc& dsc) {
+ auto pixelToCoordinate = [width = mRaw->dim.x](unsigned pixel) -> iPoint2D {
+ return iPoint2D(pixel % width, pixel / width);
+ };
+
+ assert(numBlocks * BlockSize == input.getRemainSize());
+ blocks.reserve(numBlocks);
+
+ const auto pixelsPerBlock = dsc.pixelsPerPacket * PacketsPerBlock;
+ assert((numBlocks - 1U) * pixelsPerBlock < mRaw->dim.area());
+ assert(numBlocks * pixelsPerBlock >= mRaw->dim.area());
+
+ unsigned currPixel = 0;
+ std::generate_n(std::back_inserter(blocks), numBlocks,
+ [input = &input, &currPixel, pixelToCoordinate,
+ pixelsPerBlock]() -> Block {
+ ByteStream bs = input->getStream(BlockSize);
+ iPoint2D beginCoord = pixelToCoordinate(currPixel);
+ currPixel += pixelsPerBlock;
+ iPoint2D endCoord = pixelToCoordinate(currPixel);
+ return {std::move(bs), beginCoord, endCoord};
+ });
+ assert(blocks.size() == numBlocks);
+ assert(currPixel >= mRaw->dim.area());
+ assert(input.getRemainSize() == 0);
+
+ // Clamp the end coordinate for the last block.
+ blocks.back().endCoord = mRaw->dim;
+ blocks.back().endCoord.y -= 1;
+}
+
+class PanasonicDecompressorV5::ProxyStream {
+ ByteStream block;
+ std::vector<uchar8> buf;
+ ByteStream input;
+
+ void parseBlock() {
+ assert(buf.empty());
+ assert(block.getRemainSize() == BlockSize);
+
+ static_assert(BlockSize > sectionSplitOffset, "");
+
+ Buffer FirstSection = block.getBuffer(sectionSplitOffset);
+ Buffer SecondSection = block.getBuffer(block.getRemainSize());
+ assert(FirstSection.getSize() < SecondSection.getSize());
+
+ buf.reserve(BlockSize);
+
+ // First copy the second section. This makes it the first section.
+ buf.insert(buf.end(), SecondSection.begin(), SecondSection.end());
+ // Now append the original 1'st section right after the new 1'st section.
+ buf.insert(buf.end(), FirstSection.begin(), FirstSection.end());
+
+ assert(buf.size() == BlockSize);
+ assert(block.getRemainSize() == 0);
+
+ // And reset the clock.
+ input = ByteStream(DataBuffer(Buffer(buf.data(), buf.size())));
+ // input.setByteOrder(Endianness::big); // does not seem to matter?!
+ }
+
+public:
+ explicit ProxyStream(ByteStream block_) : block(std::move(block_)) {}
+
+ ByteStream& getStream() {
+ parseBlock();
+ return input;
+ }
+};
+
+template <const PanasonicDecompressorV5::PacketDsc& dsc>
+void PanasonicDecompressorV5::processPixelPacket(BitPumpLSB* bs,
+ ushort16* dest) const {
+ static_assert(dsc.pixelsPerPacket > 0, "dsc should be compile-time const");
+ static_assert(dsc.bps > 0 && dsc.bps <= 16, "");
+
+ assert(bs->getFillLevel() == 0);
+
+ const ushort16* const endDest = dest + dsc.pixelsPerPacket;
+ for (; dest != endDest;) {
+ bs->fill();
+ for (; bs->getFillLevel() >= dsc.bps; dest++) {
+ assert(dest != endDest);
+
+ *dest = bs->getBitsNoFill(dsc.bps);
+ }
+ }
+ bs->skipBitsNoFill(bs->getFillLevel()); // get rid of padding.
+}
+
+template <const PanasonicDecompressorV5::PacketDsc& dsc>
+void PanasonicDecompressorV5::processBlock(const Block& block) const {
+ static_assert(dsc.pixelsPerPacket > 0, "dsc should be compile-time const");
+ static_assert(BlockSize % bytesPerPacket == 0, "");
+
+ ProxyStream proxy(block.bs);
+ BitPumpLSB bs(proxy.getStream());
+
+ for (int y = block.beginCoord.y; y <= block.endCoord.y; y++) {
+ int x = 0;
+ // First row may not begin at the first column.
+ if (block.beginCoord.y == y)
+ x = block.beginCoord.x;
+
+ int endx = mRaw->dim.x;
+ // Last row may end before the last column.
+ if (block.endCoord.y == y)
+ endx = block.endCoord.x;
+
+ auto* dest = reinterpret_cast<ushort16*>(mRaw->getData(x, y));
+
+ assert(x % dsc.pixelsPerPacket == 0);
+ assert(endx % dsc.pixelsPerPacket == 0);
+
+ for (; x < endx;) {
+ processPixelPacket<dsc>(&bs, dest);
+
+ x += dsc.pixelsPerPacket;
+ dest += dsc.pixelsPerPacket;
+ }
+ }
+}
+
+template <const PanasonicDecompressorV5::PacketDsc& dsc>
+void PanasonicDecompressorV5::decompressThreadedInternal(
+ const RawDecompressorThread* t) const {
+ assert(t->start < t->end);
+ assert(t->end <= blocks.size());
+ for (size_t i = t->start; i < t->end; i++)
+ processBlock<dsc>(blocks[i]);
+}
+
+void PanasonicDecompressorV5::decompressThreaded(
+ const RawDecompressorThread* t) const {
+ switch (bps) {
+ case 12:
+ decompressThreadedInternal<TwelveBitPacket>(t);
+ break;
+ case 14:
+ decompressThreadedInternal<FourteenBitPacket>(t);
+ break;
+ default:
+ __builtin_unreachable();
+ }
+}
+
+void PanasonicDecompressorV5::decompress() const {
+ assert(blocks.size() == numBlocks);
+ startThreading(blocks.size());
+}
+
+} // namespace rawspeed
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/PanasonicDecompressorV5.h b/src/external/rawspeed/src/librawspeed/decompressors/PanasonicDecompressorV5.h
new file mode 100644
index 000000000..2af005cba
--- /dev/null
+++ b/src/external/rawspeed/src/librawspeed/decompressors/PanasonicDecompressorV5.h
@@ -0,0 +1,109 @@
+/*
+ RawSpeed - RAW file decoder.
+
+ Copyright (C) 2018 Roman Lebedev
+ Copyright (C) 2018 Stefan Hoffmeister
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#pragma once
+
+#include "common/Common.h" // for uint32
+#include "common/Point.h" // for iPoint2D
+#include "decompressors/AbstractParallelizedDecompressor.h"
+#include "io/BitPumpLSB.h" // for BitPumpLSB
+#include "io/ByteStream.h" // for ByteStream
+#include <cstddef> // for size_t
+#include <utility> // for move
+#include <vector> // for vector
+
+namespace rawspeed {
+
+class RawImage;
+
+class PanasonicDecompressorV5 final : public AbstractParallelizedDecompressor {
+ // The RW2 raw image buffer consists of individual blocks,
+ // each one BlockSize bytes in size.
+ static constexpr uint32 BlockSize = 0x4000;
+
+ // These blocks themselves comprise of two sections,
+ // split and swapped at section_split_offset:
+ // bytes: [0..sectionSplitOffset-1][sectionSplitOffset..BlockSize-1]
+ // pixels: [a..b][0..a-1]
+ // When reading, these two sections need to be swapped to enable linear
+ // processing..
+ static constexpr uint32 sectionSplitOffset = 0x1FF8;
+
+ // The blocks themselves consist of packets with fixed size of bytesPerPacket,
+ // and each packet decodes to pixelsPerPacket pixels, which depends on bps.
+ static constexpr uint32 bytesPerPacket = 16;
+ static constexpr uint32 bitsPerPacket = 8 * bytesPerPacket;
+ static_assert(BlockSize % bytesPerPacket == 0, "");
+ static constexpr uint32 PacketsPerBlock = BlockSize / bytesPerPacket;
+
+ // Contains the decoding recepie for the packet,
+ struct PacketDsc;
+
+ // There are two variants. Which one is to be used depends on image's bps.
+ static const PacketDsc TwelveBitPacket;
+ static const PacketDsc FourteenBitPacket;
+
+ // Takes care of unsplitting&swapping back the block at sectionSplitOffset.
+ class ProxyStream;
+
+ // The full input buffer, containing all the blocks.
+ ByteStream input;
+
+ const uint32 bps;
+
+ size_t numBlocks;
+
+ struct Block {
+ ByteStream bs;
+ iPoint2D beginCoord;
+ // The rectangle is an incorrect representation. All the rows
+ // between the first and last one span the entire width of the image.
+ iPoint2D endCoord;
+
+ Block() = default;
+ Block(ByteStream&& bs_, iPoint2D beginCoord_, iPoint2D endCoord_)
+ : bs(std::move(bs_)), beginCoord(beginCoord_), endCoord(endCoord_) {}
+ };
+
+ // If really wanted, this vector could be avoided,
+ // and each Block computed on-the-fly
+ std::vector<Block> blocks;
+
+ void chopInputIntoBlocks(const PacketDsc& dsc);
+
+ template <const PacketDsc& dsc>
+ void processPixelPacket(BitPumpLSB* bs, ushort16* dest) const;
+
+ template <const PacketDsc& dsc> void processBlock(const Block& block) const;
+
+ template <const PacketDsc& dsc>
+ void decompressThreadedInternal(const RawDecompressorThread* t) const;
+
+ void decompressThreaded(const RawDecompressorThread* t) const final;
+
+public:
+ PanasonicDecompressorV5(const RawImage& img, const ByteStream& input_,
+ uint32 bps_);
+
+ void decompress() const final;
+};
+
+} // namespace rawspeed
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/PentaxDecompressor.cpp b/src/external/rawspeed/src/librawspeed/decompressors/PentaxDecompressor.cpp
index 50fff52ef..ef4a38241 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/PentaxDecompressor.cpp
+++ b/src/external/rawspeed/src/librawspeed/decompressors/PentaxDecompressor.cpp
@@ -27,20 +27,18 @@
#include "io/BitPumpMSB.h" // for BitPumpMSB, BitStream<>::f...
#include "io/Buffer.h" // for Buffer
#include "io/ByteStream.h" // for ByteStream
-#include "tiff/TiffEntry.h" // for TiffEntry, ::TIFF_UNDEFINED
-#include "tiff/TiffIFD.h" // for TiffIFD
-#include "tiff/TiffTag.h" // for TiffTag
#include <cassert> // for assert
-#include <vector> // for vector, allocator
+#include <vector> // for vector
namespace rawspeed {
// 16 entries of codes per bit length
// 13 entries of code values
-const uchar8 PentaxDecompressor::pentax_tree[][2][16] = {
- {{0, 2, 3, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0},
- {3, 4, 2, 5, 1, 6, 0, 7, 8, 9, 10, 11, 12}},
-};
+const std::array<std::array<std::array<uchar8, 16>, 2>, 1>
+ PentaxDecompressor::pentax_tree = {{
+ {{{0, 2, 3, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0},
+ {3, 4, 2, 5, 1, 6, 0, 7, 8, 9, 10, 11, 12}}},
+ }};
PentaxDecompressor::PentaxDecompressor(const RawImage& img,
ByteStream* metaData)
@@ -60,9 +58,9 @@ HuffmanTable PentaxDecompressor::SetupHuffmanTable_Legacy() {
HuffmanTable ht;
/* Initialize with legacy data */
- auto nCodes = ht.setNCodesPerLength(Buffer(pentax_tree[0][0], 16));
+ auto nCodes = ht.setNCodesPerLength(Buffer(pentax_tree[0][0].data(), 16));
assert(nCodes == 13); // see pentax_tree definition
- ht.setCodeValues(Buffer(pentax_tree[0][1], nCodes));
+ ht.setCodeValues(Buffer(pentax_tree[0][1].data(), nCodes));
return ht;
}
@@ -76,8 +74,8 @@ HuffmanTable PentaxDecompressor::SetupHuffmanTable_Modern(ByteStream stream) {
stream.skipBytes(12);
- uint32 v0[16];
- uint32 v1[16];
+ std::array<uint32, 16> v0;
+ std::array<uint32, 16> v1;
for (uint32 i = 0; i < depth; i++)
v0[i] = stream.getU16();
for (uint32 i = 0; i < depth; i++) {
@@ -90,7 +88,7 @@ HuffmanTable PentaxDecompressor::SetupHuffmanTable_Modern(ByteStream stream) {
std::vector<uchar8> nCodesPerLength;
nCodesPerLength.resize(17);
- uint32 v2[16];
+ std::array<uint32, 16> v2;
/* Calculate codes and store bitcounts */
for (uint32 c = 0; c < depth; c++) {
v2[c] = v0[c] >> (12 - v1[c]);
@@ -146,8 +144,8 @@ void PentaxDecompressor::decompress(const ByteStream& data) const {
assert(mRaw->dim.x > 0);
assert(mRaw->dim.x % 2 == 0);
- int pUp1[2] = {0, 0};
- int pUp2[2] = {0, 0};
+ std::array<int, 2> pUp1 = {{}};
+ std::array<int, 2> pUp2 = {{}};
for (int y = 0; y < mRaw->dim.y && mRaw->dim.x >= 2; y++) {
auto* dest = reinterpret_cast<ushort16*>(&draw[y * mRaw->pitch]);
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/PentaxDecompressor.h b/src/external/rawspeed/src/librawspeed/decompressors/PentaxDecompressor.h
index 76c5b84b3..4cc915977 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/PentaxDecompressor.h
+++ b/src/external/rawspeed/src/librawspeed/decompressors/PentaxDecompressor.h
@@ -21,8 +21,8 @@
#pragma once
-#include "common/Common.h" // for uint32
-#include "common/RawImage.h" // for RawImage, RawImageData
+#include "common/Common.h" // for uchar8
+#include "common/RawImage.h" // for RawImage
#include "decompressors/AbstractDecompressor.h" // for AbstractDecompressor
#include "decompressors/HuffmanTable.h" // for HuffmanTable
@@ -30,8 +30,6 @@ namespace rawspeed {
class ByteStream;
-class TiffIFD;
-
class PentaxDecompressor final : public AbstractDecompressor {
RawImage mRaw;
const HuffmanTable ht;
@@ -46,7 +44,7 @@ private:
static HuffmanTable SetupHuffmanTable_Modern(ByteStream stream);
static HuffmanTable SetupHuffmanTable(ByteStream* metaData);
- static const uchar8 pentax_tree[][2][16];
+ static const std::array<std::array<std::array<uchar8, 16>, 2>, 1> pentax_tree;
};
} // namespace rawspeed
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/PhaseOneDecompressor.cpp b/src/external/rawspeed/src/librawspeed/decompressors/PhaseOneDecompressor.cpp
new file mode 100644
index 000000000..61a733793
--- /dev/null
+++ b/src/external/rawspeed/src/librawspeed/decompressors/PhaseOneDecompressor.cpp
@@ -0,0 +1,152 @@
+/*
+ RawSpeed - RAW file decoder.
+
+ Copyright (C) 2009-2014 Klaus Post
+ Copyright (C) 2014-2015 Pedro Côrte-Real
+ Copyright (C) 2017-2018 Roman Lebedev
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "decompressors/PhaseOneDecompressor.h"
+#include "common/Common.h" // for int32, uint32, ushort16
+#include "common/Point.h" // for iPoint2D
+#include "common/RawImage.h" // for RawImage, RawImageData
+#include "decoders/RawDecoderException.h" // for ThrowRDE
+#include "io/BitPumpMSB32.h" // for BitPumpMSB32
+#include <algorithm> // for for_each
+#include <array> // for array
+#include <cassert> // for assert
+#include <cstddef> // for size_t
+#include <utility> // for move
+#include <vector> // for vector, vector<>::size_type
+
+namespace rawspeed {
+
+PhaseOneDecompressor::PhaseOneDecompressor(const RawImage& img,
+ std::vector<PhaseOneStrip>&& strips_)
+ : AbstractParallelizedDecompressor(img), strips(std::move(strips_)) {
+ if (mRaw->getDataType() != TYPE_USHORT16)
+ ThrowRDE("Unexpected data type");
+
+ if (!((mRaw->getCpp() == 1 && mRaw->getBpp() == 2)))
+ ThrowRDE("Unexpected cpp: %u", mRaw->getCpp());
+
+ if (!mRaw->dim.hasPositiveArea() || mRaw->dim.x % 2 != 0 ||
+ mRaw->dim.x > 11608 || mRaw->dim.y > 8708) {
+ ThrowRDE("Unexpected image dimensions found: (%u; %u)", mRaw->dim.x,
+ mRaw->dim.y);
+ }
+
+ validateStrips();
+}
+
+void PhaseOneDecompressor::validateStrips() const {
+ // The 'strips' vector should contain exactly one element per row of image.
+
+ // If the lenght is different, then the 'strips' vector is clearly incorrect.
+ if (strips.size() != static_cast<decltype(strips)::size_type>(mRaw->dim.y)) {
+ ThrowRDE("Height (%u) vs strip count %zu mismatch", mRaw->dim.y,
+ strips.size());
+ }
+
+ struct RowBin {
+ using value_type = unsigned char;
+ bool isEmpty() const { return data == 0; }
+ void fill() { data = 1; }
+ value_type data = 0;
+ };
+
+ // Now, the strips in 'strips' vector aren't in order.
+ // The 'decltype(strips)::value_type::n' is the row number of a strip.
+ // We need to make sure that we have every row (0..mRaw->dim.y-1), once.
+
+ // There are many ways to do that. Here, we take the histogram of all the
+ // row numbers, and if any bin ends up not being '1' (one strip per row),
+ // then the input is bad.
+ std::vector<RowBin> histogram;
+ histogram.resize(strips.size());
+ int numBinsFilled = 0;
+ std::for_each(strips.begin(), strips.end(),
+ [y = mRaw->dim.y, &histogram,
+ &numBinsFilled](const PhaseOneStrip& strip) {
+ if (strip.n < 0 || strip.n >= y)
+ ThrowRDE("Strip specifies out-of-bounds row %u", strip.n);
+ RowBin& rowBin = histogram[strip.n];
+ if (!rowBin.isEmpty())
+ ThrowRDE("Duplicate row %u", strip.n);
+ rowBin.fill();
+ numBinsFilled++;
+ });
+ assert(histogram.size() == strips.size());
+ assert(numBinsFilled == mRaw->dim.y &&
+ "We should only get here if all the rows/bins got filled.");
+}
+
+void PhaseOneDecompressor::decompressStrip(const PhaseOneStrip& strip) const {
+ uint32 width = mRaw->dim.x;
+ assert(width % 2 == 0);
+
+ static constexpr std::array<const int, 10> length = {8, 7, 6, 9, 11,
+ 10, 5, 12, 14, 13};
+
+ BitPumpMSB32 pump(strip.bs);
+
+ std::array<int32, 2> pred;
+ pred.fill(0);
+ std::array<int, 2> len;
+ auto* img = reinterpret_cast<ushort16*>(mRaw->getData(0, strip.n));
+ for (uint32 col = 0; col < width; col++) {
+ if (col >= (width & ~7U)) // last 'width % 8' pixels.
+ len[0] = len[1] = 14;
+ else if ((col & 7) == 0) {
+ for (int& i : len) {
+ int j = 0;
+
+ for (; j < 5; j++) {
+ if (pump.getBits(1) != 0) {
+ if (col == 0)
+ ThrowRDE("Can not initialize lengths. Data is corrupt.");
+
+ // else, we have previously initialized lengths, so we are fine
+ break;
+ }
+ }
+
+ assert((col == 0 && j > 0) || col != 0);
+ if (j > 0)
+ i = length[2 * (j - 1) + pump.getBits(1)];
+ }
+ }
+
+ int i = len[col & 1];
+ if (i == 14)
+ img[col] = pred[col & 1] = pump.getBits(16);
+ else {
+ pred[col & 1] +=
+ static_cast<signed>(pump.getBits(i)) + 1 - (1 << (i - 1));
+ // FIXME: is the truncation the right solution here?
+ img[col] = ushort16(pred[col & 1]);
+ }
+ }
+}
+
+void PhaseOneDecompressor::decompressThreaded(
+ const RawDecompressorThread* t) const {
+ for (size_t i = t->start; i < t->end && i < strips.size(); i++)
+ decompressStrip(strips[i]);
+}
+
+} // namespace rawspeed
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/PhaseOneDecompressor.h b/src/external/rawspeed/src/librawspeed/decompressors/PhaseOneDecompressor.h
new file mode 100644
index 000000000..e7b9d3f81
--- /dev/null
+++ b/src/external/rawspeed/src/librawspeed/decompressors/PhaseOneDecompressor.h
@@ -0,0 +1,55 @@
+/*
+ RawSpeed - RAW file decoder.
+
+ Copyright (C) 2009-2014 Klaus Post
+ Copyright (C) 2014 Pedro Côrte-Real
+ Copyright (C) 2018 Roman Lebedev
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#pragma once
+
+#include "decompressors/AbstractParallelizedDecompressor.h" // for Abstract...
+#include "io/ByteStream.h" // for ByteStream
+#include <utility> // for move
+#include <vector> // for vector
+
+namespace rawspeed {
+
+class RawImage;
+
+struct PhaseOneStrip {
+ const int n;
+ const ByteStream bs;
+
+ PhaseOneStrip(int block, ByteStream bs_) : n(block), bs(std::move(bs_)) {}
+};
+
+class PhaseOneDecompressor final : public AbstractParallelizedDecompressor {
+ std::vector<PhaseOneStrip> strips;
+
+ void decompressStrip(const PhaseOneStrip& strip) const;
+
+ void decompressThreaded(const RawDecompressorThread* t) const final;
+
+ void validateStrips() const;
+
+public:
+ PhaseOneDecompressor(const RawImage& img,
+ std::vector<PhaseOneStrip>&& strips_);
+};
+
+} // namespace rawspeed
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/SamsungV0Decompressor.cpp b/src/external/rawspeed/src/librawspeed/decompressors/SamsungV0Decompressor.cpp
index da31936bb..b67659580 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/SamsungV0Decompressor.cpp
+++ b/src/external/rawspeed/src/librawspeed/decompressors/SamsungV0Decompressor.cpp
@@ -21,17 +21,12 @@
*/
#include "decompressors/SamsungV0Decompressor.h"
-#include "common/Common.h" // for ushort16, uint32, int32
+#include "common/Common.h" // for uint32, ushort16, int32
#include "common/Point.h" // for iPoint2D
#include "common/RawImage.h" // for RawImage, RawImageData
#include "decoders/RawDecoderException.h" // for ThrowRDE
#include "io/BitPumpMSB32.h" // for BitPumpMSB32
-#include "io/Buffer.h" // for Buffer
#include "io/ByteStream.h" // for ByteStream
-#include "io/Endianness.h" // for Endianness, Endianness::li...
-#include "tiff/TiffEntry.h" // for TiffEntry
-#include "tiff/TiffIFD.h" // for TiffIFD
-#include "tiff/TiffTag.h" // for TiffTag, TiffTag::IMAGELENGTH
#include <algorithm> // for max
#include <cassert> // for assert
#include <iterator> // for advance, begin, end, next
@@ -122,7 +117,7 @@ void SamsungV0Decompressor::decompressStrip(uint32 y,
BitPumpMSB32 bits(bs);
- int len[4];
+ std::array<int, 4> len;
for (int& i : len)
i = y < 2 ? 7 : 4;
@@ -139,7 +134,7 @@ void SamsungV0Decompressor::decompressStrip(uint32 y,
bits.fill();
bool dir = !!bits.getBitsNoFill(1);
- int op[4];
+ std::array<int, 4> op;
for (int& i : op)
i = bits.getBitsNoFill(2);
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/SamsungV0Decompressor.h b/src/external/rawspeed/src/librawspeed/decompressors/SamsungV0Decompressor.h
index da840ee7b..958123c1d 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/SamsungV0Decompressor.h
+++ b/src/external/rawspeed/src/librawspeed/decompressors/SamsungV0Decompressor.h
@@ -28,9 +28,7 @@
namespace rawspeed {
-class Buffer;
class RawImage;
-class TiffIFD;
// Decoder for compressed srw files (NX300 and later)
class SamsungV0Decompressor final : public AbstractSamsungDecompressor {
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/SamsungV1Decompressor.cpp b/src/external/rawspeed/src/librawspeed/decompressors/SamsungV1Decompressor.cpp
index 47e4fa285..a1aa17904 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/SamsungV1Decompressor.cpp
+++ b/src/external/rawspeed/src/librawspeed/decompressors/SamsungV1Decompressor.cpp
@@ -84,12 +84,23 @@ void SamsungV1Decompressor::decompress() {
// encode, the second the number of bits that come after with the difference
// The table has 14 entries because the difference can have between 0 (no
// difference) and 13 bits (differences between 12 bits numbers can need 13)
- const uchar8 tab[14][2] = {{3, 4}, {3, 7}, {2, 6}, {2, 5}, {4, 3},
- {6, 0}, {7, 9}, {8, 10}, {9, 11}, {10, 12},
- {10, 13}, {5, 1}, {4, 8}, {4, 2}};
+ static const std::array<std::array<uchar8, 2>, 14> tab = {{{3, 4},
+ {3, 7},
+ {2, 6},
+ {2, 5},
+ {4, 3},
+ {6, 0},
+ {7, 9},
+ {8, 10},
+ {9, 11},
+ {10, 12},
+ {10, 13},
+ {5, 1},
+ {4, 8},
+ {4, 2}}};
std::vector<encTableItem> tbl(1024);
- ushort16 vpred[2][2] = {{0, 0}, {0, 0}};
- ushort16 hpred[2];
+ std::array<std::array<ushort16, 2>, 2> vpred = {{}};
+ std::array<ushort16, 2> hpred;
// We generate a 1024 entry table (to be addressed by reading 10 bits) by
// consecutively filling in 2^(10-N) positions where N is the variable number
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/SamsungV2Decompressor.cpp b/src/external/rawspeed/src/librawspeed/decompressors/SamsungV2Decompressor.cpp
index 49b3a33e3..b3f71c922 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/SamsungV2Decompressor.cpp
+++ b/src/external/rawspeed/src/librawspeed/decompressors/SamsungV2Decompressor.cpp
@@ -202,7 +202,7 @@ void SamsungV2Decompressor::decompressRow(uint32 row) {
// By default we are not scaling values at all
int32 scale = 0;
- uint32 diffBitsMode[3][2] = {{0}};
+ std::array<std::array<int, 2>, 3> diffBitsMode = {{}};
for (auto& i : diffBitsMode)
i[0] = i[1] = (row == 0 || row == 1) ? 7 : 4;
@@ -210,7 +210,7 @@ void SamsungV2Decompressor::decompressRow(uint32 row) {
assert(width % 16 == 0);
for (uint32 col = 0; col < width; col += 16) {
if (!(optflags & OptFlags::QP) && !(col & 63)) {
- static constexpr int32 scalevals[] = {0, -2, 2};
+ static constexpr std::array<int32, 3> scalevals = {{0, -2, 2}};
uint32 i = pump.getBits(2);
scale = i < 3 ? scale + scalevals[i] : pump.getBits(12);
}
@@ -236,8 +236,10 @@ void SamsungV2Decompressor::decompressRow(uint32 row) {
ThrowRDE(
"Got a previous line lookup on first two lines. File corrupted?");
- static constexpr int32 motionOffset[7] = {-4, -2, -2, 0, 0, 2, 4};
- static constexpr int32 motionDoAverage[7] = {0, 0, 1, 0, 1, 0, 0};
+ static constexpr std::array<int32, 7> motionOffset = {-4, -2, -2, 0,
+ 0, 2, 4};
+ static constexpr std::array<int32, 7> motionDoAverage = {0, 0, 1, 0,
+ 1, 0, 0};
int32 slideOffset = motionOffset[motion];
int32 doAverage = motionDoAverage[motion];
@@ -273,9 +275,9 @@ void SamsungV2Decompressor::decompressRow(uint32 row) {
}
// Figure out how many difference bits we have to read for each pixel
- uint32 diffBits[4] = {0};
+ std::array<uint32, 4> diffBits = {};
if (optflags & OptFlags::SKIP || !pump.getBits(1)) {
- uint32 flags[4];
+ std::array<uint32, 4> flags;
for (unsigned int& flag : flags)
flag = pump.getBits(2);
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/SonyArw1Decompressor.cpp b/src/external/rawspeed/src/librawspeed/decompressors/SonyArw1Decompressor.cpp
index 0d6bddc30..1cbd2360b 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/SonyArw1Decompressor.cpp
+++ b/src/external/rawspeed/src/librawspeed/decompressors/SonyArw1Decompressor.cpp
@@ -21,14 +21,13 @@
*/
#include "decompressors/SonyArw1Decompressor.h"
-#include "common/Common.h" // for uchar8
-#include "common/Point.h" // for iPoint2D
-#include "common/RawImage.h" // for RawImage
-#include "decoders/RawDecoderException.h" // for ThrowRDE
-#include "decompressors/AbstractDecompressor.h" // for RawDecom...
-#include "decompressors/HuffmanTable.h" // for HuffmanTable
-#include "io/BitPumpMSB.h" // for BitPumpMSB
-#include <algorithm> // for move
+#include "common/Common.h" // for uint32, uchar8, ushort16
+#include "common/Point.h" // for iPoint2D
+#include "common/RawImage.h" // for RawImage, RawImageData
+#include "decoders/RawDecoderException.h" // for ThrowRDE
+#include "decompressors/HuffmanTable.h" // for HuffmanTable
+#include "io/BitPumpMSB.h" // for BitPumpMSB
+#include <cassert> // for assert
namespace rawspeed {
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/SonyArw1Decompressor.h b/src/external/rawspeed/src/librawspeed/decompressors/SonyArw1Decompressor.h
index 67a158675..1be0ccb8a 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/SonyArw1Decompressor.h
+++ b/src/external/rawspeed/src/librawspeed/decompressors/SonyArw1Decompressor.h
@@ -22,11 +22,10 @@
#include "common/RawImage.h" // for RawImage
#include "decompressors/AbstractDecompressor.h" // for AbstractDecompressor
-#include "io/ByteStream.h" // for ByteStream
namespace rawspeed {
-class RawImage;
+class ByteStream;
class SonyArw1Decompressor final : public AbstractDecompressor {
RawImage mRaw;
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/SonyArw2Decompressor.cpp b/src/external/rawspeed/src/librawspeed/decompressors/SonyArw2Decompressor.cpp
index 231b23a72..8465ed013 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/SonyArw2Decompressor.cpp
+++ b/src/external/rawspeed/src/librawspeed/decompressors/SonyArw2Decompressor.cpp
@@ -21,13 +21,13 @@
*/
#include "decompressors/SonyArw2Decompressor.h"
-#include "common/Common.h" // for uchar8
+#include "common/Common.h" // for uint32
#include "common/Point.h" // for iPoint2D
#include "common/RawImage.h" // for RawImage
-#include "decoders/RawDecoderException.h" // for ThrowRDE, ...
+#include "decoders/RawDecoderException.h" // for ThrowRDE
#include "decompressors/AbstractParallelizedDecompressor.h" // for RawDecom...
#include "io/BitPumpLSB.h" // for BitPumpLSB
-#include <algorithm> // for move
+#include <cassert> // for assert
namespace rawspeed {
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/UncompressedDecompressor.h b/src/external/rawspeed/src/librawspeed/decompressors/UncompressedDecompressor.h
index 6e625137c..8d70c19a3 100644
--- a/src/external/rawspeed/src/librawspeed/decompressors/UncompressedDecompressor.h
+++ b/src/external/rawspeed/src/librawspeed/decompressors/UncompressedDecompressor.h
@@ -28,7 +28,7 @@
#include "io/Buffer.h" // for Buffer, Buffer::size_type
#include "io/ByteStream.h" // for ByteStream
#include "io/Endianness.h" // for Endianness
-#include <algorithm> // for move
+#include <utility> // for move
namespace rawspeed {
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/VC5Decompressor.cpp b/src/external/rawspeed/src/librawspeed/decompressors/VC5Decompressor.cpp
new file mode 100644
index 000000000..b6ffde7bc
--- /dev/null
+++ b/src/external/rawspeed/src/librawspeed/decompressors/VC5Decompressor.cpp
@@ -0,0 +1,829 @@
+/*
+ RawSpeed - RAW file decoder.
+
+ Copyright (C) 2018 Stefan Löffler
+ Copyright (C) 2018 Roman Lebedev
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+/*
+ This is a decompressor for VC-5 raw compression algo, as used in GoPro raws.
+ This implementation is similar to that one of the official reference
+ implementation of the https://github.com/gopro/gpr project, and is producing
+ bitwise-identical output as compared with the Adobe DNG Converter
+ implementation.
+ */
+
+#include "rawspeedconfig.h"
+#include "decompressors/VC5Decompressor.h"
+#include "common/Array2DRef.h" // for Array2DRef
+#include "common/Optional.h" // for Optional
+#include "common/Point.h" // for iPoint2D
+#include "common/RawspeedException.h" // for RawspeedException
+#include "common/SimpleLUT.h" // for SimpleLUT, SimpleLUT<>::va...
+#include "decoders/RawDecoderException.h" // for ThrowRDE
+#include "io/Endianness.h" // for Endianness, Endianness::big
+#include <cassert> // for assert
+#include <cmath> // for pow
+#include <initializer_list> // for initializer_list
+#include <limits> // for numeric_limits
+#include <string> // for string
+#include <utility> // for move
+
+namespace {
+
+// Definitions needed by table17.inc
+// Taken from
+// https://github.com/gopro/gpr/blob/a513701afce7b03173213a2f67dfd9dd28fa1868/source/lib/vc5_decoder/vlc.h
+struct RLV {
+ uint_fast8_t size; //!< Size of code word in bits
+ uint32_t bits; //!< Code word bits right justified
+ uint16_t count; //!< Run length
+ uint16_t value; //!< Run value (unsigned)
+};
+#define RLVTABLE(n) \
+ struct { \
+ const uint32_t length; \
+ const RLV entries[n]; \
+ } constexpr
+#include "gopro/vc5/table17.inc"
+
+constexpr int16_t decompand(int16_t val) {
+ double c = val;
+ // Invert companding curve
+ c += (c * c * c * 768) / (255. * 255. * 255.);
+ if (c > std::numeric_limits<int16_t>::max())
+ return std::numeric_limits<int16_t>::max();
+ if (c < std::numeric_limits<int16_t>::min())
+ return std::numeric_limits<int16_t>::min();
+ return c;
+}
+
+#ifndef NDEBUG
+int ignore = []() {
+ for (const RLV& entry : table17.entries) {
+ assert(((-decompand(entry.value)) == decompand(-int16_t(entry.value))) &&
+ "negation of decompanded value is the same as decompanding of "
+ "negated value");
+ }
+ return 0;
+}();
+#endif
+
+const std::array<RLV, table17.length> decompandedTable17 = []() {
+ std::array<RLV, table17.length> d;
+ for (auto i = 0U; i < table17.length; i++) {
+ d[i] = table17.entries[i];
+ d[i].value = decompand(table17.entries[i].value);
+ }
+ return d;
+}();
+
+} // namespace
+
+#define PRECISION_MIN 8
+#define PRECISION_MAX 32
+
+#define MARKER_BAND_END 1
+
+namespace rawspeed {
+
+void VC5Decompressor::Wavelet::setBandValid(const int band) {
+ mDecodedBandMask |= (1 << band);
+}
+
+bool VC5Decompressor::Wavelet::isBandValid(const int band) const {
+ return mDecodedBandMask & (1 << band);
+}
+
+bool VC5Decompressor::Wavelet::allBandsValid() const {
+ return mDecodedBandMask == static_cast<uint32>((1 << numBands) - 1);
+}
+
+Array2DRef<const int16_t>
+VC5Decompressor::Wavelet::bandAsArray2DRef(const unsigned int iBand) const {
+ return {bands[iBand]->data.data(), width, height};
+}
+
+namespace {
+auto convolute = [](int x, int y, std::array<int, 4> muls,
+ const Array2DRef<const int16_t> high, auto lowGetter,
+ int DescaleShift = 0) {
+ auto highCombined = muls[0] * high(x, y);
+ auto lowsCombined = [muls, lowGetter]() {
+ int lows = 0;
+ for (int i = 0; i < 3; i++)
+ lows += muls[1 + i] * lowGetter(i);
+ return lows;
+ }();
+ // Round up 'lows' up
+ lowsCombined += 4;
+ // And finally 'average' them.
+ auto lowsRounded = lowsCombined >> 3;
+ auto total = highCombined + lowsRounded;
+ // Descale it.
+ total <<= DescaleShift;
+ // And average it.
+ total >>= 1;
+ return total;
+};
+
+struct ConvolutionParams {
+ struct First {
+ static constexpr std::array<int, 4> mul_even = {+1, +11, -4, +1};
+ static constexpr std::array<int, 4> mul_odd = {-1, +5, +4, -1};
+ static constexpr int coord_shift = 0;
+ };
+ static constexpr First First{};
+
+ struct Middle {
+ static constexpr std::array<int, 4> mul_even = {+1, +1, +8, -1};
+ static constexpr std::array<int, 4> mul_odd = {-1, -1, +8, +1};
+ static constexpr int coord_shift = -1;
+ };
+ static constexpr Middle Middle{};
+
+ struct Last {
+ static constexpr std::array<int, 4> mul_even = {+1, -1, +4, +5};
+ static constexpr std::array<int, 4> mul_odd = {-1, +1, -4, +11};
+ static constexpr int coord_shift = -2;
+ };
+ static constexpr Last Last{};
+};
+
+constexpr std::array<int, 4> ConvolutionParams::First::mul_even;
+constexpr std::array<int, 4> ConvolutionParams::First::mul_odd;
+
+constexpr std::array<int, 4> ConvolutionParams::Middle::mul_even;
+constexpr std::array<int, 4> ConvolutionParams::Middle::mul_odd;
+
+constexpr std::array<int, 4> ConvolutionParams::Last::mul_even;
+constexpr std::array<int, 4> ConvolutionParams::Last::mul_odd;
+
+} // namespace
+
+void VC5Decompressor::Wavelet::reconstructPass(
+ const Array2DRef<int16_t> dst, const Array2DRef<const int16_t> high,
+ const Array2DRef<const int16_t> low) const noexcept {
+ auto process = [low, high, dst](auto segment, int x, int y) {
+ auto lowGetter = [&x, &y, low](int delta) {
+ return low(x, y + decltype(segment)::coord_shift + delta);
+ };
+ auto convolution = [&x, &y, high, lowGetter](std::array<int, 4> muls) {
+ return convolute(x, y, muls, high, lowGetter, /*DescaleShift*/ 0);
+ };
+
+ int even = convolution(decltype(segment)::mul_even);
+ int odd = convolution(decltype(segment)::mul_odd);
+
+ dst(x, 2 * y) = static_cast<int16_t>(even);
+ dst(x, 2 * y + 1) = static_cast<int16_t>(odd);
+ };
+
+ // Vertical reconstruction
+#ifdef HAVE_OPENMP
+#pragma omp for schedule(static)
+#endif
+ for (int y = 0; y < height; ++y) {
+ if (y == 0) {
+ // 1st row
+ for (int x = 0; x < width; ++x)
+ process(ConvolutionParams::First, x, y);
+ } else if (y + 1 < height) {
+ // middle rows
+ for (int x = 0; x < width; ++x)
+ process(ConvolutionParams::Middle, x, y);
+ } else {
+ // last row
+ for (int x = 0; x < width; ++x)
+ process(ConvolutionParams::Last, x, y);
+ }
+ }
+}
+
+void VC5Decompressor::Wavelet::combineLowHighPass(
+ const Array2DRef<int16_t> dst, const Array2DRef<const int16_t> low,
+ const Array2DRef<const int16_t> high, int descaleShift,
+ bool clampUint = false) const noexcept {
+ auto process = [low, high, descaleShift, clampUint, dst](auto segment, int x,
+ int y) {
+ auto lowGetter = [&x, &y, low](int delta) {
+ return low(x + decltype(segment)::coord_shift + delta, y);
+ };
+ auto convolution = [&x, &y, high, lowGetter,
+ descaleShift](std::array<int, 4> muls) {
+ return convolute(x, y, muls, high, lowGetter, descaleShift);
+ };
+
+ int even = convolution(decltype(segment)::mul_even);
+ int odd = convolution(decltype(segment)::mul_odd);
+
+ if (clampUint) {
+ even = clampBits(even, 14);
+ odd = clampBits(odd, 14);
+ }
+ dst(2 * x, y) = static_cast<int16_t>(even);
+ dst(2 * x + 1, y) = static_cast<int16_t>(odd);
+ };
+
+ // Horizontal reconstruction
+#ifdef HAVE_OPENMP
+#pragma omp for schedule(static)
+#endif
+ for (int y = 0; y < dst.height; ++y) {
+ // First col
+ int x = 0;
+ process(ConvolutionParams::First, x, y);
+ // middle cols
+ for (x = 1; x + 1 < width; ++x) {
+ process(ConvolutionParams::Middle, x, y);
+ }
+ // last col
+ process(ConvolutionParams::Last, x, y);
+ }
+}
+
+void VC5Decompressor::Wavelet::ReconstructableBand::processLow(
+ const Wavelet& wavelet) noexcept {
+ Array2DRef<int16_t> lowpass;
+#ifdef HAVE_OPENMP
+#pragma omp single copyprivate(lowpass)
+#endif
+ lowpass = Array2DRef<int16_t>::create(&lowpass_storage, wavelet.width,
+ 2 * wavelet.height);
+
+ const Array2DRef<const int16_t> highlow = wavelet.bandAsArray2DRef(2);
+ const Array2DRef<const int16_t> lowlow = wavelet.bandAsArray2DRef(0);
+
+ // Reconstruct the "immediates", the actual low pass ...
+ wavelet.reconstructPass(lowpass, highlow, lowlow);
+}
+
+void VC5Decompressor::Wavelet::ReconstructableBand::processHigh(
+ const Wavelet& wavelet) noexcept {
+ Array2DRef<int16_t> highpass;
+#ifdef HAVE_OPENMP
+#pragma omp single copyprivate(highpass)
+#endif
+ highpass = Array2DRef<int16_t>::create(&highpass_storage, wavelet.width,
+ 2 * wavelet.height);
+
+ const Array2DRef<const int16_t> highhigh = wavelet.bandAsArray2DRef(3);
+ const Array2DRef<const int16_t> lowhigh = wavelet.bandAsArray2DRef(1);
+
+ wavelet.reconstructPass(highpass, highhigh, lowhigh);
+}
+
+void VC5Decompressor::Wavelet::ReconstructableBand::combine(
+ const Wavelet& wavelet) noexcept {
+ int16_t descaleShift = (wavelet.prescale == 2 ? 2 : 0);
+
+ Array2DRef<int16_t> dest;
+#ifdef HAVE_OPENMP
+#pragma omp single copyprivate(dest)
+#endif
+ dest =
+ Array2DRef<int16_t>::create(&data, 2 * wavelet.width, 2 * wavelet.height);
+
+ const Array2DRef<int16_t> lowpass(lowpass_storage.data(), wavelet.width,
+ 2 * wavelet.height);
+ const Array2DRef<int16_t> highpass(highpass_storage.data(), wavelet.width,
+ 2 * wavelet.height);
+
+ // And finally, combine the low pass, and high pass.
+ wavelet.combineLowHighPass(dest, lowpass, highpass, descaleShift, clampUint);
+}
+
+void VC5Decompressor::Wavelet::ReconstructableBand::decode(
+ const Wavelet& wavelet) noexcept {
+ assert(wavelet.allBandsValid());
+ assert(data.empty());
+ processLow(wavelet);
+ processHigh(wavelet);
+ combine(wavelet);
+}
+
+VC5Decompressor::VC5Decompressor(ByteStream bs, const RawImage& img)
+ : mRaw(img), mBs(std::move(bs)) {
+ if (!mRaw->dim.hasPositiveArea())
+ ThrowRDE("Bad image dimensions.");
+
+ if (mRaw->dim.x % mVC5.patternWidth != 0)
+ ThrowRDE("Width %u is not a multiple of %u", mRaw->dim.x,
+ mVC5.patternWidth);
+
+ if (mRaw->dim.y % mVC5.patternHeight != 0)
+ ThrowRDE("Height %u is not a multiple of %u", mRaw->dim.y,
+ mVC5.patternHeight);
+
+ // Initialize wavelet sizes.
+ for (Channel& channel : channels) {
+ channel.width = mRaw->dim.x / mVC5.patternWidth;
+ channel.height = mRaw->dim.y / mVC5.patternHeight;
+
+ uint16_t waveletWidth = channel.width;
+ uint16_t waveletHeight = channel.height;
+ for (Wavelet& wavelet : channel.wavelets) {
+ // Pad dimensions as necessary and divide them by two for the next wavelet
+ for (auto* dimension : {&waveletWidth, &waveletHeight})
+ *dimension = roundUpDivision(*dimension, 2);
+ wavelet.width = waveletWidth;
+ wavelet.height = waveletHeight;
+ }
+ }
+
+ if (img->whitePoint <= 0 || img->whitePoint > int(((1U << 16U) - 1U)))
+ ThrowRDE("Bad white level %i", img->whitePoint);
+
+ outputBits = 0;
+ for (int wp = img->whitePoint; wp != 0; wp >>= 1)
+ ++outputBits;
+ assert(outputBits <= 16);
+
+ parseVC5();
+}
+
+void VC5Decompressor::initVC5LogTable() {
+ mVC5LogTable = decltype(mVC5LogTable)(
+ [outputBits = outputBits](unsigned i, unsigned tableSize) {
+ // The vanilla "inverse log" curve for decoding.
+ auto normalizedCurve = [](auto normalizedI) {
+ return (std::pow(113.0, normalizedI) - 1) / 112.0;
+ };
+
+ auto normalizeI = [tableSize](auto x) { return x / (tableSize - 1.0); };
+ auto denormalizeY = [maxVal = std::numeric_limits<ushort16>::max()](
+ auto y) { return maxVal * y; };
+ // Adjust for output whitelevel bitdepth.
+ auto rescaleY = [outputBits](auto y) {
+ auto scale = 16 - outputBits;
+ return y >> scale;
+ };
+
+ const auto naiveY = denormalizeY(normalizedCurve(normalizeI(i)));
+ const auto intY = static_cast<unsigned int>(naiveY);
+ const auto rescaledY = rescaleY(intY);
+ return rescaledY;
+ });
+}
+
+void VC5Decompressor::parseVC5() {
+ mBs.setByteOrder(Endianness::big);
+
+ assert(mRaw->dim.x > 0);
+ assert(mRaw->dim.y > 0);
+
+ // All VC-5 data must start with "VC-%" (0x56432d35)
+ if (mBs.getU32() != 0x56432d35)
+ ThrowRDE("not a valid VC-5 datablock");
+
+ bool done = false;
+ while (!done) {
+ auto tag = static_cast<VC5Tag>(mBs.getU16());
+ ushort16 val = mBs.getU16();
+
+ bool optional = matches(tag, VC5Tag::Optional);
+ if (optional)
+ tag = -tag;
+
+ switch (tag) {
+ case VC5Tag::ChannelCount:
+ if (val != numChannels)
+ ThrowRDE("Bad channel count %u, expected %u", val, numChannels);
+ break;
+ case VC5Tag::ImageWidth:
+ if (val != mRaw->dim.x)
+ ThrowRDE("Image width mismatch: %u vs %u", val, mRaw->dim.x);
+ break;
+ case VC5Tag::ImageHeight:
+ if (val != mRaw->dim.y)
+ ThrowRDE("Image height mismatch: %u vs %u", val, mRaw->dim.y);
+ break;
+ case VC5Tag::LowpassPrecision:
+ if (val < PRECISION_MIN || val > PRECISION_MAX)
+ ThrowRDE("Invalid precision %i", val);
+ mVC5.lowpassPrecision = val;
+ break;
+ case VC5Tag::ChannelNumber:
+ if (val >= numChannels)
+ ThrowRDE("Bad channel number (%u)", val);
+ mVC5.iChannel = val;
+ break;
+ case VC5Tag::ImageFormat:
+ if (val != mVC5.imgFormat)
+ ThrowRDE("Image format %i is not 4(RAW)", val);
+ break;
+ case VC5Tag::SubbandCount:
+ if (val != numSubbands)
+ ThrowRDE("Unexpected subband count %u, expected %u", val, numSubbands);
+ break;
+ case VC5Tag::MaxBitsPerComponent:
+ if (val != VC5_LOG_TABLE_BITWIDTH) {
+ ThrowRDE("Bad bits per componend %u, not %u", val,
+ VC5_LOG_TABLE_BITWIDTH);
+ }
+ break;
+ case VC5Tag::PatternWidth:
+ if (val != mVC5.patternWidth)
+ ThrowRDE("Bad pattern width %u, not %u", val, mVC5.patternWidth);
+ break;
+ case VC5Tag::PatternHeight:
+ if (val != mVC5.patternHeight)
+ ThrowRDE("Bad pattern height %u, not %u", val, mVC5.patternHeight);
+ break;
+ case VC5Tag::SubbandNumber:
+ if (val >= numSubbands)
+ ThrowRDE("Bad subband number %u", val);
+ mVC5.iSubband = val;
+ break;
+ case VC5Tag::Quantization:
+ mVC5.quantization = static_cast<short16>(val);
+ break;
+ case VC5Tag::ComponentsPerSample:
+ if (val != mVC5.cps)
+ ThrowRDE("Bad compnent per sample count %u, not %u", val, mVC5.cps);
+ break;
+ case VC5Tag::PrescaleShift:
+ // FIXME: something is wrong. We get this before VC5Tag::ChannelNumber.
+ // Defaulting to 'mVC5.iChannel=0' seems to work *for existing samples*.
+ for (int iWavelet = 0; iWavelet < numWaveletLevels; ++iWavelet) {
+ auto& channel = channels[mVC5.iChannel];
+ auto& wavelet = channel.wavelets[iWavelet];
+ wavelet.prescale = (val >> (14 - 2 * iWavelet)) & 0x03;
+ }
+ break;
+ default: { // A chunk.
+ unsigned int chunkSize = 0;
+ if (matches(tag, VC5Tag::LARGE_CHUNK)) {
+ chunkSize = static_cast<unsigned int>(
+ ((static_cast<std::underlying_type<VC5Tag>::type>(tag) & 0xff)
+ << 16) |
+ (val & 0xffff));
+ } else if (matches(tag, VC5Tag::SMALL_CHUNK)) {
+ chunkSize = (val & 0xffff);
+ }
+
+ if (is(tag, VC5Tag::LargeCodeblock)) {
+ parseLargeCodeblock(mBs.getStream(chunkSize, 4));
+ break;
+ }
+
+ // And finally, we got here if we didn't handle this tag/maybe-chunk.
+
+ // Magic, all the other 'large' chunks are actually optional,
+ // and don't specify any chunk bytes-to-be-skipped.
+ if (matches(tag, VC5Tag::LARGE_CHUNK)) {
+ optional = true;
+ chunkSize = 0;
+ }
+
+ if (!optional) {
+ ThrowRDE("Unknown (unhandled) non-optional Tag 0x%04hx",
+ static_cast<std::underlying_type<VC5Tag>::type>(tag));
+ }
+
+ if (chunkSize)
+ mBs.skipBytes(chunkSize, 4);
+
+ break;
+ }
+ }
+
+ done = true;
+ for (int iChannel = 0; iChannel < numChannels && done; ++iChannel) {
+ Wavelet& wavelet = channels[iChannel].wavelets[0];
+ if (!wavelet.allBandsValid())
+ done = false;
+ }
+ }
+}
+
+VC5Decompressor::Wavelet::LowPassBand::LowPassBand(const Wavelet& wavelet,
+ ByteStream bs_,
+ ushort16 lowpassPrecision_)
+ : AbstractDecodeableBand(std::move(bs_)),
+ lowpassPrecision(lowpassPrecision_) {
+ // Low-pass band is a uncompressed version of the image, hugely downscaled.
+ // It consists of width * height pixels, `lowpassPrecision` each.
+ // We can easily check that we have sufficient amount of bits to decode it.
+ const auto waveletArea = iPoint2D(wavelet.width, wavelet.height).area();
+ const auto bitsTotal = waveletArea * lowpassPrecision;
+ const auto bytesTotal = roundUpDivision(bitsTotal, 8);
+ bs = bs.getStream(bytesTotal); // And clamp the size while we are at it.
+}
+
+void VC5Decompressor::Wavelet::LowPassBand::decode(const Wavelet& wavelet) {
+ const auto dst =
+ Array2DRef<int16_t>::create(&data, wavelet.width, wavelet.height);
+
+ BitPumpMSB bits(bs);
+ for (auto row = 0; row < dst.height; ++row) {
+ for (auto col = 0; col < dst.width; ++col)
+ dst(col, row) = static_cast<int16_t>(bits.getBits(lowpassPrecision));
+ }
+}
+
+void VC5Decompressor::Wavelet::HighPassBand::decode(const Wavelet& wavelet) {
+ auto dequantize = [quant = quant](int16_t val) -> int16_t {
+ return val * quant;
+ };
+
+ Array2DRef<int16_t>::create(&data, wavelet.width, wavelet.height);
+
+ BitPumpMSB bits(bs);
+ // decode highpass band
+ int pixelValue = 0;
+ unsigned int count = 0;
+ int nPixels = wavelet.width * wavelet.height;
+ for (int iPixel = 0; iPixel < nPixels;) {
+ getRLV(&bits, &pixelValue, &count);
+ for (; count > 0; --count) {
+ if (iPixel >= nPixels)
+ ThrowRDE("Buffer overflow");
+ data[iPixel] = dequantize(pixelValue);
+ ++iPixel;
+ }
+ }
+ getRLV(&bits, &pixelValue, &count);
+ static_assert(decompand(MARKER_BAND_END) == MARKER_BAND_END, "passthrought");
+ if (pixelValue != MARKER_BAND_END || count != 0)
+ ThrowRDE("EndOfBand marker not found");
+}
+
+void VC5Decompressor::parseLargeCodeblock(const ByteStream& bs) {
+ static const auto subband_wavelet_index = []() {
+ std::array<int, numSubbands> wavelets;
+ int wavelet = 0;
+ for (auto i = wavelets.size() - 1; i > 0;) {
+ for (auto t = 0; t < numWaveletLevels; t++) {
+ wavelets[i] = wavelet;
+ i--;
+ }
+ if (i > 0)
+ wavelet++;
+ }
+ wavelets.front() = wavelet;
+ return wavelets;
+ }();
+ static const auto subband_band_index = []() {
+ std::array<int, numSubbands> bands;
+ bands.front() = 0;
+ for (auto i = 1U; i < bands.size();) {
+ for (int t = 1; t <= numWaveletLevels;) {
+ bands[i] = t;
+ t++;
+ i++;
+ }
+ }
+ return bands;
+ }();
+
+ if (!mVC5.iSubband.hasValue())
+ ThrowRDE("Did not see VC5Tag::SubbandNumber yet");
+
+ const int idx = subband_wavelet_index[mVC5.iSubband.getValue()];
+ const int band = subband_band_index[mVC5.iSubband.getValue()];
+
+ auto& wavelets = channels[mVC5.iChannel].wavelets;
+
+ Wavelet& wavelet = wavelets[idx];
+ if (wavelet.isBandValid(band)) {
+ ThrowRDE("Band %u for wavelet %u on channel %u was already seen", band, idx,
+ mVC5.iChannel);
+ }
+
+ std::unique_ptr<Wavelet::AbstractBand>& dstBand = wavelet.bands[band];
+ if (mVC5.iSubband.getValue() == 0) {
+ assert(band == 0);
+ // low-pass band, only one, for the smallest wavelet, per channel per image
+ if (!mVC5.lowpassPrecision.hasValue())
+ ThrowRDE("Did not see VC5Tag::LowpassPrecision yet");
+ dstBand = std::make_unique<Wavelet::LowPassBand>(
+ wavelet, bs, mVC5.lowpassPrecision.getValue());
+ mVC5.lowpassPrecision.reset();
+ } else {
+ if (!mVC5.quantization.hasValue())
+ ThrowRDE("Did not see VC5Tag::Quantization yet");
+ dstBand = std::make_unique<Wavelet::HighPassBand>(
+ bs, mVC5.quantization.getValue());
+ mVC5.quantization.reset();
+ }
+ wavelet.setBandValid(band);
+
+ // If this wavelet is fully specified, mark the low-pass band of the
+ // next lower wavelet as specified.
+ if (idx > 0 && wavelet.allBandsValid()) {
+ Wavelet& nextWavelet = wavelets[idx - 1];
+ assert(!nextWavelet.isBandValid(0));
+ nextWavelet.bands[0] = std::make_unique<Wavelet::ReconstructableBand>();
+ nextWavelet.setBandValid(0);
+ }
+
+ mVC5.iSubband.reset();
+}
+
+void VC5Decompressor::decode(unsigned int offsetX, unsigned int offsetY,
+ unsigned int width, unsigned int height) {
+ if (offsetX || offsetY || mRaw->dim != iPoint2D(width, height))
+ ThrowRDE("VC5Decompressor expects to fill the whole image, not some tile.");
+
+ initVC5LogTable();
+
+ const std::vector<DecodeableBand> allDecodeableBands = [&]() {
+ std::vector<DecodeableBand> bands;
+ bands.reserve(numSubbandsTotal);
+ // All the high-pass bands for all wavelets,
+ // in this specific order of decreasing worksize.
+ for (int waveletLevel = 0; waveletLevel < numWaveletLevels;
+ waveletLevel++) {
+ for (auto channelId = 0; channelId < numChannels; channelId++) {
+ for (int bandId = 1; bandId <= numHighPassBands; bandId++) {
+ auto& channel = channels[channelId];
+ auto& wavelet = channel.wavelets[waveletLevel];
+ auto* band = wavelet.bands[bandId].get();
+ auto* decodeableHighPassBand =
+ dynamic_cast<Wavelet::HighPassBand*>(band);
+ bands.emplace_back(decodeableHighPassBand, wavelet);
+ }
+ }
+ }
+ // The low-pass bands at the end. I'm guessing they should be fast to
+ // decode.
+ for (Channel& channel : channels) {
+ // Low-pass band of the smallest wavelet.
+ Wavelet& smallestWavelet = channel.wavelets.back();
+ auto* decodeableLowPassBand =
+ dynamic_cast<Wavelet::LowPassBand*>(smallestWavelet.bands[0].get());
+ bands.emplace_back(decodeableLowPassBand, smallestWavelet);
+ }
+ assert(allDecodeableBands.size() == numSubbandsTotal);
+ return bands;
+ }();
+
+ const std::vector<ReconstructionStep> reconstructionSteps = [&]() {
+ std::vector<ReconstructionStep> steps;
+ steps.reserve(numLowPassBandsTotal);
+ // For every channel, recursively reconstruct the low-pass bands.
+ for (auto& channel : channels) {
+ // Reconstruct the intermediate lowpass bands.
+ for (int waveletLevel = numWaveletLevels - 1; waveletLevel > 0;
+ waveletLevel--) {
+ Wavelet* wavelet = &(channel.wavelets[waveletLevel]);
+ Wavelet& nextWavelet = channel.wavelets[waveletLevel - 1];
+
+ auto* band = dynamic_cast<Wavelet::ReconstructableBand*>(
+ nextWavelet.bands[0].get());
+ steps.emplace_back(wavelet, band);
+ }
+ // Finally, reconstruct the final lowpass band.
+ Wavelet* wavelet = &(channel.wavelets.front());
+ steps.emplace_back(wavelet, &(channel.band));
+ }
+ assert(steps.size() == numLowPassBandsTotal);
+ return steps;
+ }();
+
+#ifdef HAVE_OPENMP
+ bool exceptionThrown = false;
+#pragma omp parallel default(none) shared(exceptionThrown) \
+ num_threads(rawspeed_get_number_of_processor_cores())
+ {
+#endif
+#ifdef HAVE_OPENMP
+#pragma omp for schedule(dynamic, 1)
+#endif
+ for (auto decodeableBand = allDecodeableBands.begin();
+ decodeableBand < allDecodeableBands.end(); ++decodeableBand) {
+ try {
+ decodeableBand->band->decode(decodeableBand->wavelet);
+ } catch (RawspeedException& err) {
+ // Propagate the exception out of OpenMP magic.
+ mRaw->setError(err.what());
+#ifdef HAVE_OPENMP
+#pragma omp atomic write
+ exceptionThrown = true;
+#pragma omp cancel for
+#else
+ throw;
+#endif
+ }
+ }
+
+#ifdef HAVE_OPENMP
+#pragma omp cancel parallel if (exceptionThrown)
+
+ // Parallel region termination is usually disabled by default,
+ // thus we can't just rely on it. Proceed only if decoding did not fail.
+ if (!exceptionThrown) {
+#endif
+ // And now, reconstruct the low-pass bands.
+ for (const ReconstructionStep& step : reconstructionSteps) {
+ step.band.decode(step.wavelet);
+
+#ifdef HAVE_OPENMP
+#pragma omp single nowait
+#endif
+ step.wavelet.clear(); // we no longer need it.
+ }
+
+ // And finally!
+ combineFinalLowpassBands();
+
+#ifdef HAVE_OPENMP
+ }
+ }
+
+ std::string firstErr;
+ if (mRaw->isTooManyErrors(1, &firstErr)) {
+ assert(exceptionThrown);
+ ThrowRDE("Too many errors encountered. Giving up. First Error:\n%s",
+ firstErr.c_str());
+ } else {
+ assert(!exceptionThrown);
+ }
+#endif
+}
+
+void VC5Decompressor::combineFinalLowpassBands() const noexcept {
+ const Array2DRef<uint16_t> out(reinterpret_cast<uint16_t*>(mRaw->getData()),
+ mRaw->dim.x, mRaw->dim.y,
+ mRaw->pitch / sizeof(uint16_t));
+
+ const int width = out.width / 2;
+ const int height = out.height / 2;
+
+ const Array2DRef<const int16_t> lowbands0 = Array2DRef<const int16_t>(
+ channels[0].band.data.data(), channels[0].width, channels[0].height);
+ const Array2DRef<const int16_t> lowbands1 = Array2DRef<const int16_t>(
+ channels[1].band.data.data(), channels[1].width, channels[1].height);
+ const Array2DRef<const int16_t> lowbands2 = Array2DRef<const int16_t>(
+ channels[2].band.data.data(), channels[2].width, channels[2].height);
+ const Array2DRef<const int16_t> lowbands3 = Array2DRef<const int16_t>(
+ channels[3].band.data.data(), channels[3].width, channels[3].height);
+
+ // Convert to RGGB output
+#ifdef HAVE_OPENMP
+#pragma omp for schedule(static) collapse(2)
+#endif
+ for (int row = 0; row < height; ++row) {
+ for (int col = 0; col < width; ++col) {
+ const int mid = 2048;
+
+ int gs = lowbands0(col, row);
+ int rg = lowbands1(col, row) - mid;
+ int bg = lowbands2(col, row) - mid;
+ int gd = lowbands3(col, row) - mid;
+
+ int r = gs + 2 * rg;
+ int b = gs + 2 * bg;
+ int g1 = gs + gd;
+ int g2 = gs - gd;
+
+ out(2 * col + 0, 2 * row + 0) = static_cast<uint16_t>(mVC5LogTable[r]);
+ out(2 * col + 1, 2 * row + 0) = static_cast<uint16_t>(mVC5LogTable[g1]);
+ out(2 * col + 0, 2 * row + 1) = static_cast<uint16_t>(mVC5LogTable[g2]);
+ out(2 * col + 1, 2 * row + 1) = static_cast<uint16_t>(mVC5LogTable[b]);
+ }
+ }
+}
+
+inline void VC5Decompressor::getRLV(BitPumpMSB* bits, int* value,
+ unsigned int* count) {
+ unsigned int iTab;
+
+ static constexpr auto maxBits = 1 + table17.entries[table17.length - 1].size;
+
+ // Ensure the maximum number of bits are cached to make peekBits() as fast as
+ // possible.
+ bits->fill(maxBits);
+ for (iTab = 0; iTab < table17.length; ++iTab) {
+ if (decompandedTable17[iTab].bits ==
+ bits->peekBitsNoFill(decompandedTable17[iTab].size))
+ break;
+ }
+ if (iTab >= table17.length)
+ ThrowRDE("Code not found in codebook");
+
+ bits->skipBitsNoFill(decompandedTable17[iTab].size);
+ *value = decompandedTable17[iTab].value;
+ *count = decompandedTable17[iTab].count;
+ if (*value != 0) {
+ if (bits->getBitsNoFill(1))
+ *value = -(*value);
+ }
+}
+
+} // namespace rawspeed
diff --git a/src/external/rawspeed/src/librawspeed/decompressors/VC5Decompressor.h b/src/external/rawspeed/src/librawspeed/decompressors/VC5Decompressor.h
new file mode 100644
index 000000000..268ed2eeb
--- /dev/null
+++ b/src/external/rawspeed/src/librawspeed/decompressors/VC5Decompressor.h
@@ -0,0 +1,229 @@
+/*
+ RawSpeed - RAW file decoder.
+
+ Copyright (C) 2018 Stefan Löffler
+ Copyright (C) 2018 Roman Lebedev
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#pragma once
+
+#include "common/Array2DRef.h" // for Array2DRef
+#include "common/Common.h" // for ushort16, short16
+#include "common/DefaultInitAllocatorAdaptor.h" // for DefaultInitAllocatorA...
+#include "common/Optional.h" // for Optional
+#include "common/RawImage.h" // for RawImage
+#include "common/SimpleLUT.h" // for SimpleLUT, SimpleLUT...
+#include "decompressors/AbstractDecompressor.h" // for AbstractDecompressor
+#include "io/BitPumpMSB.h" // for BitPumpMSB
+#include "io/ByteStream.h" // for ByteStream
+#include <array> // for array
+#include <cstdint> // for int16_t, uint16_t
+#include <memory> // for unique_ptr
+#include <type_traits> // for underlying_type, und...
+#include <utility> // for move
+#include <vector> // for vector
+
+namespace rawspeed {
+
+const int MAX_NUM_PRESCALE = 8;
+
+// Decompresses VC-5 as used by GoPro
+
+enum class VC5Tag : int16_t {
+ NoTag = 0x0, // synthetic, not an actual tag
+
+ ChannelCount = 0x000c,
+ ImageWidth = 0x0014,
+ ImageHeight = 0x0015,
+ LowpassPrecision = 0x0023,
+ SubbandCount = 0x000E,
+ SubbandNumber = 0x0030,
+ Quantization = 0x0035,
+ ChannelNumber = 0x003e,
+ ImageFormat = 0x0054,
+ MaxBitsPerComponent = 0x0066,
+ PatternWidth = 0x006a,
+ PatternHeight = 0x006b,
+ ComponentsPerSample = 0x006c,
+ PrescaleShift = 0x006d,
+
+ LARGE_CHUNK = 0x2000,
+ SMALL_CHUNK = 0x4000,
+ UniqueImageIdentifier = 0x4004,
+ LargeCodeblock = 0x6000,
+
+ Optional = int16_t(0x8000U), // only signbit set
+};
+inline VC5Tag operator&(VC5Tag LHS, VC5Tag RHS) {
+ using value_type = std::underlying_type<VC5Tag>::type;
+ return static_cast<VC5Tag>(static_cast<value_type>(LHS) &
+ static_cast<value_type>(RHS));
+}
+inline bool matches(VC5Tag LHS, VC5Tag RHS) {
+ // Are there any common bit set?
+ return (LHS & RHS) != VC5Tag::NoTag;
+}
+inline bool is(VC5Tag LHS, VC5Tag RHS) {
+ // Does LHS have all the RHS bits set?
+ return (LHS & RHS) == RHS;
+}
+inline VC5Tag operator-(VC5Tag tag) {
+ using value_type = std::underlying_type<VC5Tag>::type;
+ // Negate
+ return static_cast<VC5Tag>(-static_cast<value_type>(tag));
+}
+
+class VC5Decompressor final : public AbstractDecompressor {
+ RawImage mRaw;
+ ByteStream mBs;
+
+ static constexpr auto VC5_LOG_TABLE_BITWIDTH = 12;
+ int outputBits;
+ SimpleLUT<unsigned, VC5_LOG_TABLE_BITWIDTH> mVC5LogTable;
+
+ void initVC5LogTable();
+
+ static constexpr int numWaveletLevels = 3;
+ static constexpr int numHighPassBands = 3;
+ static constexpr int numLowPassBands = 1;
+ static constexpr int numSubbands =
+ numLowPassBands + numHighPassBands * numWaveletLevels;
+
+ struct {
+ ushort16 iChannel = 0; // 0'th channel is the default
+ Optional<ushort16> iSubband;
+ Optional<ushort16> lowpassPrecision;
+ Optional<short16> quantization;
+
+ const ushort16 imgFormat = 4;
+ const ushort16 patternWidth = 2;
+ const ushort16 patternHeight = 2;
+ const ushort16 cps = 1;
+ } mVC5;
+
+ class Wavelet {
+ public:
+ int width, height;
+ int16_t prescale;
+
+ struct AbstractBand {
+ std::vector<int16_t, DefaultInitAllocatorAdaptor<int16_t>> data;
+ virtual ~AbstractBand() = default;
+ virtual void decode(const Wavelet& wavelet) = 0;
+ };
+ struct ReconstructableBand final : AbstractBand {
+ bool clampUint;
+ std::vector<int16_t, DefaultInitAllocatorAdaptor<int16_t>>
+ lowpass_storage;
+ std::vector<int16_t, DefaultInitAllocatorAdaptor<int16_t>>
+ highpass_storage;
+ explicit ReconstructableBand(bool clampUint_ = false)
+ : clampUint(clampUint_) {}
+ void processLow(const Wavelet& wavelet) noexcept;
+ void processHigh(const Wavelet& wavelet) noexcept;
+ void combine(const Wavelet& wavelet) noexcept;
+ void decode(const Wavelet& wavelet) noexcept final;
+ };
+ struct AbstractDecodeableBand : AbstractBand {
+ ByteStream bs;
+ explicit AbstractDecodeableBand(ByteStream bs_) : bs(std::move(bs_)) {}
+ };
+ struct LowPassBand final : AbstractDecodeableBand {
+ ushort16 lowpassPrecision;
+ LowPassBand(const Wavelet& wavelet, ByteStream bs_,
+ ushort16 lowpassPrecision_);
+ void decode(const Wavelet& wavelet) final;
+ };
+ struct HighPassBand final : AbstractDecodeableBand {
+ int16_t quant;
+ HighPassBand(ByteStream bs_, int16_t quant_)
+ : AbstractDecodeableBand(std::move(bs_)), quant(quant_) {}
+ void decode(const Wavelet& wavelet) final;
+ };
+
+ static constexpr uint16_t numBands = 4;
+ std::array<std::unique_ptr<AbstractBand>, numBands> bands;
+
+ void clear() {
+ for (auto& band : bands)
+ band.reset();
+ }
+
+ void setBandValid(int band);
+ bool isBandValid(int band) const;
+ uint32_t getValidBandMask() const { return mDecodedBandMask; }
+ bool allBandsValid() const;
+
+ void reconstructPass(Array2DRef<int16_t> dst,
+ Array2DRef<const int16_t> high,
+ Array2DRef<const int16_t> low) const noexcept;
+
+ void combineLowHighPass(Array2DRef<int16_t> dst,
+ Array2DRef<const int16_t> low,
+ Array2DRef<const int16_t> high, int descaleShift,
+ bool clampUint /*= false*/) const noexcept;
+
+ Array2DRef<const int16_t> bandAsArray2DRef(unsigned int iBand) const;
+
+ protected:
+ uint32 mDecodedBandMask = 0;
+ };
+
+ struct Channel {
+ std::array<Wavelet, numWaveletLevels> wavelets;
+
+ Wavelet::ReconstructableBand band{/*clampUint*/ true};
+ // the final lowband.
+ int width, height;
+ };
+
+ static constexpr int numChannels = 4;
+ static constexpr int numSubbandsTotal = numSubbands * numChannels;
+ static constexpr int numLowPassBandsTotal = numWaveletLevels * numChannels;
+ std::array<Channel, numChannels> channels;
+
+ struct DecodeableBand {
+ Wavelet::AbstractDecodeableBand* band;
+ const Wavelet& wavelet;
+ DecodeableBand(Wavelet::AbstractDecodeableBand* band_,
+ const Wavelet& wavelet_)
+ : band(band_), wavelet(wavelet_) {}
+ };
+ struct ReconstructionStep {
+ Wavelet& wavelet;
+ Wavelet::ReconstructableBand& band;
+ ReconstructionStep(Wavelet* wavelet_, Wavelet::ReconstructableBand* band_)
+ : wavelet(*wavelet_), band(*band_) {}
+ };
+
+ static inline void getRLV(BitPumpMSB* bits, int* value, unsigned int* count);
+
+ void parseLargeCodeblock(const ByteStream& bs);
+
+ // FIXME: this *should* be threadedable nicely.
+ void combineFinalLowpassBands() const noexcept;
+
+ void parseVC5();
+
+public:
+ VC5Decompressor(ByteStream bs, const RawImage& img);
+
+ void decode(unsigned int offsetX, unsigned int offsetY, unsigned int width,
+ unsigned int height);
+};
+
+} // namespace rawspeed
diff --git a/src/external/rawspeed/src/librawspeed/io/BitPumpJPEG.h b/src/external/rawspeed/src/librawspeed/io/BitPumpJPEG.h
index d9e562d0a..5cfb42cf0 100644
--- a/src/external/rawspeed/src/librawspeed/io/BitPumpJPEG.h
+++ b/src/external/rawspeed/src/librawspeed/io/BitPumpJPEG.h
@@ -33,6 +33,10 @@ struct JPEGBitPumpTag;
// i.e. we push into the cache from the right and read it from the left
using BitPumpJPEG = BitStream<JPEGBitPumpTag, BitStreamCacheRightInLeftOut>;
+template <> struct BitStreamTraits<BitPumpJPEG> final {
+ static constexpr bool canUseWithHuffmanTable = true;
+};
+
template <>
inline BitPumpJPEG::size_type BitPumpJPEG::fillCache(const uchar8* input)
{
@@ -64,7 +68,7 @@ inline BitPumpJPEG::size_type BitPumpJPEG::fillCache(const uchar8* input)
// Normally we would rewind the pos to the FF byte, but in order to
// prevent potential endless loop on corrupt lossless jpeg, let's not.
- cache.cache &= ~0xFF;
+ cache.cache &= ~0xFFULL; // clear low 8 bits.
cache.cache <<= 64 - cache.fillLevel;
cache.fillLevel = 64;
break;
diff --git a/src/external/rawspeed/src/librawspeed/io/BitPumpLSB.h b/src/external/rawspeed/src/librawspeed/io/BitPumpLSB.h
index c7665b8a7..91a6e11d6 100644
--- a/src/external/rawspeed/src/librawspeed/io/BitPumpLSB.h
+++ b/src/external/rawspeed/src/librawspeed/io/BitPumpLSB.h
@@ -27,12 +27,12 @@
namespace rawspeed {
-struct PlainBitPumpTag;
+struct LSBBitPumpTag;
-// The PlainPump is ordered in LSB bit order,
+// The LSBPump is ordered in LSB bit order,
// i.e. we push into the cache from the left and read it from the right
-using BitPumpLSB = BitStream<PlainBitPumpTag, BitStreamCacheLeftInRightOut>;
+using BitPumpLSB = BitStream<LSBBitPumpTag, BitStreamCacheLeftInRightOut>;
template <>
inline BitPumpLSB::size_type BitPumpLSB::fillCache(const uchar8* input) {
diff --git a/src/external/rawspeed/src/librawspeed/io/BitPumpMSB.h b/src/external/rawspeed/src/librawspeed/io/BitPumpMSB.h
index 9006404ad..bd5d8ed56 100644
--- a/src/external/rawspeed/src/librawspeed/io/BitPumpMSB.h
+++ b/src/external/rawspeed/src/librawspeed/io/BitPumpMSB.h
@@ -33,6 +33,10 @@ struct MSBBitPumpTag;
using BitPumpMSB = BitStream<MSBBitPumpTag, BitStreamCacheRightInLeftOut>;
+template <> struct BitStreamTraits<BitPumpMSB> final {
+ static constexpr bool canUseWithHuffmanTable = true;
+};
+
template <>
inline BitPumpMSB::size_type BitPumpMSB::fillCache(const uchar8* input)
{
diff --git a/src/external/rawspeed/src/librawspeed/io/BitPumpMSB32.h b/src/external/rawspeed/src/librawspeed/io/BitPumpMSB32.h
index ed77c9200..0797ce284 100644
--- a/src/external/rawspeed/src/librawspeed/io/BitPumpMSB32.h
+++ b/src/external/rawspeed/src/librawspeed/io/BitPumpMSB32.h
@@ -33,6 +33,10 @@ struct MSB32BitPumpTag;
using BitPumpMSB32 = BitStream<MSB32BitPumpTag, BitStreamCacheRightInLeftOut>;
+template <> struct BitStreamTraits<BitPumpMSB32> final {
+ static constexpr bool canUseWithHuffmanTable = true;
+};
+
template <>
inline BitPumpMSB32::size_type BitPumpMSB32::fillCache(const uchar8* input)
{
diff --git a/src/external/rawspeed/src/librawspeed/io/BitStream.h b/src/external/rawspeed/src/librawspeed/io/BitStream.h
index 6c151e01d..d9c8037ba 100644
--- a/src/external/rawspeed/src/librawspeed/io/BitStream.h
+++ b/src/external/rawspeed/src/librawspeed/io/BitStream.h
@@ -60,7 +60,7 @@ struct BitStreamCacheLeftInRightOut : BitStreamCacheBase
}
inline uint32 peek(uint32 count) const noexcept {
- return cache & ((1 << count) - 1);
+ return cache & ((1U << count) - 1U);
}
inline void skip(uint32 count) noexcept {
@@ -78,7 +78,7 @@ struct BitStreamCacheRightInLeftOut : BitStreamCacheBase
}
inline uint32 peek(uint32 count) const noexcept {
- return (cache >> (fillLevel - count)) & ((1 << count) - 1);
+ return (cache >> (fillLevel - count)) & ((1U << count) - 1U);
}
inline void skip(uint32 count) noexcept {
@@ -86,6 +86,10 @@ struct BitStreamCacheRightInLeftOut : BitStreamCacheBase
}
};
+template <typename BIT_STREAM> struct BitStreamTraits final {
+ static constexpr bool canUseWithHuffmanTable = false;
+};
+
template <typename Tag, typename Cache>
class BitStream final : public ByteStream {
Cache cache;
@@ -109,15 +113,17 @@ private:
inline void fillSafe() {
assert(data);
if (pos + BitStreamCacheBase::MaxProcessBytes <= size) {
- uchar8 tmp[BitStreamCacheBase::MaxProcessBytes] = {0};
+ std::array<uchar8, BitStreamCacheBase::MaxProcessBytes> tmp;
+ tmp.fill(0);
assert(!(size - pos < BitStreamCacheBase::MaxProcessBytes));
- memcpy(tmp, data + pos, BitStreamCacheBase::MaxProcessBytes);
- pos += fillCache(tmp);
+ memcpy(tmp.data(), data + pos, BitStreamCacheBase::MaxProcessBytes);
+ pos += fillCache(tmp.data());
} else if (pos < size) {
- uchar8 tmp[BitStreamCacheBase::MaxProcessBytes] = {0};
+ std::array<uchar8, BitStreamCacheBase::MaxProcessBytes> tmp;
+ tmp.fill(0);
assert(size - pos < BitStreamCacheBase::MaxProcessBytes);
- memcpy(tmp, data + pos, size - pos);
- pos += fillCache(tmp);
+ memcpy(tmp.data(), data + pos, size - pos);
+ pos += fillCache(tmp.data());
} else if (pos < size + Cache::MaxGetBits / 8) {
// yes, this case needs to continue using Cache::MaxGetBits
// assert(size <= pos);
@@ -156,6 +162,8 @@ public:
return pos - (cache.fillLevel >> 3);
}
+ inline size_type getFillLevel() const { return cache.fillLevel; }
+
// rewinds to the beginning of the buffer.
void resetBufferPosition() {
pos = 0;
diff --git a/src/external/rawspeed/src/librawspeed/io/Buffer.cpp b/src/external/rawspeed/src/librawspeed/io/Buffer.cpp
index 0ce16b7df..7c9307bff 100644
--- a/src/external/rawspeed/src/librawspeed/io/Buffer.cpp
+++ b/src/external/rawspeed/src/librawspeed/io/Buffer.cpp
@@ -19,12 +19,11 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "rawspeedconfig.h"
#include "io/Buffer.h"
-#include "AddressSanitizer.h" // for ASan::RegionIsPoisoned
+#include "AddressSanitizer.h" // for ASan
#include "common/Common.h" // for uchar8, roundUp
-#include "common/Memory.h" // for alignedFree, alignedMalloc
-#include "io/IOException.h" // for IOException (ptr only), ThrowIOE
+#include "common/Memory.h" // for alignedFree, alignedFreeConstPtr, alig...
+#include "io/IOException.h" // for ThrowIOE
#include <cassert> // for assert
#include <memory> // for unique_ptr
diff --git a/src/external/rawspeed/src/librawspeed/io/Buffer.h b/src/external/rawspeed/src/librawspeed/io/Buffer.h
index 77e655e9d..f9419e1f2 100644
--- a/src/external/rawspeed/src/librawspeed/io/Buffer.h
+++ b/src/external/rawspeed/src/librawspeed/io/Buffer.h
@@ -21,15 +21,14 @@
#pragma once
-#include "rawspeedconfig.h"
-#include "AddressSanitizer.h" // for ASan::RegionIsPoisoned
-#include "common/Common.h" // for uchar8, uint32, uint64
+#include "AddressSanitizer.h" // for ASan
+#include "common/Common.h" // for uchar8, uint64, uint32
#include "common/Memory.h" // for alignedFree
-#include "io/Endianness.h" // for getByteSwapped
+#include "io/Endianness.h" // for Endianness, Endianness::little, getHos...
#include "io/IOException.h" // for ThrowIOE
-#include <algorithm> // for swap
#include <cassert> // for assert
#include <memory> // for unique_ptr
+#include <utility> // for swap
namespace rawspeed {
diff --git a/src/external/rawspeed/src/librawspeed/io/ByteStream.h b/src/external/rawspeed/src/librawspeed/io/ByteStream.h
index a9613e59a..cd2c10599 100644
--- a/src/external/rawspeed/src/librawspeed/io/ByteStream.h
+++ b/src/external/rawspeed/src/librawspeed/io/ByteStream.h
@@ -225,12 +225,12 @@ public:
// special factory function to set up internal buffer with copy of passed data.
// only necessary to create 'fake' TiffEntries (see e.g. RAF)
- static ByteStream createCopy(void* data, size_type size) {
+ static ByteStream createCopy(void* data_, size_type size_) {
ByteStream bs;
- auto* new_data = alignedMalloc<uchar8, 8>(roundUp(size, 8));
- memcpy(new_data, data, size);
+ auto* new_data = alignedMalloc<uchar8, 8>(roundUp(size_, 8));
+ memcpy(new_data, data_, size_);
bs.data = new_data;
- bs.size = size;
+ bs.size = size_;
bs.isOwner = true;
return bs; // hint: copy elision or move will happen
}
diff --git a/src/external/rawspeed/src/librawspeed/io/Endianness.h b/src/external/rawspeed/src/librawspeed/io/Endianness.h
index 777810767..7e05e3d77 100644
--- a/src/external/rawspeed/src/librawspeed/io/Endianness.h
+++ b/src/external/rawspeed/src/librawspeed/io/Endianness.h
@@ -24,6 +24,7 @@
#include "common/Common.h" // for uint32, ushort16, uint64, int32, short16
#include <cassert> // for assert
#include <cstring> // for memcpy
+// IWYU pragma: no_include "io/EndiannessTest.h"
namespace rawspeed {
@@ -66,25 +67,35 @@ inline Endianness getHostEndianness() {
#define BSWAP64(A) __builtin_bswap64(A)
#endif
-inline short16 getByteSwapped(short16 v) { return BSWAP16(v); }
-inline ushort16 getByteSwapped(ushort16 v) { return BSWAP16(v); }
-inline int32 getByteSwapped(int32 v) { return BSWAP32(v); }
-inline uint32 getByteSwapped(uint32 v) { return BSWAP32(v); }
-inline uint64 getByteSwapped(uint64 v) { return BSWAP64(v); }
+inline short16 getByteSwapped(short16 v) {
+ return static_cast<short16>(BSWAP16(static_cast<ushort16>(v)));
+}
+inline ushort16 getByteSwapped(ushort16 v) {
+ return static_cast<ushort16>(BSWAP16(v));
+}
+inline int32 getByteSwapped(int32 v) {
+ return static_cast<int32>(BSWAP32(static_cast<uint32>(v)));
+}
+inline uint32 getByteSwapped(uint32 v) {
+ return static_cast<uint32>(BSWAP32(v));
+}
+inline uint64 getByteSwapped(uint64 v) {
+ return BSWAP64(static_cast<uint64>(v));
+}
// the float/double versions use two memcpy which guarantee strict aliasing
// and are compiled into the same assembly as the popular union trick.
inline float getByteSwapped(float f) {
uint32 i;
memcpy(&i, &f, sizeof(i));
- i = BSWAP32(i);
+ i = getByteSwapped(i);
memcpy(&f, &i, sizeof(i));
return f;
}
inline double getByteSwapped(double d) {
uint64 i;
memcpy(&i, &d, sizeof(i));
- i = BSWAP64(i);
+ i = getByteSwapped(i);
memcpy(&d, &i, sizeof(i));
return d;
}
diff --git a/src/external/rawspeed/src/librawspeed/io/FileIOException.h b/src/external/rawspeed/src/librawspeed/io/FileIOException.h
index 4c0b70164..315a3bd2f 100644
--- a/src/external/rawspeed/src/librawspeed/io/FileIOException.h
+++ b/src/external/rawspeed/src/librawspeed/io/FileIOException.h
@@ -34,6 +34,6 @@ public:
};
#define ThrowFIE(...) \
- ThrowExceptionHelper(rawspeed::FileIOException, __VA_ARGS__);
+ ThrowExceptionHelper(rawspeed::FileIOException, __VA_ARGS__)
} // namespace rawspeed
diff --git a/src/external/rawspeed/src/librawspeed/io/FileReader.cpp b/src/external/rawspeed/src/librawspeed/io/FileReader.cpp
index bfa12ad05..fe1518cc1 100644
--- a/src/external/rawspeed/src/librawspeed/io/FileReader.cpp
+++ b/src/external/rawspeed/src/librawspeed/io/FileReader.cpp
@@ -20,14 +20,13 @@
*/
#include "io/FileReader.h"
-#include "io/Buffer.h" // for Buffer
-#include "io/FileIOException.h" // for FileIOException (ptr only), ThrowFIE
-#include <algorithm> // for move
-#include <cstdio> // for fclose, fseek, fopen, fread, ftell
+#include "io/Buffer.h" // for Buffer, Buffer::size_type
+#include "io/FileIOException.h" // for ThrowFIE
+#include <cstdio> // for fseek, fclose, feof, ferror, fopen
#include <fcntl.h> // for SEEK_END, SEEK_SET
#include <limits> // for numeric_limits
-#include <memory> // for unique_ptr
-#include <type_traits> // for make_unsigned
+#include <memory> // for unique_ptr, make_unique, operator==
+#include <utility> // for move
#if !(defined(__unix__) || defined(__APPLE__))
#ifndef NOMINMAX
diff --git a/src/external/rawspeed/src/librawspeed/metadata/CameraMetaData.cpp b/src/external/rawspeed/src/librawspeed/metadata/CameraMetaData.cpp
index bb60ed5f7..748caf6cd 100644
--- a/src/external/rawspeed/src/librawspeed/metadata/CameraMetaData.cpp
+++ b/src/external/rawspeed/src/librawspeed/metadata/CameraMetaData.cpp
@@ -62,7 +62,7 @@ CameraMetaData::CameraMetaData(const char *docname) {
continue;
// Create cameras for aliases.
- for (uint32 i = 0; i < cam->aliases.size(); i++) {
+ for (auto i = 0UL; i < cam->aliases.size(); i++) {
addCamera(std::make_unique<Camera>(cam, i));
}
}
diff --git a/src/external/rawspeed/src/librawspeed/metadata/CameraMetaData.h b/src/external/rawspeed/src/librawspeed/metadata/CameraMetaData.h
index 31cc442c3..0bc73ac53 100644
--- a/src/external/rawspeed/src/librawspeed/metadata/CameraMetaData.h
+++ b/src/external/rawspeed/src/librawspeed/metadata/CameraMetaData.h
@@ -21,11 +21,12 @@
#pragma once
#include "rawspeedconfig.h"
-#include "common/Common.h" // for uint32
-#include <map> // for map
-#include <memory> // for unique_ptr
-#include <string> // for string
-#include <tuple> // for tuple
+#include "common/Common.h" // for uint32
+#include "metadata/Camera.h" // for Camera
+#include <map> // for map
+#include <memory> // for unique_ptr
+#include <string> // for string
+#include <tuple> // for tuple
namespace rawspeed {
diff --git a/src/external/rawspeed/src/librawspeed/metadata/CameraSensorInfo.cpp b/src/external/rawspeed/src/librawspeed/metadata/CameraSensorInfo.cpp
index 50c90ff58..c75ceda27 100644
--- a/src/external/rawspeed/src/librawspeed/metadata/CameraSensorInfo.cpp
+++ b/src/external/rawspeed/src/librawspeed/metadata/CameraSensorInfo.cpp
@@ -19,8 +19,8 @@
*/
#include "metadata/CameraSensorInfo.h"
-#include <algorithm> // for move
-#include <vector> // for vector
+#include <utility> // for move
+#include <vector> // for vector
using std::vector;
diff --git a/src/external/rawspeed/src/librawspeed/metadata/ColorFilterArray.cpp b/src/external/rawspeed/src/librawspeed/metadata/ColorFilterArray.cpp
index afd1249d5..0e9b865c1 100644
--- a/src/external/rawspeed/src/librawspeed/metadata/ColorFilterArray.cpp
+++ b/src/external/rawspeed/src/librawspeed/metadata/ColorFilterArray.cpp
@@ -20,15 +20,15 @@
#include "metadata/ColorFilterArray.h"
#include "common/Common.h" // for writeLog, uint32, DEBUG_PR...
-#include "common/Point.h" // for iPoint2D
+#include "common/Point.h" // for iPoint2D, iPoint2D::value_...
#include "decoders/RawDecoderException.h" // for ThrowRDE
#include <algorithm> // for fill
+#include <cmath> // for abs
#include <cstdarg> // for va_arg, va_end, va_list
#include <cstdlib> // for size_t, abs
#include <map> // for map
#include <stdexcept> // for out_of_range
-#include <string> // for string, allocator
-// IWYU pragma: no_include <bits/std_abs.h>
+#include <string> // for string
using std::vector;
using std::string;
@@ -78,7 +78,7 @@ void ColorFilterArray::setCFA( iPoint2D in_size, ... )
}
va_list arguments;
va_start(arguments, in_size);
- for (uint32 i = 0; i < size.area(); i++ ) {
+ for (auto i = 0UL; i < size.area(); i++) {
cfa[i] = static_cast<CFAColor>(va_arg(arguments, int));
}
va_end (arguments);
diff --git a/src/external/rawspeed/src/librawspeed/parsers/CiffParser.cpp b/src/external/rawspeed/src/librawspeed/parsers/CiffParser.cpp
index 4383aaa74..c32700b0d 100644
--- a/src/external/rawspeed/src/librawspeed/parsers/CiffParser.cpp
+++ b/src/external/rawspeed/src/librawspeed/parsers/CiffParser.cpp
@@ -21,18 +21,19 @@
*/
#include "parsers/CiffParser.h"
-#include "common/Common.h" // for make_unique, trimSpaces
+#include "common/Common.h" // for trimSpaces, uint32, ushort16
#include "decoders/CrwDecoder.h" // for CrwDecoder
#include "decoders/RawDecoder.h" // for RawDecoder
#include "io/ByteStream.h" // for ByteStream
-#include "io/Endianness.h" // for getHostEndianness, Endianne...
-#include "parsers/CiffParserException.h" // for CiffParserException (ptr only)
+#include "io/Endianness.h" // for Endianness, Endianness::little
+#include "parsers/CiffParserException.h" // for ThrowCPE
#include "tiff/CiffEntry.h" // for CiffEntry
#include "tiff/CiffIFD.h" // for CiffIFD
-#include "tiff/CiffTag.h" // for CiffTag::CIFF_MAKEMODEL
-#include <memory> // for unique_ptr, default_delete
-#include <string> // for operator==, basic_string
-#include <utility> // for move, pair
+#include "tiff/CiffTag.h" // for CIFF_MAKEMODEL
+#include <memory> // for unique_ptr, make_unique
+#include <string> // for operator==, string
+#include <utility> // for move
+#include <vector> // for vector
using std::string;
diff --git a/src/external/rawspeed/src/librawspeed/parsers/FiffParser.cpp b/src/external/rawspeed/src/librawspeed/parsers/FiffParser.cpp
index 6d4df19eb..d90d3b90a 100644
--- a/src/external/rawspeed/src/librawspeed/parsers/FiffParser.cpp
+++ b/src/external/rawspeed/src/librawspeed/parsers/FiffParser.cpp
@@ -21,22 +21,22 @@
*/
#include "parsers/FiffParser.h"
-#include "common/Common.h" // for make_unique, uint32, uchar8
+#include "common/Common.h" // for uint32, ushort16
#include "decoders/RafDecoder.h" // for RafDecoder
#include "decoders/RawDecoder.h" // for RawDecoder
-#include "io/Buffer.h" // for Buffer
+#include "io/Buffer.h" // for Buffer, DataBuffer
#include "io/ByteStream.h" // for ByteStream
-#include "io/Endianness.h" // for getU32BE, getHostEndianness
+#include "io/Endianness.h" // for Endianness, Endianness::big
#include "parsers/FiffParserException.h" // for ThrowFPE
#include "parsers/RawParser.h" // for RawParser
-#include "parsers/TiffParser.h" // for TiffParser::parse, TiffParser::makeDecoder
+#include "parsers/TiffParser.h" // for TiffParser
#include "parsers/TiffParserException.h" // for TiffParserException
-#include "tiff/TiffEntry.h" // for TiffEntry, TiffDataType::TI...
-#include "tiff/TiffIFD.h" // for TiffIFD, TiffRootIFD, TiffI...
-#include "tiff/TiffTag.h" // for TiffTag, TiffTag::FUJIOLDWB
-#include <algorithm> // for move
+#include "tiff/TiffEntry.h" // for TiffEntry, TIFF_SHORT, TIFF...
+#include "tiff/TiffIFD.h" // for TiffIFD, TiffRootIFDOwner
+#include "tiff/TiffTag.h" // for FUJIOLDWB, FUJI_STRIPBYTECO...
#include <limits> // for numeric_limits
-#include <memory> // for default_delete, unique_ptr
+#include <memory> // for make_unique, unique_ptr
+#include <utility> // for move
using std::numeric_limits;
diff --git a/src/external/rawspeed/src/librawspeed/parsers/TiffParser.cpp b/src/external/rawspeed/src/librawspeed/parsers/TiffParser.cpp
index 221fd35a1..a74bbee4e 100644
--- a/src/external/rawspeed/src/librawspeed/parsers/TiffParser.cpp
+++ b/src/external/rawspeed/src/librawspeed/parsers/TiffParser.cpp
@@ -22,8 +22,8 @@
*/
#include "parsers/TiffParser.h"
-#include "common/Common.h" // for make_unique, trimSpaces
-#include "common/NORangesSet.h" // for NORangesSet
+#include "common/Common.h" // for uint32, ushort16
+#include "common/NORangesSet.h" // for set
#include "decoders/ArwDecoder.h" // for ArwDecoder
#include "decoders/Cr2Decoder.h" // for Cr2Decoder
#include "decoders/DcrDecoder.h" // for DcrDecoder
@@ -37,17 +37,16 @@
#include "decoders/NefDecoder.h" // for NefDecoder
#include "decoders/OrfDecoder.h" // for OrfDecoder
#include "decoders/PefDecoder.h" // for PefDecoder
-#include "decoders/RafDecoder.h" // for RafDecoder
#include "decoders/RawDecoder.h" // for RawDecoder
#include "decoders/Rw2Decoder.h" // for Rw2Decoder
#include "decoders/SrwDecoder.h" // for SrwDecoder
#include "decoders/ThreefrDecoder.h" // for ThreefrDecoder
#include "io/ByteStream.h" // for ByteStream
-#include "parsers/TiffParserException.h" // for TiffParserException
+#include "parsers/TiffParserException.h" // for ThrowTPE
#include <cassert> // for assert
#include <cstdint> // for UINT32_MAX
-#include <memory> // for unique_ptr
-#include <string> // for operator==, basic_string
+#include <memory> // for make_unique, unique_ptr
+#include <string> // for string
#include <tuple> // for tie, tuple
#include <vector> // for vector
// IWYU pragma: no_include <ext/alloc_traits.h>
diff --git a/src/external/rawspeed/src/librawspeed/tiff/CiffEntry.cpp b/src/external/rawspeed/src/librawspeed/tiff/CiffEntry.cpp
index 5d762c84a..329b71151 100644
--- a/src/external/rawspeed/src/librawspeed/tiff/CiffEntry.cpp
+++ b/src/external/rawspeed/src/librawspeed/tiff/CiffEntry.cpp
@@ -21,11 +21,13 @@
*/
#include "tiff/CiffEntry.h"
-#include "common/Common.h" // for uchar8, uint32, ushort16
-#include "common/NORangesSet.h" // for NORangesSet
+#include "common/Common.h" // for uint32, uchar8, ushort16
+#include "common/NORangesSet.h" // for set
+#include "io/Buffer.h" // for Buffer
#include "io/ByteStream.h" // for ByteStream
-#include "parsers/CiffParserException.h" // for CiffParserException (ptr only)
-#include <string> // for string, allocator
+#include "parsers/CiffParserException.h" // for ThrowCPE
+#include <string> // for string
+#include <utility> // for pair
#include <vector> // for vector
using std::string;
diff --git a/src/external/rawspeed/src/librawspeed/tiff/CiffEntry.h b/src/external/rawspeed/src/librawspeed/tiff/CiffEntry.h
index 788d48ac5..2e0873219 100644
--- a/src/external/rawspeed/src/librawspeed/tiff/CiffEntry.h
+++ b/src/external/rawspeed/src/librawspeed/tiff/CiffEntry.h
@@ -23,7 +23,7 @@
#pragma once
#include "common/Common.h" // for uint32, uchar8, ushort16
-#include "common/NORangesSet.h" // for NORangesSet
+#include "common/NORangesSet.h" // for set
#include "io/ByteStream.h" // for ByteStream
#include "tiff/CiffTag.h" // for CiffTag
#include <string> // for string
@@ -31,7 +31,8 @@
namespace rawspeed {
-class CiffIFD;
+class Buffer;
+class CiffIFD; // IWYU pragma: keep
/*
* Tag data type information.
diff --git a/src/external/rawspeed/src/librawspeed/tiff/CiffIFD.cpp b/src/external/rawspeed/src/librawspeed/tiff/CiffIFD.cpp
index 8c4b4361d..17ac74be1 100644
--- a/src/external/rawspeed/src/librawspeed/tiff/CiffIFD.cpp
+++ b/src/external/rawspeed/src/librawspeed/tiff/CiffIFD.cpp
@@ -21,19 +21,17 @@
*/
#include "tiff/CiffIFD.h"
-#include "common/Common.h" // for uint32, ushort16, isIn
-#include "common/NORangesSet.h" // for NORangesSet
-#include "common/RawspeedException.h" // for RawspeedException
+#include "common/Common.h" // for isIn, uint32, ushort16
+#include "common/NORangesSet.h" // for set
#include "io/ByteStream.h" // for ByteStream
-#include "io/IOException.h" // for IOException
-#include "parsers/CiffParserException.h" // for ThrowCPE, CiffParserException
-#include "tiff/CiffEntry.h" // for CiffEntry, CiffDataType::CI...
+#include "parsers/CiffParserException.h" // for ThrowCPE
#include <cassert> // for assert
-#include <map> // for map, _Rb_tree_iterator
-#include <memory> // for unique_ptr
-#include <string> // for allocator, operator==, string
-#include <utility> // for pair
-#include <vector> // for vector
+#include <initializer_list> // for initializer_list
+#include <map> // for map, _Rb_tree_const_iterator
+#include <memory> // for unique_ptr, make_unique
+#include <string> // for operator==, string
+#include <utility> // for move, pair
+#include <vector> // for vector, vector<>::size_type
using std::string;
using std::vector;
@@ -41,6 +39,8 @@ using std::unique_ptr;
namespace rawspeed {
+class Buffer;
+
void CiffIFD::parseIFDEntry(NORangesSet<Buffer>* valueDatas,
const ByteStream* valueData,
ByteStream* dirEntries) {
diff --git a/src/external/rawspeed/src/librawspeed/tiff/CiffIFD.h b/src/external/rawspeed/src/librawspeed/tiff/CiffIFD.h
index e5e05e959..531835321 100644
--- a/src/external/rawspeed/src/librawspeed/tiff/CiffIFD.h
+++ b/src/external/rawspeed/src/librawspeed/tiff/CiffIFD.h
@@ -23,7 +23,7 @@
#pragma once
#include "common/Common.h" // for uint32
-#include "common/NORangesSet.h" // for NORangesSet
+#include "common/NORangesSet.h" // for set
#include "tiff/CiffEntry.h" // IWYU pragma: keep
#include "tiff/CiffTag.h" // for CiffTag
#include <map> // for map
@@ -33,6 +33,7 @@
namespace rawspeed {
+class Buffer;
class ByteStream;
class CiffIFD final {
diff --git a/src/external/rawspeed/src/librawspeed/tiff/TiffEntry.cpp b/src/external/rawspeed/src/librawspeed/tiff/TiffEntry.cpp
index 44fdba316..9c31f8264 100644
--- a/src/external/rawspeed/src/librawspeed/tiff/TiffEntry.cpp
+++ b/src/external/rawspeed/src/librawspeed/tiff/TiffEntry.cpp
@@ -21,15 +21,16 @@
*/
#include "tiff/TiffEntry.h"
-#include "common/Common.h" // for uint32, ushort16, int32
+#include "common/Common.h" // for uint32, short16, ushort16
#include "parsers/TiffParserException.h" // for ThrowTPE
#include "tiff/TiffIFD.h" // for TiffIFD, TiffRootIFD
-#include "tiff/TiffTag.h" // for ::DNGPRIVATEDATA, ::EXIFIFD...
-#include <algorithm> // for move
+#include "tiff/TiffTag.h" // for TiffTag, DNGPRIVATEDATA
#include <cassert> // for assert
#include <cstdint> // for UINT32_MAX
#include <cstring> // for strnlen
+#include <initializer_list> // for initializer_list
#include <string> // for string
+#include <utility> // for move
using std::string;
@@ -38,8 +39,8 @@ namespace rawspeed {
class DataBuffer;
// order see TiffDataType
-const uint32 TiffEntry::datashifts[] = {0, 0, 0, 1, 2, 3, 0,
- 0, 1, 2, 3, 2, 3, 2};
+const std::array<uint32, 14> TiffEntry::datashifts = {0, 0, 0, 1, 2, 3, 0,
+ 0, 1, 2, 3, 2, 3, 2};
// 0-1-2-3-4-5-6-7-8-9-10-11-12-13
TiffEntry::TiffEntry(TiffIFD* parent_, ByteStream* bs) : parent(parent_) {
diff --git a/src/external/rawspeed/src/librawspeed/tiff/TiffEntry.h b/src/external/rawspeed/src/librawspeed/tiff/TiffEntry.h
index 93edcc3e3..3d8825026 100644
--- a/src/external/rawspeed/src/librawspeed/tiff/TiffEntry.h
+++ b/src/external/rawspeed/src/librawspeed/tiff/TiffEntry.h
@@ -112,7 +112,7 @@ public:
const DataBuffer& getRootIfdData() const;
protected:
- static const uint32 datashifts[];
+ static const std::array<uint32, 14> datashifts;
};
} // namespace rawspeed
diff --git a/src/external/rawspeed/src/librawspeed/tiff/TiffIFD.cpp b/src/external/rawspeed/src/librawspeed/tiff/TiffIFD.cpp
index 0cdcce9db..4a0a08d09 100644
--- a/src/external/rawspeed/src/librawspeed/tiff/TiffIFD.cpp
+++ b/src/external/rawspeed/src/librawspeed/tiff/TiffIFD.cpp
@@ -22,18 +22,18 @@
*/
#include "tiff/TiffIFD.h"
-#include "common/Common.h" // for getHostEndianness, uint32, make_...
-#include "common/NORangesSet.h" // for NORangesSet
+#include "common/Common.h" // for trimSpaces, uint32
+#include "common/NORangesSet.h" // for set
#include "common/RawspeedException.h" // for RawspeedException
#include "io/IOException.h" // for IOException
#include "tiff/TiffEntry.h" // for TiffEntry
-#include "tiff/TiffTag.h" // for TiffTag, ::DNGPRIVATEDATA, ::EXI...
-#include <algorithm> // for move
+#include "tiff/TiffTag.h" // for TiffTag, MAKE, DNGPRIVATEDATA
+#include <cassert> // for assert
#include <cstdint> // for UINT32_MAX
-#include <map> // for map, _Rb_tree_const_iterator, al...
-#include <memory> // for default_delete, unique_ptr
-#include <string> // for operator==, string, basic_string
-#include <utility> // for pair
+#include <map> // for map, _Rb_tree_const_iterator
+#include <memory> // for unique_ptr, make_unique
+#include <string> // for string, operator==
+#include <utility> // for move, pair
#include <vector> // for vector
using std::string;
diff --git a/src/external/rawspeed/src/librawspeed/tiff/TiffTag.h b/src/external/rawspeed/src/librawspeed/tiff/TiffTag.h
index 4d8a2320c..78129f0b6 100644
--- a/src/external/rawspeed/src/librawspeed/tiff/TiffTag.h
+++ b/src/external/rawspeed/src/librawspeed/tiff/TiffTag.h
@@ -35,6 +35,8 @@ enum TiffTag {
PANASONIC_ISO_SPEED = 23,
NEWSUBFILETYPE = 0x00FE,
SUBFILETYPE = 0x00FF,
+ PANASONIC_BITSPERSAMPLE = 0xa,
+ PANASONIC_RAWFORMAT = 0x2d,
MAKERNOTE_ALT = 0x2e,
IMAGEWIDTH = 0x0100,
@@ -349,6 +351,8 @@ enum TiffTag {
KODAK_KDC_OFFSET = 0xFD04,
KODAK_KDC_WIDTH = 0xFD00,
KODAK_KDC_HEIGHT = 0xFD01,
+ KODAK_KDC_SENSOR_WIDTH = 0xFA13,
+ KODAK_KDC_SENSOR_HEIGHT = 0xFA14,
KODAK_IFD2 = 0xFE00,
};