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 (GTHREAD REQUIRED gthread-2.0>=2.44)
pkg_check_modules (GOBJECT REQUIRED gobject-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 (SIGC REQUIRED sigc++-2.0>=2.3.1)
pkg_check_modules (LENSFUN REQUIRED lensfun>=0.2)
if(WIN32) if(WIN32)
add_definitions(-DWIN32) add_definitions(-DWIN32)

View File

@ -9,6 +9,7 @@ include_directories(${EXTRA_INCDIR}
${GTK_INCLUDE_DIRS} ${GTK_INCLUDE_DIRS}
${IPTCDATA_INCLUDE_DIRS} ${IPTCDATA_INCLUDE_DIRS}
${LCMS_INCLUDE_DIRS} ${LCMS_INCLUDE_DIRS}
${LENSFUN_INCLUDE_DIRS}
) )
link_directories("${PROJECT_SOURCE_DIR}/rtexif" link_directories("${PROJECT_SOURCE_DIR}/rtexif"
@ -109,6 +110,7 @@ set(RTENGINESOURCEFILES
slicer.cc slicer.cc
stdimagesource.cc stdimagesource.cc
utils.cc utils.cc
rtlensfun.cc
) )
if(NOT WITH_SYSTEM_KLT) if(NOT WITH_SYSTEM_KLT)
@ -153,6 +155,7 @@ target_link_libraries(rtengine rtexif
${PNG_LIBRARIES} ${PNG_LIBRARIES}
${TIFF_LIBRARIES} ${TIFF_LIBRARIES}
${ZLIB_LIBRARIES} ${ZLIB_LIBRARIES}
${LENSFUN_LIBRARIES}
) )
install(FILES ${CAMCONSTSFILE} DESTINATION "${DATADIR}" PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ) 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 false;
} }
return (params.lensProf.lcpFile.length() > 0 && return (params.lensProf.useDist &&
params.lensProf.useDist); (params.lensProf.useLensfun ||
params.lensProf.lcpFile.length() > 0));
} }
} // namespace } // namespace

View File

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

View File

@ -60,7 +60,7 @@ class ImProcFunctions
TRANSFORM_HIGH_QUALITY_FULLIMAGE TRANSFORM_HIGH_QUALITY_FULLIMAGE
}; };
void transformLuminanceOnly (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int oW, int oH, int fW, int fH); 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 (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); void sharpenHaloCtrl (LabImage* lab, float** blurmap, float** base, int W, int H, SharpeningParams &sharpenParam);
@ -74,6 +74,7 @@ class ImProcFunctions
bool needsGradient (); bool needsGradient ();
bool needsVignetting (); bool needsVignetting ();
bool needsLCP (); bool needsLCP ();
bool needsLensfun();
// static cmsUInt8Number* Mempro = NULL; // 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) 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); Image16* lab2rgb16 (LabImage* lab, int cx, int cy, int cw, int ch, const procparams::ColorManagementParams &icm, bool bw, GammaValues *ga = nullptr);
// CieImage *ciec; // 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, 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 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 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 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); 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 rgb2lab (const Imagefloat &src, LabImage &dst, const Glib::ustring &workingSpace);
void lab2rgb (const LabImage &src, Imagefloat &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 "rtthumbnail.h"
#include "profilestore.h" #include "profilestore.h"
#include "../rtgui/threadutils.h" #include "../rtgui/threadutils.h"
#include "rtlensfun.h"
namespace rtengine namespace rtengine
{ {
@ -50,6 +51,7 @@ int init (const Settings* s, Glib::ustring baseDir, Glib::ustring userSettingsDi
Color::init (); Color::init ();
PerceptualToneCurve::init (); PerceptualToneCurve::init ();
RawImageSource::init (); RawImageSource::init ();
LFDatabase::init();
delete lcmsMutex; delete lcmsMutex;
lcmsMutex = new MyMutex; lcmsMutex = new MyMutex;
dfm.init( s->darkFramesPath ); dfm.init( s->darkFramesPath );

View File

@ -24,6 +24,7 @@
#include "mytime.h" #include "mytime.h"
#include "rt_math.h" #include "rt_math.h"
#include "sleef.c" #include "sleef.c"
#include "rtlensfun.h"
using namespace std; 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) int cx, int cy, double scale)
{ {
assert (lcp); assert (lcp);
x += cx; // x += cx;
y += cy; // y += cy;
lcp->correctDistortion(x, y, scale); // std::cout << "DIST: x=" << x << ", y=" << y;
x -= (cx * scale); lcp->correctDistortion(x, y, cx, cy, scale);
y -= (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))) #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, 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; 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 // 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; const int DivisionsPerBorder = 32;
@ -316,9 +319,30 @@ void ImProcFunctions::transform (Imagefloat* original, Imagefloat* transformed,
float focusDist = metadata->getFocusDist(); float focusDist = metadata->getFocusDist();
double fNumber = metadata->getFNumber(); 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); LCPProfile *pLCPProf = lcpStore->getProfile (params->lensProf.lcpFile);
if (pLCPProf) { 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); transformLuminanceOnly (original, transformed, cx, cy, oW, oH, fW, fH);
} else { } else {
TransformMode mode; 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 w2 = (double) oW / 2.0 - 0.5;
double h2 = (double) oH / 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) { switch (mode) {
case ImProcFunctions::TRANSFORM_HIGH_QUALITY_FULLIMAGE: case ImProcFunctions::TRANSFORM_HIGH_QUALITY_FULLIMAGE:
enableLCPCA = pLCPMap && params->lensProf.useCA && pLCPMap->enableCA; enableLCPCA = pLCPMap && params->lensProf.useCA && pLCPMap->supportsCA();
// no break on purpose // no break on purpose
case ImProcFunctions::TRANSFORM_HIGH_QUALITY: case ImProcFunctions::TRANSFORM_HIGH_QUALITY:
enableLCPDist = pLCPMap && params->lensProf.useDist; 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)) { if (!needsCA() && !needsDistortion() && !needsRotation() && !needsPerspective() && (!params->lensProf.useDist || pLCPMap == nullptr)) {
return 1; return 1;
} }
if (pLCPMap && !pLCPMap->supportsAutoFill()) {
return 1;
}
double scaleU = 2, scaleL = 0.001; // upper and lower border, iterate inbetween double scaleU = 2, scaleL = 0.001; // upper and lower border, iterate inbetween
do { do {
@ -1019,12 +1047,17 @@ bool ImProcFunctions::needsVignetting ()
bool ImProcFunctions::needsLCP () 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 () 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; 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) { if (isFisheye) {
double u = x * scale; double u = x * scale;
double v = y * scale; double v = y * scale;
@ -253,6 +256,9 @@ void LCPMapper::correctDistortion(double& x, double& y, double scale) const
x = xnew * mc.fx + x0; x = xnew * mc.fx + x0;
y = ynew * mc.fy + y0; y = ynew * mc.fy + y0;
} }
x -= cx * scale;
y -= cy * scale;
} }
void LCPMapper::correctCA(double& x, double& y, int channel) const void LCPMapper::correctCA(double& x, double& y, int channel) const

View File

@ -136,8 +136,20 @@ public:
#define lcpStore LCPStore::getInstance() #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 // Once precalculated class to correct a point
class LCPMapper class LCPMapper: public LensCorrection
{ {
bool useCADist; // should the distortion in the CA info be used? 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, LCPMapper(LCPProfile* pProf, float focalLength, float focalLength35mm, float focusDist, float aperture, bool vignette, bool useCADistP, int fullWidth, int fullHeight,
const CoarseTransformParams& coarse, int rawRotationDeg); 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 correctCA(double& x, double& y, int channel) const;
void processVignetteLine(int width, int y, float *line) const; void processVignetteLine(int width, int y, float *line) const;
void processVignetteLine3Channels(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 = ""; lcpFile = "";
useDist = useVign = true; useDist = useVign = true;
useCA = false; useCA = false;
useLensfun = false;
lfAutoMatch = true;
lfCameraMake = "";
lfCameraModel = "";
lfLens = "";
} }
void CoarseTransformParams::setDefaults() 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); 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 // save perspective correction
if (!pedited || pedited->perspective.horizontal) { if (!pedited || pedited->perspective.horizontal) {
keyFile.set_double ("Perspective", "Horizontal", 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; 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 // load perspective correction
@ -8432,6 +8488,11 @@ bool ProcParams::operator== (const ProcParams& other)
&& lensProf.useDist == other.lensProf.useDist && lensProf.useDist == other.lensProf.useDist
&& lensProf.useVign == other.lensProf.useVign && lensProf.useVign == other.lensProf.useVign
&& lensProf.useCA == other.lensProf.useCA && 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.horizontal == other.perspective.horizontal
&& perspective.vertical == other.perspective.vertical && perspective.vertical == other.perspective.vertical
&& gradient.enabled == other.gradient.enabled && gradient.enabled == other.gradient.enabled

View File

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

View File

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

View File

@ -23,24 +23,34 @@
#include <lensfun.h> #include <lensfun.h>
#include <glibmm.h> #include <glibmm.h>
#include <memory> #include <memory>
#include "lcp.h"
namespace rtengine { namespace rtengine {
class LFModifier { class LFModifier: public LensCorrection {
public: public:
~LFModifier();
bool ok() const; bool ok() const;
void correctDistortion(double &x, double &y); void correctDistortion(double &x, double &y, int cx, int cy, double scale) const;
void processVignetteLine(int width, int y, float *line); bool supportsAutoFill() const { return false; }
void processVignetteLine3Channels(int width, int y, float *line); 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: private:
explicit LFModifier(lfModifier *m);
LFModifier(const LFModifier &);
LFModifier &operator=(const LFModifier &);
friend class LFDatabase; friend class LFDatabase;
std::shared_ptr<lfModifier> data_; lfModifier *data_;
}; };
class LFCamera { class LFCamera {
public: public:
LFCamera();
bool ok() const; bool ok() const;
Glib::ustring getMake() const; Glib::ustring getMake() const;
@ -51,35 +61,41 @@ public:
private: private:
friend class LFDatabase; friend class LFDatabase;
std::shared_ptr<lfCamera> data_; const lfCamera *data_;
}; };
class LFLens { class LFLens {
public: public:
LFLens();
bool ok() const; bool ok() const;
Glib::ustring getDisplayString() const; Glib::ustring getDisplayString() const;
private: private:
friend class LFDatabase; friend class LFDatabase;
std::shared_ptr<lfLens> data_; const lfLens *data_;
}; };
class LFDatabase { class LFDatabase {
public: public:
static bool init(); static bool init();
static LFDatabase *getInstance(); static const LFDatabase *getInstance();
std::vector<LFCamera> getCameras(); ~LFDatabase();
std::vector<LFLens> getLenses(const LFCamera &camera);
LFCamera findCamera(const Glib::ustring &make, const Glib::ustring &model); std::vector<LFCamera> getCameras() const;
LFLens findLens(const LFCamera &camera, const Glib::ustring &name); std::vector<LFLens> getLenses(const LFCamera &camera) const;
LFModifier getModifier(const LFCamera &camera, const LFLens &lens, LFCamera findCamera(const Glib::ustring &make, const Glib::ustring &model) const;
int width, int height, LFLens findLens(const LFCamera &camera, const Glib::ustring &name) const;
float focalLen, float aperture); LFModifier *getModifier(const LFCamera &camera, const LFLens &lens,
int width, int height,
float focalLen, float aperture, float focusDist) const;
private: private:
LFDatabase();
LFDatabase(const LFDatabase &);
LFDatabase &operator=(const LFDatabase &);
static LFDatabase instance_; static LFDatabase instance_;
std::shared_ptr<lfDatabase> data_; lfDatabase *data_;
}; };
} // namespace rtengine } // 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) IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rheight, TypeInterpolation interp, const ImageMetaData *metadata, double& myscale)
{ {
std::string camName = metadata->getCamera(); std::string camName = metadata->getCamera();
double focalLen = metadata->getFocalLen();
double focalLen35mm = metadata->getFocalLen35mm();
float focusDist = metadata->getFocusDist();
float shutter = metadata->getShutterSpeed(); float shutter = metadata->getShutterSpeed();
float fnumber = metadata->getFNumber(); float fnumber = metadata->getFNumber();
float iso = metadata->getISOSpeed(); float iso = metadata->getISOSpeed();

View File

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

View File

@ -21,7 +21,7 @@
#include <glibmm.h> #include <glibmm.h>
#include "options.h" #include "options.h"
#include "rtengine.h" #include "../rtengine/rtengine.h"
class CacheImageData: public rtengine::ImageMetaData class CacheImageData: public rtengine::ImageMetaData
{ {
@ -89,9 +89,9 @@ public:
bool hasExif() const { return false; } bool hasExif() const { return false; }
const rtexif::TagDirectory *getExifData() const { return NULL; } const rtexif::TagDirectory *getExifData() const { return NULL; }
bool hasIPTC() const { return false; } 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; } 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; } int getISOSpeed() const { return iso; }
double getFNumber() const { return fnumber; } double getFNumber() const { return fnumber; }
double getFocalLen() const { return focalLen; } double getFocalLen() const { return focalLen; }

View File

@ -291,6 +291,11 @@ void ParamsEdited::set (bool v)
lensProf.useDist = v; lensProf.useDist = v;
lensProf.useVign = v; lensProf.useVign = v;
lensProf.useCA = v; lensProf.useCA = v;
lensProf.useLensfun = v;
lensProf.lfAutoMatch = v;
lensProf.lfCameraMake = v;
lensProf.lfCameraModel = v;
lensProf.lfLens = v;
perspective.horizontal = v; perspective.horizontal = v;
perspective.vertical = v; perspective.vertical = v;
gradient.enabled = 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.useDist = lensProf.useDist && p.lensProf.useDist == other.lensProf.useDist;
lensProf.useVign = lensProf.useVign && p.lensProf.useVign == other.lensProf.useVign; lensProf.useVign = lensProf.useVign && p.lensProf.useVign == other.lensProf.useVign;
lensProf.useCA = lensProf.useCA && p.lensProf.useCA == other.lensProf.useCA; 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.horizontal = perspective.horizontal && p.perspective.horizontal == other.perspective.horizontal;
perspective.vertical = perspective.vertical && p.perspective.vertical == other.perspective.vertical; perspective.vertical = perspective.vertical && p.perspective.vertical == other.perspective.vertical;
gradient.enabled = gradient.enabled && p.gradient.enabled == other.gradient.enabled; gradient.enabled = gradient.enabled && p.gradient.enabled == other.gradient.enabled;

View File

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