added basic integration of lensfun
so far only distortion correction, and no GUI yet
This commit is contained in:
parent
b4d3caf9c6
commit
dde94bc6d3
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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 );
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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; }
|
||||
|
@ -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;
|
||||
|
@ -428,6 +428,7 @@ class LensProfParamsEdited
|
||||
{
|
||||
public:
|
||||
bool lcpFile, useDist, useVign, useCA;
|
||||
bool useLensfun, lfAutoMatch, lfCameraMake, lfCameraModel, lfLens;
|
||||
|
||||
bool isUnchanged() const;
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user