Merge commit '638ecc4cde79b0296f2e04f683ca4cb881c28f36' as 'rtengine/libraw'
This commit is contained in:
251
rtengine/libraw/RawSpeed3/rawspeed3_c_api/rawspeed3_capi.cpp
Normal file
251
rtengine/libraw/RawSpeed3/rawspeed3_c_api/rawspeed3_capi.cpp
Normal 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
|
Reference in New Issue
Block a user