blob: ce1cdbe8a70dfcb9ac1920682a2728be37982f0c [file]
/* -*- C++ -*-
* Copyright 2019-2025 LibRaw LLC (info@libraw.org)
*
LibRaw is free software; you can redistribute it and/or modify
it under the terms of the one of two licenses as you choose:
1. GNU LESSER GENERAL PUBLIC LICENSE version 2.1
(See file LICENSE.LGPL provided in LibRaw distribution archive for details).
2. COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
(See file LICENSE.CDDL provided in LibRaw distribution archive for details).
*/
#define LIBRAW_EXPAT_CONFLICT
#include "third_party/libraw/internal/libraw_cxx_defs.h"
#ifdef USE_RAWSPEED
#include <RawSpeed/StdAfx.h>
#include <RawSpeed/FileMap.h>
#include <RawSpeed/RawParser.h>
#include <RawSpeed/RawDecoder.h>
#include <RawSpeed/CameraMetaData.h>
#include <RawSpeed/ColorFilterArray.h>
#include "../../RawSpeed/rawspeed_xmldata.cpp"
const int RAWSPEED_DATA_COUNT = (sizeof(_rawspeed_data_xml) / sizeof(_rawspeed_data_xml[0]));
class CameraMetaDataLR : public RawSpeed::CameraMetaData
{
public:
CameraMetaDataLR() : CameraMetaData() {}
CameraMetaDataLR(char *filename) : RawSpeed::CameraMetaData(filename) {}
CameraMetaDataLR(char *data, int sz);
};
#define P1 imgdata.idata
#define S imgdata.sizes
#define O imgdata.params
#define C imgdata.color
#define T imgdata.thumbnail
#define MN imgdata.makernotes
#define IO libraw_internal_data.internal_output_params
#define ID libraw_internal_data.internal_data
CameraMetaDataLR::CameraMetaDataLR(char *data, int sz) : RawSpeed::CameraMetaData()
{
ctxt = xmlNewParserCtxt();
if (ctxt == NULL)
{
RawSpeed::ThrowCME("CameraMetaData:Could not initialize context.");
}
xmlResetLastError();
doc = xmlCtxtReadMemory(ctxt, data, sz, "", NULL, XML_PARSE_DTDVALID);
if (doc == NULL)
{
RawSpeed::ThrowCME("CameraMetaData: XML Document could not be parsed successfully. "
"Error was: %s",
ctxt->lastError.message);
}
if (ctxt->valid == 0)
{
if (ctxt->lastError.code == 0x5e)
{
// ignore this error code
}
else
{
RawSpeed::ThrowCME("CameraMetaData: XML file does not validate. DTD Error was: %s",
ctxt->lastError.message);
}
}
xmlNodePtr cur;
cur = xmlDocGetRootElement(doc);
if (xmlStrcmp(cur->name, (const xmlChar *)"Cameras"))
{
RawSpeed::ThrowCME("CameraMetaData: XML document of the wrong type, root node is not "
"cameras.");
return;
}
cur = cur->xmlChildrenNode;
while (cur != NULL)
{
if ((!xmlStrcmp(cur->name, (const xmlChar *)"Camera")))
{
RawSpeed::Camera *camera = new RawSpeed::Camera(doc, cur);
addCamera(camera);
// Create cameras for aliases.
for (unsigned int i = 0; i < camera->aliases.size(); i++)
{
addCamera(new RawSpeed::Camera(camera, i));
}
}
cur = cur->next;
}
if (doc)
xmlFreeDoc(doc);
doc = 0;
if (ctxt)
xmlFreeParserCtxt(ctxt);
ctxt = 0;
}
void *make_camera_metadata()
{
int len = 0, i;
for (i = 0; i < RAWSPEED_DATA_COUNT; i++)
if (_rawspeed_data_xml[i])
{
len += int(strlen(_rawspeed_data_xml[i]));
}
char *rawspeed_xml =
(char *)calloc(len + 1, sizeof(_rawspeed_data_xml[0][0]));
if (!rawspeed_xml)
return NULL;
int offt = 0;
for (i = 0; i < RAWSPEED_DATA_COUNT; i++)
if (_rawspeed_data_xml[i])
{
int ll = int(strlen(_rawspeed_data_xml[i]));
if (offt + ll > len)
break;
memmove(rawspeed_xml + offt, _rawspeed_data_xml[i], ll);
offt += ll;
}
rawspeed_xml[offt] = 0;
CameraMetaDataLR *ret = NULL;
try
{
ret = new CameraMetaDataLR(rawspeed_xml, offt);
}
catch (...)
{
// Mask all exceptions
}
free(rawspeed_xml);
return ret;
}
void clear_rawspeed_decoder(void* _rawspeed_decoder)
{
RawSpeed::RawDecoder *d =
static_cast<RawSpeed::RawDecoder *>(_rawspeed_decoder);
if(d)
delete d;
}
void clear_camera_metadata(void* _rawspeed_camerameta)
{
CameraMetaDataLR *cmeta =
static_cast<CameraMetaDataLR *>(_rawspeed_camerameta);
if(cmeta)
delete cmeta;
}
int LibRaw::set_rawspeed_camerafile(char * filename)
{
#ifdef USE_RAWSPEED
try
{
CameraMetaDataLR *camerameta = new CameraMetaDataLR(filename);
if (_rawspeed_camerameta)
{
CameraMetaDataLR *d =
static_cast<CameraMetaDataLR *>(_rawspeed_camerameta);
delete d;
}
_rawspeed_camerameta = static_cast<void *>(camerameta);
}
catch (...)
{
// just return error code
return -1;
}
#else
(void)filename;
#endif
return 0;
}
#ifdef USE_RAWSPEED
void LibRaw::fix_after_rawspeed(int /*bl*/)
{
if (load_raw == &LibRaw::lossy_dng_load_raw)
C.maximum = 0xffff;
else if (load_raw == &LibRaw::sony_load_raw)
C.maximum = 0x3ff0;
}
#else
void LibRaw::fix_after_rawspeed(int) {}
#endif
int LibRaw::try_rawspeed()
{
#ifdef USE_RAWSPEED
int ret = LIBRAW_SUCCESS;
#ifdef USE_RAWSPEED_BITS
int rawspeed_ignore_errors = (imgdata.rawparams.use_rawspeed & LIBRAW_RAWSPEEDV1_IGNOREERRORS);
#else
int rawspeed_ignore_errors = 0;
#endif
if (imgdata.idata.dng_version && imgdata.idata.colors == 3 &&
!strcasecmp(imgdata.idata.software,
"Adobe Photoshop Lightroom 6.1.1 (Windows)"))
rawspeed_ignore_errors = 1;
// RawSpeed Supported,
INT64 spos = ID.input->tell();
void *_rawspeed_buffer = 0;
try
{
ID.input->seek(0, SEEK_SET);
INT64 _rawspeed_buffer_sz = ID.input->size() + 32LL;
if(_rawspeed_buffer_sz > 2147483647LL)
throw LIBRAW_EXCEPTION_ALLOC;
_rawspeed_buffer = malloc(_rawspeed_buffer_sz);
if (!_rawspeed_buffer)
throw LIBRAW_EXCEPTION_ALLOC;
ID.input->read(_rawspeed_buffer, _rawspeed_buffer_sz, 1);
RawSpeed::FileMap map((RawSpeed::uchar8 *)_rawspeed_buffer, uint32_t(_rawspeed_buffer_sz));
RawSpeed::RawParser t(&map);
RawSpeed::RawDecoder *d = 0;
CameraMetaDataLR *meta =
static_cast<CameraMetaDataLR *>(_rawspeed_camerameta);
d = t.getDecoder();
if (!d)
throw "Unable to find decoder";
#ifdef USE_RAWSPEED_BITS
if (imgdata.rawparams.use_rawspeed & LIBRAW_RAWSPEEDV1_FAILONUNKNOWN)
d->failOnUnknown = TRUE;
else
d->failOnUnknown = FALSE;
#endif
d->interpolateBadPixels = FALSE;
d->applyStage1DngOpcodes = FALSE;
try
{
d->checkSupport(meta);
}
catch (const RawSpeed::RawDecoderException &e)
{
imgdata.process_warnings |= LIBRAW_WARN_RAWSPEED_UNSUPPORTED;
throw e;
}
_rawspeed_decoder = static_cast<void *>(d);
d->decodeRaw();
d->decodeMetaData(meta);
RawSpeed::RawImage r = d->mRaw;
if (r->errors.size() > 0 && !rawspeed_ignore_errors)
{
delete d;
_rawspeed_decoder = 0;
throw 1;
}
if (r->isCFA)
{
imgdata.rawdata.raw_image = (ushort *)r->getDataUncropped(0, 0);
}
else if (r->getCpp() == 4)
{
imgdata.rawdata.color4_image = (ushort(*)[4])r->getDataUncropped(0, 0);
if (r->whitePoint > 0 && r->whitePoint < 65536)
C.maximum = r->whitePoint;
}
else if (r->getCpp() == 3)
{
imgdata.rawdata.color3_image = (ushort(*)[3])r->getDataUncropped(0, 0);
if (r->whitePoint > 0 && r->whitePoint < 65536)
C.maximum = r->whitePoint;
}
else
{
delete d;
_rawspeed_decoder = 0;
ret = LIBRAW_UNSPECIFIED_ERROR;
}
if (_rawspeed_decoder)
{
// set sizes
RawSpeed::iPoint2D rsdim = r->getUncroppedDim();
S.raw_pitch = r->pitch;
S.raw_width = rsdim.x;
S.raw_height = rsdim.y;
// C.maximum = r->whitePoint;
fix_after_rawspeed(r->blackLevel);
}
free(_rawspeed_buffer);
_rawspeed_buffer = 0;
imgdata.process_warnings |= LIBRAW_WARN_RAWSPEED_PROCESSED;
}
catch (const RawSpeed::RawDecoderException &RDE)
{
imgdata.process_warnings |= LIBRAW_WARN_RAWSPEED_PROBLEM;
if (_rawspeed_buffer)
{
free(_rawspeed_buffer);
_rawspeed_buffer = 0;
}
if (!strncmp(RDE.what(), "Decoder canceled", strlen("Decoder canceled")))
throw LIBRAW_EXCEPTION_CANCELLED_BY_CALLBACK;
ret = LIBRAW_UNSPECIFIED_ERROR;
}
catch (...)
{
// We may get here due to cancellation flag
imgdata.process_warnings |= LIBRAW_WARN_RAWSPEED_PROBLEM;
if (_rawspeed_buffer)
{
free(_rawspeed_buffer);
_rawspeed_buffer = 0;
}
ret = LIBRAW_UNSPECIFIED_ERROR;
}
ID.input->seek(spos, SEEK_SET);
return ret;
#else
return LIBRAW_NOT_IMPLEMENTED;
#endif
}
#endif