Merge commit '638ecc4cde79b0296f2e04f683ca4cb881c28f36' as 'rtengine/libraw'

This commit is contained in:
Lawrence Lee
2023-11-12 11:49:00 -08:00
213 changed files with 77043 additions and 0 deletions

View File

@@ -0,0 +1,69 @@
# About RawSpeed v3
The current version of the RawSpeed library (https://github.com/darktable-org/rawspeed ) does not have a version number, we call it "version 3" to distinguish it from RawSpeed/master, the version number is taken from darktable 3.x (which uses this library).
This library provides faster decoding of some RAW formats (even faster than RawSpeed v1), the difference can be tens of percent (without using OpenMP) for Huffman-compressed files (Canon CR2, Nikon NEF, etc).
Unfortunately, the RawSpeed-v3 source code is constantly changing and this is due not so much to the development of the library (support for new cameras, formats, etc.), but to the fact that the current maintainer is using it as an aid in self-development as a programmer.
They are extremely reluctant to accept 3rd-party patches to this library, therefore, the fixes necessary for correct work with LibRaw have been added to the LibRaw distribution (see below). All our patches, of course, are suitable only for a specific version (commit-id) of RawSpeed-v3, if you want to use a different version, you will have to adjust them.
# Building RawSpeed v3 and C-API wrapper
## Preparing the source
1. Take a specific commit from github
https://github.com/darktable-org/rawspeed/commit/de70ef5fbc62cde91009c8cff7a206272abe631e
2. Apply the following patches from LibRaw/RawSpeed3/patches folder:
* **01.CameraMeta-extensibility.patch** - allows derived classes from CameraMeta, which allows loading camera descriptions not only from a disk file.
* **02.Makernotes-processing.patch** - fixes an error in processing the Makernotes tag.
* **03.remove-limits-and-logging.patch** - removes debug printing and file size limits. This patch is optional, but if you are going to decode files from cameras that were not available at the time a particular version of RawSpeed was created, then this patch can be useful.
* **04.clang-cl-compatibility.patch -** fixes for compatibility with Microsoft C++ library.
## Building the RawSpeed-v3 library
We **do not** offer advice on building RawSpeed3, if you need such advice please contact the maintainer of the library. At a minimum, it **can be** compiled with Clang (XCode) on macOS and clang-cl (MSVC) on Windows.
Use your favorite build system. Files for CMake come with RawSpeed, but any other build system can be used (in that case you probably will need to create your own rawspeedconfig.h instead of one created via CMake).
In our projects we use RawSpeed-v3 without OpenMP.
## Building the C-API wrapper
To simplify the integration with LibRaw, we have implemented a simple wrapper with a C interface, which hides everything unnecessary, thus:
* To build LibRaw (with RawSpeed-v3 support) you do not need access to RawSpeed .h-files
* When building LibRaw and RawSpeed-v3 using different compilers there is no issue with C++ name mangling.
The wrapper sources are in the **LibRaw/RawSpeed3/rawspeed3_c_api folder**, they include four files:
1. **rawspeed3_capi.h** - header file
2. **rawspeed3_capi.cpp** - wrapper sources
3. **rsxml2c.sh** - shell script that will convert RawSpeed/data/cameras.xml to a C++ file containing camera definitions
4. **rawspeed3_capi_test.cpp** - test program for checking the build correctness and operation ability.
The wrapper provides simple *decode only* interface (init library, decode RAW passed via buffer, free decoded file buffer, release the library) it is self-documented via comments in the rawspeed3_capi.h file.
To make a file with camera definitions, run the command (you can add it to the build system):
`sh ./rawspeed3_c_api/rsxml2c.sh < path/to/RawSpeed/data/cameras.xml > rawspeed3_c_api/cameras.cpp`
The **rsxml2c.sh** script requires **cat**, **tr**, and **sed** unix command-line utilities installed, there is no specific version requirements.
Add the resulting file (LibRaw/RawSpeed3/rawspeed3_c_api/cameras.cpp) and LibRaw/RawSpeed3/rawspeed3_c_api/rawspeed3_capi.cpp, to the build of the RawSpeed-v3 (dynamic) library, which you learned to build in the previous step.
If building Windows DLL: rawspeed3_capi.cpp should be compiled with -DRAWSPEED_BUILDLIB to create dll export entries automatically.
To check that everything works, you can use the LibRaw/RawSpeed3/rawspeed3_c_api/rawspeed3_capi_test.cpp test program, it should be possible to build it and link with RawSpeed-v3 (+ C-API); and after that this test program should be ready to decode RAW files passed to it from command line.
# Building LibRaw with RawSpeed-v3 support
When building, specify the following parameters
* LibRaw/RawSpeed3/rawspeed3_c_api to the search path for include files
* Specify preprocessor flags -DUSE_RAWSPEED3 -DUSE_RAWSPEED_BITS:
* USE_RAWSPEED3 enables the use of RawSpeed-v3
* USE_RAWSPEED_BITS enables (a more granulated) control of RawSpeed-v3 / RawSpeed processing
* set the RawSpeed-v3 (+ C-API) library, obtained in the previous steps, as an input linker file
# Using LibRaw with RawSpeed-v3 Support
Use LibRaw as usual. Enable RawSpeed3 use by setting bits in imgdata.rawparams.userawspeed (LIBRAW_RAWSPEEDV3_USE, LIBRAW_RAWSPEEDV3_IGNOREERRORS, LIBRAW_RAWSPEEDV3_FAILONUNKNOWN)
If RawSpeed was set as the decoder the following bits will be set in imgdata.processwarnings:
* LIBRAW_WARN_RAWSPEED3_PROCESSED - if decoding was successful
* LIBRAW_WARN_RAWSPEED3_PROBLEM - if decoding attempt failed
(flags and bits are described in LibRaw's Changelog)
With RawSpeed-v3, the entire RAW file is read into the memory buffer (as it is with RawSpeed version 1), so it increases LibRaw memory footprint.

View File

@@ -0,0 +1,13 @@
diff --git a/src/librawspeed/metadata/CameraMetaData.h b/src/librawspeed/metadata/CameraMetaData.h
index c2f6f1dd..13cab9c9 100644
--- a/src/librawspeed/metadata/CameraMetaData.h
+++ b/src/librawspeed/metadata/CameraMetaData.h
@@ -41,7 +41,7 @@ struct CameraId {
}
};
-class CameraMetaData {
+class CameraMetaData final {
public:
CameraMetaData() = default;

View File

@@ -0,0 +1,36 @@
diff --git a/src/librawspeed/tiff/TiffIFD.cpp b/src/librawspeed/tiff/TiffIFD.cpp
index e732eae2..05251dd9 100644
--- a/src/librawspeed/tiff/TiffIFD.cpp
+++ b/src/librawspeed/tiff/TiffIFD.cpp
@@ -143,6 +143,7 @@ TiffRootIFDOwner TiffIFD::parseMakerNote(NORangesSet<Buffer>* ifds,
string make = makeEntry != nullptr ? trimSpaces(makeEntry->getString()) : "";
ByteStream bs = t->getData();
+ auto bufbegin = bs.begin() + bs.getPosition();
// helper function for easy setup of ByteStream buffer for the different maker note types
// 'rebase' means position 0 of new stream equals current position
@@ -159,7 +160,9 @@ TiffRootIFDOwner TiffIFD::parseMakerNote(NORangesSet<Buffer>* ifds,
bs.skipBytes(newPosition);
};
- if (bs.hasPrefix("AOC\0", 4)) {
+ if (bs.hasPrefix("LSI1\0", 5)) { // Skip LSI1 makernotes
+ return std::make_unique<TiffRootIFD>(this, ifds, bs, UINT32_MAX); // UINT32_MAX offset => special handling, empty IFD
+ } else if (bs.hasPrefix("AOC\0", 4)) {
setup(false, 6, 4, "Pentax makernote");
} else if (bs.hasPrefix("PENTAX", 6)) {
setup(true, 10, 8, "Pentax makernote");
@@ -197,6 +200,12 @@ TiffRootIFDOwner TiffIFD::parseMakerNote(NORangesSet<Buffer>* ifds,
}
}
+ auto readed = bs.begin() - bufbegin + bs.getPosition();
+ ByteStream bscheck(bs);
+ const auto IFDSize = 6 + 12 * bscheck.getU16();
+
+ if(IFDSize > t->count - readed) // IFDSize too big, probably binary Makernotes dir, not TIFF-like, could not be handled by TiffRootIFD reader
+ return std::make_unique<TiffRootIFD>(this, ifds, bs, UINT32_MAX); // // UINT32_MAX offset => special handling, empty IFD
// Attempt to parse the rest as an IFD
return std::make_unique<TiffRootIFD>(this, ifds, bs, bs.getPosition());
}

View File

@@ -0,0 +1,245 @@
diff --git a/src/librawspeed/common/Common.cpp b/src/librawspeed/common/Common.cpp
index 8c8c5663..d9b5e463 100644
--- a/src/librawspeed/common/Common.cpp
+++ b/src/librawspeed/common/Common.cpp
@@ -36,6 +36,7 @@ writeLog(DEBUG_PRIO priority, const char* format, ...) {
#else
void writeLog(DEBUG_PRIO priority, const char* format, ...) {
+#if 0
#ifndef _DEBUG
if (priority < DEBUG_PRIO_INFO)
#endif // _DEBUG
@@ -55,6 +56,7 @@ void writeLog(DEBUG_PRIO priority, const char* format, ...) {
if (priority < DEBUG_PRIO_INFO)
#endif // _DEBUG
fprintf(stdout, "%s", "\n");
+#endif
}
#endif
diff --git a/src/librawspeed/common/RawspeedException.h b/src/librawspeed/common/RawspeedException.h
index 33b9cc29..a9f503a7 100644
--- a/src/librawspeed/common/RawspeedException.h
+++ b/src/librawspeed/common/RawspeedException.h
@@ -45,12 +45,13 @@ template <typename T>
"Don't have thread-local-storage! Exception text may be garbled if used multithreaded"
static char buf[bufSize];
#endif
-
+#if 0
va_list val;
va_start(val, fmt);
vsnprintf(buf.data(), sizeof(buf), fmt, val);
va_end(val);
writeLog(DEBUG_PRIO_EXTRA, "EXCEPTION: %s", buf.data());
+#endif
throw T(buf.data());
}
diff --git a/src/librawspeed/decoders/ArwDecoder.cpp b/src/librawspeed/decoders/ArwDecoder.cpp
index f1d5a63c..2025d260 100644
--- a/src/librawspeed/decoders/ArwDecoder.cpp
+++ b/src/librawspeed/decoders/ArwDecoder.cpp
@@ -186,8 +186,8 @@ RawImage ArwDecoder::decodeRawInternal() {
}
}
- if (width == 0 || height == 0 || height % 2 != 0 || width > 9600 ||
- height > 6376)
+ if (width == 0 || height == 0 || height % 2 != 0 /* || width > 9600 ||
+ height > 6376 */)
ThrowRDE("Unexpected image dimensions found: (%u; %u)", width, height);
bool arw1 = uint64_t(counts->getU32()) * 8 != width * height * bitPerPixel;
@@ -241,7 +241,7 @@ void ArwDecoder::DecodeUncompressed(const TiffIFD* raw) {
mRaw->dim = iPoint2D(width, height);
- if (width == 0 || height == 0 || width > 9600 || height > 6376)
+ if (width == 0 || height == 0 /* || width > 9600 || height > 6376 */)
ThrowRDE("Unexpected image dimensions found: (%u; %u)", width, height);
if (c2 == 0)
diff --git a/src/librawspeed/decoders/IiqDecoder.cpp b/src/librawspeed/decoders/IiqDecoder.cpp
index 31c460d9..61b04e1a 100644
--- a/src/librawspeed/decoders/IiqDecoder.cpp
+++ b/src/librawspeed/decoders/IiqDecoder.cpp
@@ -185,7 +185,7 @@ RawImage IiqDecoder::decodeRawInternal() {
}
// FIXME: could be wrong. max "active pixels" in "Sensor+" mode - "101 MP"
- if (width == 0 || height == 0 || width > 11976 || height > 8854)
+ if (width == 0 || height == 0 /* || width > 11976 || height > 8854 */)
ThrowRDE("Unexpected image dimensions found: (%u; %u)", width, height);
if (split_col > width || split_row > height)
diff --git a/src/librawspeed/decoders/MosDecoder.cpp b/src/librawspeed/decoders/MosDecoder.cpp
index 9f01a11c..db4b8f50 100644
--- a/src/librawspeed/decoders/MosDecoder.cpp
+++ b/src/librawspeed/decoders/MosDecoder.cpp
@@ -113,7 +113,7 @@ RawImage MosDecoder::decodeRawInternal() {
uint32_t height = raw->getEntry(IMAGELENGTH)->getU32();
// FIXME: could be wrong. max "active pixels" - "80 MP"
- if (width == 0 || height == 0 || width > 10328 || height > 7760)
+ if (width == 0 || height == 0 /* || width > 10328 || height > 7760 */)
ThrowRDE("Unexpected image dimensions found: (%u; %u)", width, height);
mRaw->dim = iPoint2D(width, height);
diff --git a/src/librawspeed/decoders/NefDecoder.cpp b/src/librawspeed/decoders/NefDecoder.cpp
index 222c62f0..7314ca15 100644
--- a/src/librawspeed/decoders/NefDecoder.cpp
+++ b/src/librawspeed/decoders/NefDecoder.cpp
@@ -214,7 +214,7 @@ void NefDecoder::DecodeUncompressed() {
mRaw->dim = iPoint2D(width, height);
- if (width == 0 || height == 0 || width > 8288 || height > 5520)
+ if (width == 0 || height == 0 /* || width > 8288 || height > 5520 */)
ThrowRDE("Unexpected image dimensions found: (%u; %u)", width, height);
if (counts->count != offsets->count) {
@@ -370,8 +370,8 @@ void NefDecoder::DecodeSNefUncompressed() {
uint32_t width = raw->getEntry(IMAGEWIDTH)->getU32();
uint32_t height = raw->getEntry(IMAGELENGTH)->getU32();
- if (width == 0 || height == 0 || width % 2 != 0 || width > 3680 ||
- height > 2456)
+ if (width == 0 || height == 0 || width % 2 != 0 /* || width > 3680 ||
+ height > 2456 */)
ThrowRDE("Unexpected image dimensions found: (%u; %u)", width, height);
mRaw->dim = iPoint2D(width, height);
diff --git a/src/librawspeed/decoders/OrfDecoder.cpp b/src/librawspeed/decoders/OrfDecoder.cpp
index 7eb1a901..de557d5f 100644
--- a/src/librawspeed/decoders/OrfDecoder.cpp
+++ b/src/librawspeed/decoders/OrfDecoder.cpp
@@ -109,7 +109,7 @@ RawImage OrfDecoder::decodeRawInternal() {
uint32_t width = raw->getEntry(IMAGEWIDTH)->getU32();
uint32_t height = raw->getEntry(IMAGELENGTH)->getU32();
- if (!width || !height || width % 2 != 0 || width > 10400 || height > 7796)
+ if (!width || !height || width % 2 != 0 /* || width > 10400 || height > 7796 */ )
ThrowRDE("Unexpected image dimensions found: (%u; %u)", width, height);
mRaw->dim = iPoint2D(width, height);
diff --git a/src/librawspeed/decoders/RafDecoder.cpp b/src/librawspeed/decoders/RafDecoder.cpp
index 5baf02b9..27e67e7a 100644
--- a/src/librawspeed/decoders/RafDecoder.cpp
+++ b/src/librawspeed/decoders/RafDecoder.cpp
@@ -79,7 +79,7 @@ RawImage RafDecoder::decodeRawInternal() {
} else
ThrowRDE("Unable to locate image size");
- if (width == 0 || height == 0 || width > 11808 || height > 8754)
+ if (width == 0 || height == 0 /* || width > 11808 || height > 8754 */ )
ThrowRDE("Unexpected image dimensions found: (%u; %u)", width, height);
if (raw->hasEntry(FUJI_LAYOUT)) {
@@ -334,7 +334,7 @@ int RafDecoder::isCompressed() {
} else
ThrowRDE("Unable to locate image size");
- if (width == 0 || height == 0 || width > 11808 || height > 8754)
+ if (width == 0 || height == 0 /* || width > 11808 || height > 8754 */)
ThrowRDE("Unexpected image dimensions found: (%u; %u)", width, height);
uint32_t count = raw->getEntry(FUJI_STRIPBYTECOUNTS)->getU32();
diff --git a/src/librawspeed/decoders/RawDecoder.cpp b/src/librawspeed/decoders/RawDecoder.cpp
index a69727f6..e5315a42 100644
--- a/src/librawspeed/decoders/RawDecoder.cpp
+++ b/src/librawspeed/decoders/RawDecoder.cpp
@@ -62,7 +62,7 @@ void RawDecoder::decodeUncompressed(const TiffIFD *rawIFD, BitOrder order) {
uint32_t height = rawIFD->getEntry(IMAGELENGTH)->getU32();
uint32_t bitPerPixel = rawIFD->getEntry(BITSPERSAMPLE)->getU32();
- if (width == 0 || height == 0 || width > 5632 || height > 3720)
+ if (width == 0 || height == 0 /* || width > 5632 || height > 3720 */)
ThrowRDE("Unexpected image dimensions found: (%u; %u)", width, height);
mRaw->dim = iPoint2D(width, height);
diff --git a/src/librawspeed/decoders/Rw2Decoder.cpp b/src/librawspeed/decoders/Rw2Decoder.cpp
index 0e9d111d..a54de998 100644
--- a/src/librawspeed/decoders/Rw2Decoder.cpp
+++ b/src/librawspeed/decoders/Rw2Decoder.cpp
@@ -72,7 +72,7 @@ RawImage Rw2Decoder::decodeRawInternal() {
uint32_t width = raw->getEntry(static_cast<TiffTag>(2))->getU16();
if (isOldPanasonic) {
- if (width == 0 || height == 0 || width > 4330 || height > 2751)
+ if (width == 0 || height == 0 /* || width > 4330 || height > 2751 */)
ThrowRDE("Unexpected image dimensions found: (%u; %u)", width, height);
TiffEntry *offsets = raw->getEntry(STRIPOFFSETS);
diff --git a/src/librawspeed/decompressors/HasselbladDecompressor.cpp b/src/librawspeed/decompressors/HasselbladDecompressor.cpp
index 0d650065..aaa70fb5 100644
--- a/src/librawspeed/decompressors/HasselbladDecompressor.cpp
+++ b/src/librawspeed/decompressors/HasselbladDecompressor.cpp
@@ -41,8 +41,8 @@ HasselbladDecompressor::HasselbladDecompressor(const ByteStream& bs,
ThrowRDE("Unexpected component count / data type");
// 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 > 12000 || mRaw->dim.y > 8816) {
+ if (mRaw->dim.x == 0 || mRaw->dim.y == 0 || mRaw->dim.x % 2 != 0 /* ||
+ mRaw->dim.x > 12000 || mRaw->dim.y > 8816 */) {
ThrowRDE("Unexpected image dimensions found: (%u; %u)", mRaw->dim.x,
mRaw->dim.y);
}
diff --git a/src/librawspeed/decompressors/NikonDecompressor.cpp b/src/librawspeed/decompressors/NikonDecompressor.cpp
index ca39cd0a..54568243 100644
--- a/src/librawspeed/decompressors/NikonDecompressor.cpp
+++ b/src/librawspeed/decompressors/NikonDecompressor.cpp
@@ -442,8 +442,8 @@ NikonDecompressor::NikonDecompressor(const RawImage& raw, ByteStream metadata,
mRaw->getBpp() != sizeof(uint16_t))
ThrowRDE("Unexpected component count / data type");
- if (mRaw->dim.x == 0 || mRaw->dim.y == 0 || mRaw->dim.x % 2 != 0 ||
- mRaw->dim.x > 8288 || mRaw->dim.y > 5520)
+ if (mRaw->dim.x == 0 || mRaw->dim.y == 0 || mRaw->dim.x % 2 != 0 /* ||
+ mRaw->dim.x > 8288 || mRaw->dim.y > 5520 */)
ThrowRDE("Unexpected image dimensions found: (%u; %u)", mRaw->dim.x,
mRaw->dim.y);
diff --git a/src/librawspeed/decompressors/OlympusDecompressor.cpp b/src/librawspeed/decompressors/OlympusDecompressor.cpp
index b859b562..dc8aa0bc 100644
--- a/src/librawspeed/decompressors/OlympusDecompressor.cpp
+++ b/src/librawspeed/decompressors/OlympusDecompressor.cpp
@@ -56,7 +56,7 @@ OlympusDecompressor::OlympusDecompressor(const RawImage& img) : mRaw(img) {
const uint32_t w = mRaw->dim.x;
const uint32_t h = mRaw->dim.y;
- if (w == 0 || h == 0 || w % 2 != 0 || w > 10400 || h > 7792)
+ if (w == 0 || h == 0 || w % 2 != 0 /* || w > 10400 || h > 7792 */)
ThrowRDE("Unexpected image dimensions found: (%u; %u)", w, h);
}
diff --git a/src/librawspeed/decompressors/PentaxDecompressor.cpp b/src/librawspeed/decompressors/PentaxDecompressor.cpp
index 11b1d677..c2adc2e6 100644
--- a/src/librawspeed/decompressors/PentaxDecompressor.cpp
+++ b/src/librawspeed/decompressors/PentaxDecompressor.cpp
@@ -49,8 +49,8 @@ PentaxDecompressor::PentaxDecompressor(const RawImage& img,
mRaw->getBpp() != sizeof(uint16_t))
ThrowRDE("Unexpected component count / data type");
- if (!mRaw->dim.x || !mRaw->dim.y || mRaw->dim.x % 2 != 0 ||
- mRaw->dim.x > 8384 || mRaw->dim.y > 6208) {
+ if (!mRaw->dim.x || !mRaw->dim.y || mRaw->dim.x % 2 != 0 /* ||
+ mRaw->dim.x > 8384 || mRaw->dim.y > 6208 */) {
ThrowRDE("Unexpected image dimensions found: (%u; %u)", mRaw->dim.x,
mRaw->dim.y);
}
diff --git a/src/librawspeed/decompressors/SonyArw2Decompressor.cpp b/src/librawspeed/decompressors/SonyArw2Decompressor.cpp
index 8f935d9c..3cbc7e26 100644
--- a/src/librawspeed/decompressors/SonyArw2Decompressor.cpp
+++ b/src/librawspeed/decompressors/SonyArw2Decompressor.cpp
@@ -45,7 +45,7 @@ SonyArw2Decompressor::SonyArw2Decompressor(const RawImage& img,
const uint32_t w = mRaw->dim.x;
const uint32_t h = mRaw->dim.y;
- if (w == 0 || h == 0 || w % 32 != 0 || w > 9600 || h > 6376)
+ if (w == 0 || h == 0 || w % 32 != 0 /* || w > 9600 || h > 6376 */)
ThrowRDE("Unexpected image dimensions found: (%u; %u)", w, h);
// 1 byte per pixel

View File

@@ -0,0 +1,37 @@
diff --git a/src/librawspeed/common/DefaultInitAllocatorAdaptor.h b/src/librawspeed/common/DefaultInitAllocatorAdaptor.h
index 2ff8969e..fa18c312 100644
--- a/src/librawspeed/common/DefaultInitAllocatorAdaptor.h
+++ b/src/librawspeed/common/DefaultInitAllocatorAdaptor.h
@@ -27,8 +27,12 @@
namespace rawspeed {
template <typename T, typename ActualAllocator = std::allocator<T>,
- typename = std::enable_if_t<std::is_pod<T>::value>>
-class DefaultInitAllocatorAdaptor {
+#ifdef _MSC_VER
+ typename = std::enable_if_t<true>>
+#else
+ typename = std::enable_if_t<std::is_pod<T>::value >>
+#endif
+ class DefaultInitAllocatorAdaptor {
public:
using allocator_traits = std::allocator_traits<ActualAllocator>;
diff --git a/src/librawspeed/decompressors/VC5Decompressor.cpp b/src/librawspeed/decompressors/VC5Decompressor.cpp
index c498ac3a..de4ae412 100644
--- a/src/librawspeed/decompressors/VC5Decompressor.cpp
+++ b/src/librawspeed/decompressors/VC5Decompressor.cpp
@@ -398,7 +398,12 @@ VC5Decompressor::VC5Decompressor(ByteStream bs, const RawImage& img)
wavelet.height = waveletHeight;
wavelet.bands.resize(
- &wavelet == channel.wavelets.begin() ? 1 : Wavelet::maxBands);
+#ifdef _MSC_VER
+ Wavelet::maxBands
+#else
+ &wavelet == channel.wavelets.begin() ? 1 : Wavelet::maxBands
+#endif
+ );
}
}

View File

@@ -0,0 +1,251 @@
#include "rawspeed3_capi.h"
#include "RawSpeed-API.h"
#define HAVE_PUGIXML
#include <../pugixml/pugixml.hpp> // for xml_document, xml_pars...
extern const char* _rawspeed3_data_xml;
class rawspeed3_handle_data
{
public:
rawspeed3_handle_data(const char* cameradefs, bool is_file);
void release();
int decodefile(rawspeed3_ret_t* resultp, const void *data, size_t datasize, bool allowunknown);
~rawspeed3_handle_data();
private:
std::unique_ptr <rawspeed::CameraMetaData> cameraMeta;
std::unique_ptr<rawspeed::RawParser> rawParser;
std::unique_ptr<rawspeed::RawDecoder> rawDecoder;
};
/* API calls */
extern "C"
{
/*
void rawspeed3_clearresult(rawspeed3_ret_t* r)
Clears (inits) results structure
*/
DllDef void rawspeed3_clearresult(rawspeed3_ret_t* r)
{
if(!r) return;
r->width = r->height = r->bpp = r->cpp = 0;
r->status = rawspeed_inited;
r->pitch = r->filters = 0;
r->pixeldata = nullptr;
}
/*
rawspeed3_init()
Init rawspeed3 Camera, returns: 0 on failure, pointer to data block on success
Cameradefs: cameras.xml in string (is_file == false) or file (is_file == true)
*/
DllDef rawspeed3_handle_t rawspeed3_init(const char* cameradefs, bool is_file)
{
/* Create rawspeed3_handle_data and return it as void document */
if(!cameradefs) return nullptr;
try
{
/* code */
auto *handle = new rawspeed3_handle_data(cameradefs, is_file);
return (void*)handle;
}
catch(const std::exception& e)
{
return nullptr;
}
}
/*
rawspeed3_initdefault()
Init rawspeed3 Cameradefs with built-in cameras.xml (converted to _rawspeed3_data_xml),
returns: 0 on failure, pointer to data block on success
*/
DllDef rawspeed3_handle_t rawspeed3_initdefault()
{
return rawspeed3_init(_rawspeed3_data_xml,false);
}
/*
rawspeed3_decodefile(..)
parse/decode RAW file passed via memory
Parameters:
handle - rawspeed3_handle_t => handle created by rawspeed3_init()
resultp -> pointer to rawspeed3_ret_t to be filled with
data -> data buffer with raw file
datasize -> size of this buffer
allowunknown -> allow to process unknown cameras (not listed in cameras.xml)
Return values:
0 -> OK
>=1 -> decode error
-1 -> Incorrect parameters passed (handle, or data, or datasize)
*/
DllDef int rawspeed3_decodefile(rawspeed3_handle_t handle, rawspeed3_ret_t* resultp,
const void *data, size_t datasize, bool allowunknown)
{
if(!handle || !resultp || !data || datasize > 2UL * 1024UL * 1024UL * 1024UL)
{
if(resultp)
resultp->status = rawspeed3_param_error;
return -1;
}
rawspeed3_clearresult(resultp);
auto *p = static_cast<rawspeed3_handle_data*>(handle);
return p->decodefile(resultp,data,datasize,allowunknown);
}
/*
void rawspeed3_release(rawspeed3_handle_t handle)
release internal raw data buffer and error code;
*/
/* release internal raw data buffer and errmessage (if any) */
DllDef void rawspeed3_release(rawspeed3_handle_t handle)
{
if(!handle) return;
auto *p = static_cast<rawspeed3_handle_data*>(handle);
p->release();
}
/* close handle: release all internal data */
DllDef void rawspeed3_close(rawspeed3_handle_t handle)
{
if(!handle) return;
auto *p = static_cast<rawspeed3_handle_data*>(handle);
delete p;
}
} /* extern "C" */
// == Implementation
int rawspeed3_handle_data::decodefile(rawspeed3_ret_t* resultp,
const void *data, size_t datasize, bool allowunknown)
{
if(!cameraMeta)
{
resultp->status = rawspeed3_not_inited;
return rawspeed3_not_inited;
}
try
{
rawspeed::Buffer buffer( static_cast<const uint8_t*>(data),datasize);
release();
rawParser = std::make_unique<rawspeed::RawParser>(buffer);
auto d(rawParser->getDecoder(cameraMeta.get()));
if(!d)
{
resultp->status = rawspeed3_no_decoder;
return rawspeed3_no_decoder;
}
d->applyCrop = false;
d->failOnUnknown = !allowunknown;
d->interpolateBadPixels = false;
d->applyStage1DngOpcodes = false;
d->fujiRotate = false;
d->applyCrop = false;
try {
d->checkSupport(cameraMeta.get());
} catch (...) {
release();
resultp->status = rawspeed3_not_supported;
return resultp->status;
}
rawspeed::RawImage r = d->mRaw;
d->decodeMetaData(cameraMeta.get());
d->checkSupport(cameraMeta.get());
d->decodeRaw();
d->decodeMetaData(cameraMeta.get());
r = d->mRaw;
rawDecoder = std::move(d);
// we're here w/o exceptions: success
const rawspeed::iPoint2D dimUncropped = r->getUncroppedDim();
resultp->width = dimUncropped.x;
resultp->height = dimUncropped.y;
resultp->filters = r->cfa.getDcrawFilter();
resultp->cpp = r->getCpp();
resultp->bpp = r->getBpp();
resultp->pitch = r->pitch;
resultp->pixeldata = r->getDataUncropped(0,0);
const auto errors = r->getErrors();
resultp->status = errors.empty()? rawspeed3_ok : rawspeed3_ok_warnings;
return resultp->status;
/* code */
}
catch(...)
{
resultp->status = rawspeed3_processing_error;
return rawspeed3_processing_error;
}
}
namespace rawspeed
{
class CameraMetaDataFromMem : public CameraMetaData
{
public:
explicit CameraMetaDataFromMem(const char* xmlstring);
};
}
rawspeed3_handle_data::rawspeed3_handle_data(const char* cameradefs, bool is_file)
: rawParser(nullptr)
{
cameraMeta = is_file ? std::make_unique<rawspeed::CameraMetaData>(cameradefs)
: std::make_unique <rawspeed::CameraMetaDataFromMem>(cameradefs);
}
rawspeed3_handle_data::~rawspeed3_handle_data()
{
release();
cameraMeta.reset();
}
void rawspeed3_handle_data::release()
{
if(rawDecoder)
rawDecoder.reset();
if (rawParser)
rawParser.reset();
}
// Camera metadata from mem
namespace rawspeed
{
CameraMetaDataFromMem::CameraMetaDataFromMem(const char* document)
{
using pugi::xml_node;
using pugi::xml_document;
using pugi::xml_parse_result;
xml_document doc;
xml_parse_result result = doc.load_string(document);
if (!result)
throw "Camera definitions parse error";
for (xml_node camera : doc.child("Cameras").children("Camera"))
{
const auto* cam = addCamera(std::make_unique<Camera>(camera));
if (cam == nullptr)
continue;
// Create cameras for aliases.
for (auto i = 0UL; i < cam->aliases.size(); i++)
addCamera(std::make_unique<Camera>(cam, i));
}
}
} // namespace rawspeed

View File

@@ -0,0 +1,83 @@
#pragma once
#include <stdint.h>
#include <stdlib.h>
#ifdef _MSC_VER
#ifdef RAWSPEED_BUILDLIB
#define DllDef __declspec(dllexport)
#else
#define DllDef __declspec(dllimport)
#endif
#else
#define DllDef
#endif
#ifdef __cplusplus
extern "C"
{
#endif
enum rawspeed3_error_codes
{
rawspeed_inited = -2,
rawspeed3_param_error = -1,
rawspeed3_ok = 0,
rawspeed3_ok_warnings = 1,
rawspeed3_not_inited = 2,
rawspeed3_processing_error = 3,
rawspeed3_no_decoder = 4,
rawspeed3_not_supported = 5,
};
typedef void *rawspeed3_handle_t;
/* RAW file parsing results */
typedef struct
{
int status; /* -1: param error, 0 => OK, >=1 error code */
uint16_t width, height, bpp, cpp;
unsigned pitch, filters;
const void *pixeldata;
}rawspeed3_ret_t;
/* API calls */
DllDef void rawspeed3_clearresult(rawspeed3_ret_t*);
/*
rawspeed3_init()
Init rawspeed3 Camera, returns: 0 on failure, pointer to data block on success
Cameradefs: cameras.xml in string (is_file == false) or file (is_file == true)
*/
DllDef rawspeed3_handle_t rawspeed3_init(const char* cameradefs, bool is_file);
/* init with built-in cameras.xml */
DllDef rawspeed3_handle_t rawspeed3_initdefault();
/*
rawspeed3_decodefile(..)
parse/decode RAW file passed via memory
Parameters:
handle - rawspeed3_handle_t => handle created by rawspeed3_init()
resultp -> pointer to rawspeed3_ret_t to be filled with
data -> data buffer with raw file
datasize -> size of this buffer
allowunknown -> allow to process unknown cameras (not listed in cameras.xml)
Return values:
0 -> OK
1 -> decode warnings (not fatal)
>1 -> error code
-1 -> Incorrect parameters passed (handle, or data, or datasize)
*/
DllDef int rawspeed3_decodefile(rawspeed3_handle_t handle, rawspeed3_ret_t* resultp,
const void *data, size_t datasize, bool allowunknown);
/* release internal raw data buffer */
DllDef void rawspeed3_release(rawspeed3_handle_t handle);
/* close handle: release all internal data */
DllDef void rawspeed3_close(rawspeed3_handle_t handle);
#ifdef __cplusplus
} /* Extern C */
#endif

View File

@@ -0,0 +1,71 @@
#include "rawspeed3_capi.h"
#include <fstream>
#include <iostream>
#include <vector>
#include <stdint.h>
std::vector<uint8_t> readfile(char *fn)
{
std::ifstream is(fn,std::ifstream::binary);
if(is)
{
is.seekg(0, is.end);
size_t length = is.tellg();
is.seekg(0, is.beg);
std::vector<uint8_t> ret;
ret.resize(length+1);
is.read ((char*)ret.data(),length);
is.close();
ret[length] = 0; // zero terminated
std::cout << "File: " << fn << " size:" << ret.size() << std::endl;
return ret;
}
else
return std::vector<uint8_t>();
}
int main(int ac, char *av[])
{
if(ac < 2)
{
std::cout << "Usage: " << av[0] << " rawfile rawfile2 ...." << std::endl;
return 1;
}
rawspeed3_handle_t handle = rawspeed3_initdefault();
if(!handle)
{
std::cerr << "Unable to init rs3" << std::endl;
return 2;
}
for(int i = 1; i < ac; i++)
{
std::vector<uint8_t> rawdata = readfile(av[i]);
if (rawdata.size() < 100) {
std::cerr << "Input file " << av[i] << " too small or nonexistent" << std::endl;
continue;
}
rawspeed3_ret_t result;
int q = rawspeed3_decodefile(handle, &result, rawdata.data(),
rawdata.size(), true);
if (q >= rawspeed3_ok && q <= rawspeed3_ok_warnings) {
std::cout << "File decoded code=" << result.status <<" width=" << result.width
<< " height=" << result.height
<< " pitch=" << result.pitch
<< " filters=" << std::hex << result.filters << std::dec
<< " channels=" << result.cpp
<< " bpp=" << result.bpp
<< std::endl;
} else
std::cout << "RawSpeed wrapper error code:" << result.status
<< std::endl;
rawspeed3_release(handle);
}
rawspeed3_close(handle);
}

View File

@@ -0,0 +1,5 @@
#!/bin/sh
echo "const char *_rawspeed3_data_xml="
cat $1 | tr -d '\015' | sed -e 's/\\/\\\\/g;s/"/\\"/g;s/ /\\t/g;s/^/"/;s/$/\\n"/'
echo "\"\\0\";"