252 lines
6.6 KiB
C++
252 lines
6.6 KiB
C++
#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
|