added basic integration of lensfun

so far only distortion correction, and no GUI yet
This commit is contained in:
Alberto Griggio 2017-09-07 00:53:03 +02:00
parent b4d3caf9c6
commit dde94bc6d3
18 changed files with 320 additions and 113 deletions

View File

@ -272,6 +272,7 @@ pkg_check_modules (GIOMM REQUIRED giomm-2.4>=2.44)
pkg_check_modules (GTHREAD REQUIRED gthread-2.0>=2.44)
pkg_check_modules (GOBJECT REQUIRED gobject-2.0>=2.44)
pkg_check_modules (SIGC REQUIRED sigc++-2.0>=2.3.1)
pkg_check_modules (LENSFUN REQUIRED lensfun>=0.2)
if(WIN32)
add_definitions(-DWIN32)

View File

@ -9,6 +9,7 @@ include_directories(${EXTRA_INCDIR}
${GTK_INCLUDE_DIRS}
${IPTCDATA_INCLUDE_DIRS}
${LCMS_INCLUDE_DIRS}
${LENSFUN_INCLUDE_DIRS}
)
link_directories("${PROJECT_SOURCE_DIR}/rtexif"
@ -109,6 +110,7 @@ set(RTENGINESOURCEFILES
slicer.cc
stdimagesource.cc
utils.cc
rtlensfun.cc
)
if(NOT WITH_SYSTEM_KLT)
@ -153,6 +155,7 @@ target_link_libraries(rtengine rtexif
${PNG_LIBRARIES}
${TIFF_LIBRARIES}
${ZLIB_LIBRARIES}
${LENSFUN_LIBRARIES}
)
install(FILES ${CAMCONSTSFILE} DESTINATION "${DATADIR}" PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ)

View File

@ -1086,8 +1086,9 @@ bool check_need_larger_crop_for_lcp_distortion (int fw, int fh, int x, int y, in
return false;
}
return (params.lensProf.lcpFile.length() > 0 &&
params.lensProf.useDist);
return (params.lensProf.useDist &&
(params.lensProf.useLensfun ||
params.lensProf.lcpFile.length() > 0));
}
} // namespace

View File

@ -400,8 +400,9 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall)
}
if (needstransform)
ipf.transform (orig_prev, oprevi, 0, 0, 0, 0, pW, pH, fw, fh, imgsrc->getMetaData()->getFocalLen(),
ipf.transform (orig_prev, oprevi, 0, 0, 0, 0, pW, pH, fw, fh,
imgsrc->getMetaData(),
// imgsrc->getMetaData()->getFocalLen(),
// imgsrc->getMetaData()->getFocalLen35mm(), imgsrc->getMetaData()->getFocusDist(), imgsrc->getMetaData()->getFNumber(),
imgsrc->getRotateDegree(), false);
else {
@ -1120,7 +1121,7 @@ void ImProcCoordinator::getAutoCrop (double ratio, int &x, int &y, int &w, int &
MyMutex::MyLock lock (mProcessing);
LCPMapper *pLCPMap = nullptr;
LensCorrection *pLCPMap = nullptr;
if (params.lensProf.lcpFile.length() && imgsrc->getMetaData()->getFocalLen() > 0) {
LCPProfile *pLCPProf = lcpStore->getProfile (params.lensProf.lcpFile);

View File

@ -60,7 +60,7 @@ class ImProcFunctions
TRANSFORM_HIGH_QUALITY_FULLIMAGE
};
void transformLuminanceOnly (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int oW, int oH, int fW, int fH);
void transformGeneral(TransformMode mode, Imagefloat *original, Imagefloat *transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const LCPMapper *pLCPMap);
void transformGeneral(TransformMode mode, Imagefloat *original, Imagefloat *transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const LensCorrection *pLCPMap);
void sharpenHaloCtrl (float** luminance, float** blurmap, float** base, int W, int H, const SharpeningParams &sharpenParam);
void sharpenHaloCtrl (LabImage* lab, float** blurmap, float** base, int W, int H, SharpeningParams &sharpenParam);
@ -74,6 +74,7 @@ class ImProcFunctions
bool needsGradient ();
bool needsVignetting ();
bool needsLCP ();
bool needsLensfun();
// static cmsUInt8Number* Mempro = NULL;
inline void interpolateTransformCubic (Imagefloat* src, int xs, int ys, double Dx, double Dy, float *r, float *g, float *b, double mul)
@ -352,11 +353,11 @@ public:
Image16* lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm, bool bw, GammaValues *ga = nullptr);
// CieImage *ciec;
bool transCoord (int W, int H, int x, int y, int w, int h, int& xv, int& yv, int& wv, int& hv, double ascaleDef = -1, const LCPMapper *pLCPMap = nullptr);
bool transCoord (int W, int H, const std::vector<Coord2D> &src, std::vector<Coord2D> &red, std::vector<Coord2D> &green, std::vector<Coord2D> &blue, double ascaleDef = -1, const LCPMapper *pLCPMap = nullptr);
bool transCoord (int W, int H, int x, int y, int w, int h, int& xv, int& yv, int& wv, int& hv, double ascaleDef = -1, const LensCorrection *pLCPMap = nullptr);
bool transCoord (int W, int H, const std::vector<Coord2D> &src, std::vector<Coord2D> &red, std::vector<Coord2D> &green, std::vector<Coord2D> &blue, double ascaleDef = -1, const LensCorrection *pLCPMap = nullptr);
static void getAutoExp (const LUTu & histogram, int histcompr, double defgain, double clip, double& expcomp, int& bright, int& contr, int& black, int& hlcompr, int& hlcomprthresh);
static double getAutoDistor (const Glib::ustring& fname, int thumb_size);
double getTransformAutoFill (int oW, int oH, const LCPMapper *pLCPMap = nullptr);
double getTransformAutoFill (int oW, int oH, const LensCorrection *pLCPMap = nullptr);
void rgb2lab (const Imagefloat &src, LabImage &dst, const Glib::ustring &workingSpace);
void lab2rgb (const LabImage &src, Imagefloat &dst, const Glib::ustring &workingSpace);
};

View File

@ -30,6 +30,7 @@
#include "rtthumbnail.h"
#include "profilestore.h"
#include "../rtgui/threadutils.h"
#include "rtlensfun.h"
namespace rtengine
{
@ -50,6 +51,7 @@ int init (const Settings* s, Glib::ustring baseDir, Glib::ustring userSettingsDi
Color::init ();
PerceptualToneCurve::init ();
RawImageSource::init ();
LFDatabase::init();
delete lcmsMutex;
lcmsMutex = new MyMutex;
dfm.init( s->darkFramesPath );

View File

@ -24,6 +24,7 @@
#include "mytime.h"
#include "rt_math.h"
#include "sleef.c"
#include "rtlensfun.h"
using namespace std;
@ -86,16 +87,18 @@ float normn (float a, float b, int n)
}
void correct_distortion(const rtengine::LCPMapper *lcp, double &x, double &y,
inline void correct_distortion(const rtengine::LensCorrection *lcp, double &x, double &y,
int cx, int cy, double scale)
{
assert (lcp);
x += cx;
y += cy;
lcp->correctDistortion(x, y, scale);
x -= (cx * scale);
y -= (cy * scale);
// x += cx;
// y += cy;
// std::cout << "DIST: x=" << x << ", y=" << y;
lcp->correctDistortion(x, y, cx, cy, scale);
// std::cout << " --> pos[0]=" << x << ", pos[1]=" << y << std::endl;
// x -= (cx * scale);
// y -= (cy * scale);
}
}
@ -107,7 +110,7 @@ namespace rtengine
#define CLIPTOC(a,b,c,d) ((a)>=(b)?((a)<=(c)?(a):(d=true,(c))):(d=true,(b)))
bool ImProcFunctions::transCoord (int W, int H, const std::vector<Coord2D> &src, std::vector<Coord2D> &red, std::vector<Coord2D> &green, std::vector<Coord2D> &blue, double ascaleDef,
const LCPMapper *pLCPMap)
const LensCorrection *pLCPMap)
{
bool clipped = false;
@ -209,7 +212,7 @@ bool ImProcFunctions::transCoord (int W, int H, const std::vector<Coord2D> &src,
}
// Transform all corners and critical sidelines of an image
bool ImProcFunctions::transCoord (int W, int H, int x, int y, int w, int h, int& xv, int& yv, int& wv, int& hv, double ascaleDef, const LCPMapper *pLCPMap)
bool ImProcFunctions::transCoord (int W, int H, int x, int y, int w, int h, int& xv, int& yv, int& wv, int& hv, double ascaleDef, const LensCorrection *pLCPMap)
{
const int DivisionsPerBorder = 32;
@ -316,9 +319,30 @@ void ImProcFunctions::transform (Imagefloat* original, Imagefloat* transformed,
float focusDist = metadata->getFocusDist();
double fNumber = metadata->getFNumber();
LCPMapper *pLCPMap = nullptr;
LensCorrection *pLCPMap = nullptr;
if (needsLCP()) { // don't check focal length to allow distortion correction for lenses without chip
if (needsLensfun()) {
const LFDatabase *db = LFDatabase::getInstance();
Glib::ustring make, model, lens;
if (params->lensProf.lfAutoMatch) {
make = metadata->getMake();
model = metadata->getModel();
lens = metadata->getLens();
} else {
make = params->lensProf.lfCameraMake;
model = params->lensProf.lfCameraModel;
lens = params->lensProf.lfLens;
}
LFCamera c = db->findCamera(make, model);
LFLens l = db->findLens(c, lens);
pLCPMap = db->getModifier(c, l, fW, fH, focalLen, fNumber, focusDist);
std::cout << "LENSFUN:\n"
<< " camera: " << c.getDisplayString() << "\n"
<< " lens: " << l.getDisplayString() << "\n"
<< " correction? " << (pLCPMap ? "yes" : "no") << std::endl;
} else if (needsLCP()) { // don't check focal length to allow distortion correction for lenses without chip
LCPProfile *pLCPProf = lcpStore->getProfile (params->lensProf.lcpFile);
if (pLCPProf) {
@ -329,7 +353,7 @@ void ImProcFunctions::transform (Imagefloat* original, Imagefloat* transformed,
}
}
if (! (needsCA() || needsDistortion() || needsRotation() || needsPerspective() || needsLCP()) && (needsVignetting() || needsPCVignetting() || needsGradient())) {
if (! (needsCA() || needsDistortion() || needsRotation() || needsPerspective() || needsLCP() || needsLensfun()) && (needsVignetting() || needsPCVignetting() || needsGradient())) {
transformLuminanceOnly (original, transformed, cx, cy, oW, oH, fW, fH);
} else {
TransformMode mode;
@ -734,7 +758,7 @@ void ImProcFunctions::transformLuminanceOnly (Imagefloat* original, Imagefloat*
}
void ImProcFunctions::transformGeneral(ImProcFunctions::TransformMode mode, Imagefloat *original, Imagefloat *transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const LCPMapper *pLCPMap)
void ImProcFunctions::transformGeneral(ImProcFunctions::TransformMode mode, Imagefloat *original, Imagefloat *transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const LensCorrection *pLCPMap)
{
double w2 = (double) oW / 2.0 - 0.5;
double h2 = (double) oH / 2.0 - 0.5;
@ -801,7 +825,7 @@ void ImProcFunctions::transformGeneral(ImProcFunctions::TransformMode mode, Imag
switch (mode) {
case ImProcFunctions::TRANSFORM_HIGH_QUALITY_FULLIMAGE:
enableLCPCA = pLCPMap && params->lensProf.useCA && pLCPMap->enableCA;
enableLCPCA = pLCPMap && params->lensProf.useCA && pLCPMap->supportsCA();
// no break on purpose
case ImProcFunctions::TRANSFORM_HIGH_QUALITY:
enableLCPDist = pLCPMap && params->lensProf.useDist;
@ -958,12 +982,16 @@ void ImProcFunctions::transformGeneral(ImProcFunctions::TransformMode mode, Imag
}
double ImProcFunctions::getTransformAutoFill (int oW, int oH, const LCPMapper *pLCPMap)
double ImProcFunctions::getTransformAutoFill (int oW, int oH, const LensCorrection *pLCPMap)
{
if (!needsCA() && !needsDistortion() && !needsRotation() && !needsPerspective() && (!params->lensProf.useDist || pLCPMap == nullptr)) {
return 1;
}
if (pLCPMap && !pLCPMap->supportsAutoFill()) {
return 1;
}
double scaleU = 2, scaleL = 0.001; // upper and lower border, iterate inbetween
do {
@ -1019,12 +1047,17 @@ bool ImProcFunctions::needsVignetting ()
bool ImProcFunctions::needsLCP ()
{
return params->lensProf.lcpFile.length() > 0;
return params->lensProf.lcpFile.length() > 0 && !needsLensfun();
}
bool ImProcFunctions::needsLensfun()
{
return params->lensProf.useLensfun;
}
bool ImProcFunctions::needsTransform ()
{
return needsCA () || needsDistortion () || needsRotation () || needsPerspective () || needsGradient () || needsPCVignetting () || needsVignetting () || needsLCP();
return needsCA () || needsDistortion () || needsRotation () || needsPerspective () || needsGradient () || needsPCVignetting () || needsVignetting () || needsLCP() || needsLensfun();
}

View File

@ -210,8 +210,11 @@ LCPMapper::LCPMapper(LCPProfile* pProf, float focalLength, float focalLength35mm
isFisheye = pProf->isFisheye;
}
void LCPMapper::correctDistortion(double& x, double& y, double scale) const
void LCPMapper::correctDistortion(double &x, double &y, int cx, int cy, double scale) const
{
x += cx;
y += cy;
if (isFisheye) {
double u = x * scale;
double v = y * scale;
@ -253,6 +256,9 @@ void LCPMapper::correctDistortion(double& x, double& y, double scale) const
x = xnew * mc.fx + x0;
y = ynew * mc.fy + y0;
}
x -= cx * scale;
y -= cy * scale;
}
void LCPMapper::correctCA(double& x, double& y, int channel) const

View File

@ -136,8 +136,20 @@ public:
#define lcpStore LCPStore::getInstance()
class LensCorrection {
public:
virtual ~LensCorrection() {}
virtual void correctDistortion(double &x, double &y, int cx, int cy, double scale) const = 0;
virtual bool supportsAutoFill() const = 0;
virtual bool supportsCA() const = 0;
virtual void correctCA(double &x, double &y, int channel) const = 0;
virtual void processVignetteLine(int width, int y, float *line) const = 0;
virtual void processVignetteLine3Channels(int width, int y, float *line) const = 0;
};
// Once precalculated class to correct a point
class LCPMapper
class LCPMapper: public LensCorrection
{
bool useCADist; // should the distortion in the CA info be used?
@ -153,7 +165,9 @@ public:
LCPMapper(LCPProfile* pProf, float focalLength, float focalLength35mm, float focusDist, float aperture, bool vignette, bool useCADistP, int fullWidth, int fullHeight,
const CoarseTransformParams& coarse, int rawRotationDeg);
void correctDistortion(double& x, double& y, double scale) const; // MUST be the first stage
void correctDistortion(double &x, double &y, int cx, int cy, double scale) const; // MUST be the first stage
bool supportsCA() const { return enableCA; }
bool supportsAutoFill() const { return true; }
void correctCA(double& x, double& y, int channel) const;
void processVignetteLine(int width, int y, float *line) const;
void processVignetteLine3Channels(int width, int y, float *line) const;

View File

@ -922,6 +922,11 @@ void LensProfParams::setDefaults()
lcpFile = "";
useDist = useVign = true;
useCA = false;
useLensfun = false;
lfAutoMatch = true;
lfCameraMake = "";
lfCameraModel = "";
lfLens = "";
}
void CoarseTransformParams::setDefaults()
@ -2565,6 +2570,22 @@ int ProcParams::save (const Glib::ustring &fname, const Glib::ustring &fname2, b
keyFile.set_boolean ("LensProfile", "UseCA", lensProf.useCA);
}
if (!pedited || pedited->lensProf.useLensfun) {
keyFile.set_boolean("LensProfile", "UseLensfun", lensProf.useLensfun);
}
if (!pedited || pedited->lensProf.lfAutoMatch) {
keyFile.set_boolean("LensProfile", "LFAutoMatch", lensProf.lfAutoMatch);
}
if (!pedited || pedited->lensProf.lfCameraMake) {
keyFile.set_string("LensProfile", "LFCameraMake", lensProf.lfCameraMake);
}
if (!pedited || pedited->lensProf.lfCameraModel) {
keyFile.set_string("LensProfile", "LFCameraModel", lensProf.lfCameraModel);
}
if (!pedited || pedited->lensProf.lfLens) {
keyFile.set_string("LensProfile", "LFLens", lensProf.lfLens);
}
// save perspective correction
if (!pedited || pedited->perspective.horizontal) {
keyFile.set_double ("Perspective", "Horizontal", perspective.horizontal);
@ -5832,6 +5853,41 @@ int ProcParams::load (const Glib::ustring &fname, ParamsEdited* pedited)
pedited->lensProf.useCA = true;
}
}
if (keyFile.has_key("LensProfile", "UseLensfun")) {
lensProf.useLensfun = keyFile.get_boolean("LensProfile", "UseLensfun");
if (pedited) {
pedited->lensProf.useLensfun = true;
}
}
if (keyFile.has_key("LensProfile", "LFAutoMatch")) {
lensProf.lfAutoMatch = keyFile.get_boolean("LensProfile", "LFAutoMatch");
if (pedited) {
pedited->lensProf.lfAutoMatch = true;
}
}
if (keyFile.has_key("LensProfile", "LFCameraMake")) {
lensProf.lfCameraMake = keyFile.get_string("LensProfile", "LFCameraMake");
if (pedited) {
pedited->lensProf.lfCameraMake = true;
}
}
if (keyFile.has_key("LensProfile", "LFCameraModel")) {
lensProf.lfCameraModel = keyFile.get_string("LensProfile", "LFCameraModel");
if (pedited) {
pedited->lensProf.lfCameraModel = true;
}
}
if (keyFile.has_key("LensProfile", "LFLens")) {
lensProf.lfLens = keyFile.get_string("LensProfile", "LFLens");
if (pedited) {
pedited->lensProf.lfLens = true;
}
}
}
// load perspective correction
@ -8432,6 +8488,11 @@ bool ProcParams::operator== (const ProcParams& other)
&& lensProf.useDist == other.lensProf.useDist
&& lensProf.useVign == other.lensProf.useVign
&& lensProf.useCA == other.lensProf.useCA
&& lensProf.useLensfun == other.lensProf.useLensfun
&& lensProf.lfAutoMatch == other.lensProf.lfAutoMatch
&& lensProf.lfCameraMake == other.lensProf.lfCameraMake
&& lensProf.lfCameraModel == other.lensProf.lfCameraModel
&& lensProf.lfLens == other.lensProf.lfLens
&& perspective.horizontal == other.perspective.horizontal
&& perspective.vertical == other.perspective.vertical
&& gradient.enabled == other.gradient.enabled

View File

@ -831,6 +831,11 @@ class LensProfParams
public:
Glib::ustring lcpFile;
bool useDist, useVign, useCA;
bool useLensfun;
bool lfAutoMatch;
Glib::ustring lfCameraMake;
Glib::ustring lfCameraModel;
Glib::ustring lfLens;
LensProfParams()
{
@ -839,6 +844,7 @@ public:
void setDefaults();
};
/**
* Parameters of the perspective correction
*/

View File

@ -26,32 +26,46 @@ namespace rtengine {
// LFModifier
//-----------------------------------------------------------------------------
bool LFModifier::ok() const
LFModifier::LFModifier(lfModifier *m):
data_(m)
{
return data_.get();
}
void LFModifier::correctDistortion(double &x, double &y)
LFModifier::~LFModifier()
{
if (data_) {
data_->Destroy();
}
}
bool LFModifier::ok() const
{
return data_;
}
void LFModifier::correctDistortion(double &x, double &y, int cx, int cy, double scale) const
{
if (!ok()) {
return;
}
float pos[2];
data_->ApplyGeometryDistortion(x, y, 1, 1, pos);
x = pos[0];
y = pos[1];
if (data_->ApplyGeometryDistortion(x+cx, y+cy, 1, 1, pos)) {
x = pos[0] - cx;
y = pos[1] - cy;
}
}
void LFModifier::processVignetteLine(int width, int y, float *line)
void LFModifier::processVignetteLine(int width, int y, float *line) const
{
// TODO
}
void LFModifier::processVignetteLine3Channels(int width, int y, float *line)
void LFModifier::processVignetteLine3Channels(int width, int y, float *line) const
{
// TODO
}
@ -61,15 +75,21 @@ void LFModifier::processVignetteLine3Channels(int width, int y, float *line)
// LFCamera
//-----------------------------------------------------------------------------
LFCamera::LFCamera():
data_(nullptr)
{
}
bool LFCamera::ok() const
{
return data_.get();
return data_;
}
Glib::ustring LFCamera::getMake() const
{
if (ok()) {
if (data_) {
return data_->Maker;
} else {
return "";
@ -79,7 +99,7 @@ Glib::ustring LFCamera::getMake() const
Glib::ustring LFCamera::getModel() const
{
if (ok()) {
if (data_) {
return data_->Model;
} else {
return "";
@ -89,7 +109,7 @@ Glib::ustring LFCamera::getModel() const
float LFCamera::getCropFactor() const
{
if (ok()) {
if (data_) {
return data_->CropFactor;
} else {
return 0;
@ -99,7 +119,7 @@ float LFCamera::getCropFactor() const
Glib::ustring LFCamera::getDisplayString() const
{
if (ok()) {
if (data_) {
return Glib::ustring::compose("%1 %2", getMake(), getModel());
} else {
return "---";
@ -111,15 +131,21 @@ Glib::ustring LFCamera::getDisplayString() const
// LFLens
//-----------------------------------------------------------------------------
LFLens::LFLens():
data_(nullptr)
{
}
bool LFLens::ok() const
{
return data_->get();
return data_;
}
Glib::ustring LFLens::getDisplayString() const
{
if (ok()) {
if (data_) {
return Glib::ustring::compose("%1 %2", data_->Maker, data_->Model);
} else {
return "---";
@ -136,87 +162,111 @@ LFDatabase LFDatabase::instance_;
bool LFDatabase::init()
{
instance_.data_.reset(new lfDatabase());
instance_.data_ = lfDatabase::Create();
return instance_.data_->Load() != LF_NO_ERROR;
}
LFDatabase *LFDatabase::getInstance()
LFDatabase::LFDatabase():
data_(nullptr)
{
}
LFDatabase::~LFDatabase()
{
if (data_) {
data_->Destroy();
}
}
const LFDatabase *LFDatabase::getInstance()
{
return &instance_;
}
std::vector<LFCamera> LFDatabase::getCameras()
std::vector<LFCamera> LFDatabase::getCameras() const
{
auto cams = data_->GetCameras();
std::vector<LFCamera> ret;
while (*cams) {
ret.emplace_back(LFCamera());
ret.back().data_.reset(new lfCamera(**cams));
++cams;
}
if (data_) {
auto cams = data_->GetCameras();
while (*cams) {
ret.emplace_back(LFCamera());
ret.back().data_ = *cams;
++cams;
}
}
return ret;
}
std::vector<LFLens> getLenses(const LFCamera &camera)
std::vector<LFLens> LFDatabase::getLenses(const LFCamera &camera) const
{
auto lenses = data_->FindLenses(*camera.data_->get(), NULL, "", LF_SEARCH_LOOSE | LF_SEARCH_SORT_AND_UNIQUIFY);
std::vector<LFLens> ret;
while (*lenses) {
ret.emplace_back(LFLens());
ret.back().data_.reset(new lfLens(**lenses));
++lenses;
if (data_) {
auto lenses = data_->FindLenses(camera.data_, NULL, "", LF_SEARCH_LOOSE /*| LF_SEARCH_SORT_AND_UNIQUIFY*/);
while (*lenses) {
ret.emplace_back(LFLens());
ret.back().data_ = *lenses;
++lenses;
}
lf_free(lenses);
}
lf_free(lenses);
return ret;
}
LFCamera LFDatabase::findCamera(const Glib::ustring &make, const Glib::ustring &model)
LFCamera LFDatabase::findCamera(const Glib::ustring &make, const Glib::ustring &model) const
{
LFCamera ret;
auto found = data_->FindCamerasExt(make.c_str(), model.c_str(), LF_SEARCH_LOOSE);
if (found) {
ret.data_.reset(new lfCamera(*found[0]));
lf_free(found);
}
return ret;
}
LFLens LFDatabase::findLens(const LFCamera &camera, const Glib::ustring &name)
{
LFLens ret;
auto found = data_->FindLenses(camera.data_.get(), NULL, name.c_str(), LF_SEARCH_LOOSE);
if (!found) {
// try to split the maker from the model of the lens
Glib::ustring make, model;
auto i = name.find_first_of(' ');
if (i != Glib::ustring::npos) {
make = name.substr(0, i);
model = name.substr(i+1);
found = data_->FindLenses(camera.data_.get(), make.c_str(), model.c_str(), LF_SEARCH_LOOSE);
if (data_) {
auto found = data_->FindCamerasExt(make.c_str(), model.c_str(), LF_SEARCH_LOOSE);
if (found) {
ret.data_ = found[0];
lf_free(found);
}
}
if (found) {
ret.data_.reset(new lfLens(*found[0]));
lf_free(found);
return ret;
}
LFLens LFDatabase::findLens(const LFCamera &camera, const Glib::ustring &name) const
{
LFLens ret;
if (data_) {
auto found = data_->FindLenses(camera.data_, NULL, name.c_str(), LF_SEARCH_LOOSE);
if (!found) {
// try to split the maker from the model of the lens
Glib::ustring make, model;
auto i = name.find_first_of(' ');
if (i != Glib::ustring::npos) {
make = name.substr(0, i);
model = name.substr(i+1);
found = data_->FindLenses(camera.data_, make.c_str(), model.c_str(), LF_SEARCH_LOOSE);
}
}
if (found) {
ret.data_ = found[0];
lf_free(found);
}
}
return ret;
}
LFModifier LFDatabase::getModifier(const LFCamera &camera, const LFLens &lens,
int width, int height, float focalLen,
float aperture)
LFModifier *LFDatabase::getModifier(const LFCamera &camera, const LFLens &lens,
int width, int height, float focalLen,
float aperture, float focusDist) const
{
LFModifier ret;
if (camera.ok() && lens.ok()) {
lfModifier *mod = lfModifier::Create(lens.data_.get(), camera.getCropFactor(), width, height);
mod->Initialize(lens.data_.get(), LF_PF_F32, focalLen, aperture, 1000, 1, LF_RECTILINEAR, LF_MODIFY_VIGNETTING | LF_MODIFY_DISTORTION, false);
ret.data_.reset(mod);
LFModifier *ret = nullptr;
if (data_) {
if (camera.ok() && lens.ok()) {
lfModifier *mod = lfModifier::Create(lens.data_, camera.getCropFactor(), width, height);
mod->Initialize(lens.data_, LF_PF_F32, focalLen, aperture, focusDist > 0 ? focusDist : 1000, 0.0, LF_RECTILINEAR, LF_MODIFY_VIGNETTING | LF_MODIFY_DISTORTION, false);
ret = new LFModifier(mod);
}
}
return ret;
}

View File

@ -23,24 +23,34 @@
#include <lensfun.h>
#include <glibmm.h>
#include <memory>
#include "lcp.h"
namespace rtengine {
class LFModifier {
class LFModifier: public LensCorrection {
public:
~LFModifier();
bool ok() const;
void correctDistortion(double &x, double &y);
void processVignetteLine(int width, int y, float *line);
void processVignetteLine3Channels(int width, int y, float *line);
void correctDistortion(double &x, double &y, int cx, int cy, double scale) const;
bool supportsAutoFill() const { return false; }
bool supportsCA() const { return false; }
void correctCA(double &x, double &y, int channel) const {}
void processVignetteLine(int width, int y, float *line) const;
void processVignetteLine3Channels(int width, int y, float *line) const;
private:
explicit LFModifier(lfModifier *m);
LFModifier(const LFModifier &);
LFModifier &operator=(const LFModifier &);
friend class LFDatabase;
std::shared_ptr<lfModifier> data_;
lfModifier *data_;
};
class LFCamera {
public:
LFCamera();
bool ok() const;
Glib::ustring getMake() const;
@ -51,35 +61,41 @@ public:
private:
friend class LFDatabase;
std::shared_ptr<lfCamera> data_;
const lfCamera *data_;
};
class LFLens {
public:
LFLens();
bool ok() const;
Glib::ustring getDisplayString() const;
private:
friend class LFDatabase;
std::shared_ptr<lfLens> data_;
const lfLens *data_;
};
class LFDatabase {
public:
static bool init();
static LFDatabase *getInstance();
static const LFDatabase *getInstance();
std::vector<LFCamera> getCameras();
std::vector<LFLens> getLenses(const LFCamera &camera);
LFCamera findCamera(const Glib::ustring &make, const Glib::ustring &model);
LFLens findLens(const LFCamera &camera, const Glib::ustring &name);
LFModifier getModifier(const LFCamera &camera, const LFLens &lens,
int width, int height,
float focalLen, float aperture);
~LFDatabase();
std::vector<LFCamera> getCameras() const;
std::vector<LFLens> getLenses(const LFCamera &camera) const;
LFCamera findCamera(const Glib::ustring &make, const Glib::ustring &model) const;
LFLens findLens(const LFCamera &camera, const Glib::ustring &name) const;
LFModifier *getModifier(const LFCamera &camera, const LFLens &lens,
int width, int height,
float focalLen, float aperture, float focusDist) const;
private:
LFDatabase();
LFDatabase(const LFDatabase &);
LFDatabase &operator=(const LFDatabase &);
static LFDatabase instance_;
std::shared_ptr<lfDatabase> data_;
lfDatabase *data_;
};
} // namespace rtengine

View File

@ -959,9 +959,6 @@ IImage8* Thumbnail::quickProcessImage (const procparams::ProcParams& params, int
IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rheight, TypeInterpolation interp, const ImageMetaData *metadata, double& myscale)
{
std::string camName = metadata->getCamera();
double focalLen = metadata->getFocalLen();
double focalLen35mm = metadata->getFocalLen35mm();
float focusDist = metadata->getFocusDist();
float shutter = metadata->getShutterSpeed();
float fnumber = metadata->getFNumber();
float iso = metadata->getISOSpeed();

View File

@ -169,6 +169,7 @@ if(WIN32)
${GLIBMM_INCLUDE_DIRS}
${GTKMM_INCLUDE_DIRS}
${GTK_INCLUDE_DIRS}
${LENSFUN_INCLUDE_DIRS}
)
link_directories(. "${PROJECT_SOURCE_DIR}/rtexif"
${EXTRA_LIBDIR}
@ -194,6 +195,7 @@ else()
${GTK_INCLUDE_DIRS}
${IPTCDATA_INCLUDE_DIRS}
${LCMS_INCLUDE_DIRS}
${LENSFUN_INCLUDE_DIRS}
)
link_directories(${EXTRA_LIBDIR}
${CANBERRA-GTK_LIBRARY_DIRS}
@ -251,6 +253,7 @@ target_link_libraries(rth rtengine
${PNG_LIBRARIES}
${TIFF_LIBRARIES}
${ZLIB_LIBRARIES}
${LENSFUN_LIBRARIES}
)
target_link_libraries(rth-cli rtengine
@ -270,6 +273,7 @@ target_link_libraries(rth-cli rtengine
${PNG_LIBRARIES}
${TIFF_LIBRARIES}
${ZLIB_LIBRARIES}
${LENSFUN_LIBRARIES}
)
# Install executables

View File

@ -21,7 +21,7 @@
#include <glibmm.h>
#include "options.h"
#include "rtengine.h"
#include "../rtengine/rtengine.h"
class CacheImageData: public rtengine::ImageMetaData
{
@ -89,9 +89,9 @@ public:
bool hasExif() const { return false; }
const rtexif::TagDirectory *getExifData() const { return NULL; }
bool hasIPTC() const { return false; }
const procparams::IPTCPairs getIPTCData () const { return procparams::IPTCPairs(); }
const rtengine::procparams::IPTCPairs getIPTCData () const { return rtengine::procparams::IPTCPairs(); }
struct tm getDateTime () const { struct tm ret; return ret; }
time_t getDateTimeAsTS() const { time_t ret; return ret; }
time_t getDateTimeAsTS() const { return time_t(-1); }
int getISOSpeed() const { return iso; }
double getFNumber() const { return fnumber; }
double getFocalLen() const { return focalLen; }

View File

@ -291,6 +291,11 @@ void ParamsEdited::set (bool v)
lensProf.useDist = v;
lensProf.useVign = v;
lensProf.useCA = v;
lensProf.useLensfun = v;
lensProf.lfAutoMatch = v;
lensProf.lfCameraMake = v;
lensProf.lfCameraModel = v;
lensProf.lfLens = v;
perspective.horizontal = v;
perspective.vertical = v;
gradient.enabled = v;
@ -825,6 +830,11 @@ void ParamsEdited::initFrom (const std::vector<rtengine::procparams::ProcParams>
lensProf.useDist = lensProf.useDist && p.lensProf.useDist == other.lensProf.useDist;
lensProf.useVign = lensProf.useVign && p.lensProf.useVign == other.lensProf.useVign;
lensProf.useCA = lensProf.useCA && p.lensProf.useCA == other.lensProf.useCA;
lensProf.useLensfun = lensProf.useLensfun && p.lensProf.useLensfun == other.lensProf.useLensfun;
lensProf.lfAutoMatch = lensProf.lfAutoMatch && p.lensProf.lfAutoMatch == other.lensProf.lfAutoMatch;
lensProf.lfCameraMake = lensProf.lfCameraMake && p.lensProf.lfCameraMake == other.lensProf.lfCameraMake;
lensProf.lfCameraModel = lensProf.lfCameraModel && p.lensProf.lfCameraModel == other.lensProf.lfCameraModel;
lensProf.lfLens = lensProf.lfLens && p.lensProf.lfLens == other.lensProf.lfLens;
perspective.horizontal = perspective.horizontal && p.perspective.horizontal == other.perspective.horizontal;
perspective.vertical = perspective.vertical && p.perspective.vertical == other.perspective.vertical;
gradient.enabled = gradient.enabled && p.gradient.enabled == other.gradient.enabled;

View File

@ -428,6 +428,7 @@ class LensProfParamsEdited
{
public:
bool lcpFile, useDist, useVign, useCA;
bool useLensfun, lfAutoMatch, lfCameraMake, lfCameraModel, lfLens;
bool isUnchanged() const;
};