LCP (Lens Correction Profile) support
see issue 1343
This commit is contained in:
parent
f38752bd00
commit
2d59057d57
@ -183,6 +183,7 @@ if (WIN32)
|
|||||||
endif (WIN32)
|
endif (WIN32)
|
||||||
# you may need lcms v1.xx for older version : pkg_check_modules (LCMS REQUIRED lcms<=1.99)
|
# you may need lcms v1.xx for older version : pkg_check_modules (LCMS REQUIRED lcms<=1.99)
|
||||||
pkg_check_modules (LCMS REQUIRED lcms2)
|
pkg_check_modules (LCMS REQUIRED lcms2)
|
||||||
|
pkg_check_modules (EXPAT REQUIRED expat>=2.0)
|
||||||
pkg_check_modules (IPTCDATA REQUIRED libiptcdata)
|
pkg_check_modules (IPTCDATA REQUIRED libiptcdata)
|
||||||
find_package (JPEG REQUIRED)
|
find_package (JPEG REQUIRED)
|
||||||
find_package (PNG REQUIRED)
|
find_package (PNG REQUIRED)
|
||||||
|
@ -960,6 +960,8 @@ TP_LABCURVE_SATURATION;Sättigung
|
|||||||
TP_LENSGEOM_AUTOCROP;Auto-Schneiden
|
TP_LENSGEOM_AUTOCROP;Auto-Schneiden
|
||||||
TP_LENSGEOM_FILL;Auto-Füllen
|
TP_LENSGEOM_FILL;Auto-Füllen
|
||||||
TP_LENSGEOM_LABEL;Objektivkorrekturen
|
TP_LENSGEOM_LABEL;Objektivkorrekturen
|
||||||
|
TP_LENSPROFILE_FILEDLGFILTERLCP;Linsen-Korrekturdateien
|
||||||
|
TP_LENSPROFILE_LABEL;Linsen-Korrekturprofil
|
||||||
TP_LUMADENOISE_EDGETOLERANCE;Kantentoleranz
|
TP_LUMADENOISE_EDGETOLERANCE;Kantentoleranz
|
||||||
TP_LUMADENOISE_LABEL;Luminanz-Rauschfilter
|
TP_LUMADENOISE_LABEL;Luminanz-Rauschfilter
|
||||||
TP_LUMADENOISE_RADIUS;Radius
|
TP_LUMADENOISE_RADIUS;Radius
|
||||||
|
@ -960,6 +960,8 @@ TP_LABCURVE_SATURATION;Saturation
|
|||||||
TP_LENSGEOM_AUTOCROP; Auto Crop
|
TP_LENSGEOM_AUTOCROP; Auto Crop
|
||||||
TP_LENSGEOM_FILL;Auto Fill
|
TP_LENSGEOM_FILL;Auto Fill
|
||||||
TP_LENSGEOM_LABEL;Lens / Geometry
|
TP_LENSGEOM_LABEL;Lens / Geometry
|
||||||
|
TP_LENSPROFILE_FILEDLGFILTERLCP;Lens correction files
|
||||||
|
TP_LENSPROFILE_LABEL;Lens Correction Profile
|
||||||
TP_LUMADENOISE_EDGETOLERANCE;Edge Tolerance
|
TP_LUMADENOISE_EDGETOLERANCE;Edge Tolerance
|
||||||
TP_LUMADENOISE_LABEL;Luminance Noise Reduction
|
TP_LUMADENOISE_LABEL;Luminance Noise Reduction
|
||||||
TP_LUMADENOISE_RADIUS;Radius
|
TP_LUMADENOISE_RADIUS;Radius
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
include_directories (${EXTRA_INCDIR} ${GTHREAD_INCLUDE_DIRS} ${GOBJECT_INCLUDE_DIRS} ${GLIB2_INCLUDE_DIRS}
|
include_directories (${EXTRA_INCDIR} ${GTHREAD_INCLUDE_DIRS} ${GOBJECT_INCLUDE_DIRS} ${GLIB2_INCLUDE_DIRS}
|
||||||
${GLIBMM_INCLUDE_DIRS} ${IPTCDATA_INCLUDE_DIRS} ${LCMS_INCLUDE_DIRS}
|
${GLIBMM_INCLUDE_DIRS} ${IPTCDATA_INCLUDE_DIRS} ${LCMS_INCLUDE_DIRS} ${EXPAT_INCLUDE_DIRS}
|
||||||
${GTKMM_INCLUDE_DIRS} ${GTK_INCLUDE_DIRS})
|
${GTKMM_INCLUDE_DIRS} ${GTK_INCLUDE_DIRS})
|
||||||
link_directories (${CMAKE_CURRENT_SOURCE_DIR}/../rtexif ${EXTRA_LIBDIR} ${GTHREAD_LIBRARY_DIRS}
|
link_directories (${CMAKE_CURRENT_SOURCE_DIR}/../rtexif ${EXTRA_LIBDIR} ${GTHREAD_LIBRARY_DIRS}
|
||||||
${GOBJECT_LIBRARY_DIRS} ${GLIB2_LIBRARY_DIRS} ${GLIBMM_LIBRARY_DIRS}
|
${GOBJECT_LIBRARY_DIRS} ${GLIB2_LIBRARY_DIRS} ${GLIBMM_LIBRARY_DIRS}
|
||||||
${IPTCDATA_LIBRARY_DIRS} ${LCMS_LIBRARY_DIRS})
|
${IPTCDATA_LIBRARY_DIRS} ${LCMS_LIBRARY_DIRS} ${EXPAT_LIBRARY_DIRS})
|
||||||
|
|
||||||
set (RTENGINESOURCEFILES safegtk.cc colortemp.cc curves.cc flatcurves.cc diagonalcurves.cc dcraw.cc iccstore.cc
|
set (RTENGINESOURCEFILES safegtk.cc colortemp.cc curves.cc flatcurves.cc diagonalcurves.cc dcraw.cc iccstore.cc
|
||||||
dfmanager.cc ffmanager.cc rawimage.cc image8.cc image16.cc imagefloat.cc imagedata.cc imageio.cc improcfun.cc init.cc dcrop.cc
|
dfmanager.cc ffmanager.cc rawimage.cc image8.cc image16.cc imagefloat.cc imagedata.cc imageio.cc improcfun.cc init.cc dcrop.cc
|
||||||
@ -14,7 +14,7 @@ set (RTENGINESOURCEFILES safegtk.cc colortemp.cc curves.cc flatcurves.cc diagona
|
|||||||
jpeg_memsrc.cc jdatasrc.cc
|
jpeg_memsrc.cc jdatasrc.cc
|
||||||
PF_correct_RT.cc
|
PF_correct_RT.cc
|
||||||
dirpyrLab_denoise.cc dirpyrLab_equalizer.cc dirpyr_equalizer.cc
|
dirpyrLab_denoise.cc dirpyrLab_equalizer.cc dirpyr_equalizer.cc
|
||||||
calc_distort.cc dcp.cc
|
calc_distort.cc lcp.cc dcp.cc
|
||||||
klt/convolve.cc klt/error.cc klt/klt.cc klt/klt_util.cc klt/pnmio.cc klt/pyramid.cc klt/selectGoodFeatures.cc
|
klt/convolve.cc klt/error.cc klt/klt.cc klt/klt_util.cc klt/pnmio.cc klt/pyramid.cc klt/selectGoodFeatures.cc
|
||||||
klt/storeFeatures.cc klt/trackFeatures.cc klt/writeFeatures.cc
|
klt/storeFeatures.cc klt/trackFeatures.cc klt/writeFeatures.cc
|
||||||
)
|
)
|
||||||
@ -28,5 +28,5 @@ ENDIF (BUILD_SHARED_LIBS)
|
|||||||
set_target_properties (rtengine PROPERTIES COMPILE_FLAGS "${RTENGINE_CXX_FLAGS}")
|
set_target_properties (rtengine PROPERTIES COMPILE_FLAGS "${RTENGINE_CXX_FLAGS}")
|
||||||
|
|
||||||
target_link_libraries (rtengine rtexif ${EXTRA_LIB} ${GOBJECT_LIBRARIES} ${GTHREAD_LIBRARIES}
|
target_link_libraries (rtengine rtexif ${EXTRA_LIB} ${GOBJECT_LIBRARIES} ${GTHREAD_LIBRARIES}
|
||||||
${GLIB2_LIBRARIES} ${GLIBMM_LIBRARIES} ${LCMS_LIBRARIES} ${IPTCDATA_LIBRARIES}
|
${GLIB2_LIBRARIES} ${GLIBMM_LIBRARIES} ${LCMS_LIBRARIES} ${EXPAT_LIBRARIES} ${IPTCDATA_LIBRARIES}
|
||||||
${JPEG_LIBRARIES} ${PNG_LIBRARIES} ${TIFF_LIBRARIES} ${ZLIB_LIBRARIES})
|
${JPEG_LIBRARIES} ${PNG_LIBRARIES} ${TIFF_LIBRARIES} ${ZLIB_LIBRARIES})
|
||||||
|
@ -111,7 +111,8 @@ void Crop::update (int todo) {
|
|||||||
if (needstransform && !transCrop)
|
if (needstransform && !transCrop)
|
||||||
transCrop = new Imagefloat (cropw, croph);
|
transCrop = new Imagefloat (cropw, croph);
|
||||||
if ((todo & M_TRANSFORM) && needstransform)
|
if ((todo & M_TRANSFORM) && needstransform)
|
||||||
parent->ipf.transform (baseCrop, transCrop, cropx/skip, cropy/skip, trafx/skip, trafy/skip, SKIPS(parent->fw,skip), SKIPS(parent->fh,skip));
|
parent->ipf.transform (baseCrop, transCrop, cropx/skip, cropy/skip, trafx/skip, trafy/skip, SKIPS(parent->fw,skip), SKIPS(parent->fh,skip),
|
||||||
|
parent->imgsrc->getMetaData()->getFocalLen(), parent->imgsrc->getRotateDegree());
|
||||||
if (transCrop)
|
if (transCrop)
|
||||||
baseCrop = transCrop;
|
baseCrop = transCrop;
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ class ImageSource : public InitialImage {
|
|||||||
|
|
||||||
virtual ~ImageSource () {}
|
virtual ~ImageSource () {}
|
||||||
virtual int load (Glib::ustring fname, bool batch = false) =0;
|
virtual int load (Glib::ustring fname, bool batch = false) =0;
|
||||||
virtual void preprocess (const RAWParams &raw){};
|
virtual void preprocess (const RAWParams &raw, const LensProfParams &lensProf, const CoarseTransformParams& coarse){};
|
||||||
virtual void demosaic (const RAWParams &raw){};
|
virtual void demosaic (const RAWParams &raw){};
|
||||||
virtual void flushRawData (){};
|
virtual void flushRawData (){};
|
||||||
virtual void flushRGB (){};
|
virtual void flushRGB (){};
|
||||||
@ -91,6 +91,7 @@ class ImageSource : public InitialImage {
|
|||||||
|
|
||||||
virtual void getFullSize (int& w, int& h, int tr = TR_NONE) {}
|
virtual void getFullSize (int& w, int& h, int tr = TR_NONE) {}
|
||||||
virtual void getSize (int tran, PreviewProps pp, int& w, int& h) {}
|
virtual void getSize (int tran, PreviewProps pp, int& w, int& h) {}
|
||||||
|
virtual int getRotateDegree() const { return 0; }
|
||||||
|
|
||||||
virtual ImageData* getImageData () =0;
|
virtual ImageData* getImageData () =0;
|
||||||
virtual void setProgressListener (ProgressListener* pl) {}
|
virtual void setProgressListener (ProgressListener* pl) {}
|
||||||
|
@ -122,7 +122,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
|
|||||||
|
|
||||||
progress ("Applying white balance, color correction & sRGB conversion...",100*readyphase/numofphases);
|
progress ("Applying white balance, color correction & sRGB conversion...",100*readyphase/numofphases);
|
||||||
if ( todo & M_PREPROC) {
|
if ( todo & M_PREPROC) {
|
||||||
imgsrc->preprocess( rp );
|
imgsrc->preprocess( rp, params.lensProf, params.coarse );
|
||||||
imgsrc->getRAWHistogram( histRedRaw, histGreenRaw, histBlueRaw );
|
imgsrc->getRAWHistogram( histRedRaw, histGreenRaw, histBlueRaw );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,7 +193,7 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
|
|||||||
if (needstransform && orig_prev==oprevi)
|
if (needstransform && orig_prev==oprevi)
|
||||||
oprevi = new Imagefloat (pW, pH);
|
oprevi = new Imagefloat (pW, pH);
|
||||||
if ((todo & M_TRANSFORM) && needstransform)
|
if ((todo & M_TRANSFORM) && needstransform)
|
||||||
ipf.transform (orig_prev, oprevi, 0, 0, 0, 0, pW, pH);
|
ipf.transform (orig_prev, oprevi, 0, 0, 0, 0, pW, pH, imgsrc->getMetaData()->getFocalLen(), imgsrc->getRotateDegree());
|
||||||
|
|
||||||
readyphase++;
|
readyphase++;
|
||||||
|
|
||||||
@ -579,7 +579,7 @@ void ImProcCoordinator::saveInputICCReference (const Glib::ustring& fname) {
|
|||||||
ppar.icm.input = "(none)";
|
ppar.icm.input = "(none)";
|
||||||
Imagefloat* im = new Imagefloat (fW, fH);
|
Imagefloat* im = new Imagefloat (fW, fH);
|
||||||
Image16* im16 = new Image16 (fW, fH);
|
Image16* im16 = new Image16 (fW, fH);
|
||||||
imgsrc->preprocess( ppar.raw );
|
imgsrc->preprocess( ppar.raw, ppar.lensProf, ppar.coarse );
|
||||||
imgsrc->demosaic(ppar.raw );
|
imgsrc->demosaic(ppar.raw );
|
||||||
//imgsrc->getImage (imgsrc->getWB(), 0, im, pp, ppar.hlrecovery, ppar.icm, ppar.raw);
|
//imgsrc->getImage (imgsrc->getWB(), 0, im, pp, ppar.hlrecovery, ppar.icm, ppar.raw);
|
||||||
ColorTemp currWB = ColorTemp (params.wb.temperature, params.wb.green, params.wb.method);
|
ColorTemp currWB = ColorTemp (params.wb.temperature, params.wb.green, params.wb.method);
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "coord2d.h"
|
#include "coord2d.h"
|
||||||
#include "labimage.h"
|
#include "labimage.h"
|
||||||
#include "LUT.h"
|
#include "LUT.h"
|
||||||
|
#include "lcp.h"
|
||||||
|
|
||||||
namespace rtengine {
|
namespace rtengine {
|
||||||
|
|
||||||
@ -43,10 +44,10 @@ class ImProcFunctions {
|
|||||||
bool multiThread;
|
bool multiThread;
|
||||||
float g;
|
float g;
|
||||||
|
|
||||||
void simpltransform (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH);
|
void simpltransform (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, const LCPMapper *pLCPMap);
|
||||||
void vignetting (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int oW, int oH);
|
void vignetting (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int oW, int oH);
|
||||||
void transformNonSep (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH);
|
void transformNonSep (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, const LCPMapper *pLCPMap);
|
||||||
void transformSep (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH);
|
void transformSep (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, const LCPMapper *pLCPMap);
|
||||||
void sharpenHaloCtrl (LabImage* lab, float** blurmap, float** base, int W, int H);
|
void sharpenHaloCtrl (LabImage* lab, float** blurmap, float** base, int W, int H);
|
||||||
void firstAnalysisThread(Imagefloat* original, Glib::ustring wprofile, unsigned int* histogram, int row_from, int row_to);
|
void firstAnalysisThread(Imagefloat* original, Glib::ustring wprofile, unsigned int* histogram, int row_from, int row_to);
|
||||||
void dcdamping (float** aI, float** aO, float damping, int W, int H);
|
void dcdamping (float** aI, float** aO, float damping, int W, int H);
|
||||||
@ -56,6 +57,7 @@ class ImProcFunctions {
|
|||||||
bool needsRotation ();
|
bool needsRotation ();
|
||||||
bool needsPerspective ();
|
bool needsPerspective ();
|
||||||
bool needsVignetting ();
|
bool needsVignetting ();
|
||||||
|
bool needsLCP ();
|
||||||
// static cmsUInt8Number* Mempro = NULL;
|
// static cmsUInt8Number* Mempro = NULL;
|
||||||
|
|
||||||
|
|
||||||
@ -120,7 +122,8 @@ class ImProcFunctions {
|
|||||||
void MunsellLch (float lum, float hue, float chrom, float memChprov, float &correction, int zone);//jacques: Munsell correction
|
void MunsellLch (float lum, float hue, float chrom, float memChprov, float &correction, int zone);//jacques: Munsell correction
|
||||||
void colorCurve (LabImage* lold, LabImage* lnew);
|
void colorCurve (LabImage* lold, LabImage* lnew);
|
||||||
void sharpening (LabImage* lab, float** buffer);
|
void sharpening (LabImage* lab, float** buffer);
|
||||||
void transform (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH);
|
void transform (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH,
|
||||||
|
double focalLen, int rawRotationDeg);
|
||||||
void lab2monitorRgb (LabImage* lab, Image8* image);
|
void lab2monitorRgb (LabImage* lab, Image8* image);
|
||||||
void resize (Image16* src, Image16* dst, float dScale);
|
void resize (Image16* src, Image16* dst, float dScale);
|
||||||
void deconvsharpening (LabImage* lab, float** buffer);
|
void deconvsharpening (LabImage* lab, float** buffer);
|
||||||
|
@ -176,18 +176,24 @@ bool ImProcFunctions::transCoord (int W, int H, int x, int y, int w, int h, int&
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImProcFunctions::transform (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH) {
|
void ImProcFunctions::transform (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH,
|
||||||
|
double focalLen, int rawRotationDeg) {
|
||||||
|
LCPMapper *pLCPMap=NULL;
|
||||||
|
if (needsLCP() && focalLen>0) {
|
||||||
|
LCPProfile *pLCPProf=lcpStore->getProfile(params->lensProf.lcpFile);
|
||||||
|
if (pLCPProf) pLCPMap=new LCPMapper(pLCPProf, focalLen, false, original->width, original->height, params->coarse, rawRotationDeg);
|
||||||
|
}
|
||||||
|
|
||||||
if (!(needsCA() || needsDistortion() || needsRotation() || needsPerspective()) && needsVignetting())
|
if (!(needsCA() || needsDistortion() || needsRotation() || needsPerspective() || needsLCP()) && needsVignetting())
|
||||||
vignetting (original, transformed, cx, cy, oW, oH);
|
vignetting (original, transformed, cx, cy, oW, oH);
|
||||||
else if (!needsCA()) {
|
else if (!needsCA()) {
|
||||||
if (scale==1)
|
if (scale==1)
|
||||||
transformNonSep (original, transformed, cx, cy, sx, sy, oW, oH);
|
transformNonSep (original, transformed, cx, cy, sx, sy, oW, oH, pLCPMap);
|
||||||
else
|
else
|
||||||
simpltransform (original, transformed, cx, cy, sx, sy, oW, oH);
|
simpltransform (original, transformed, cx, cy, sx, sy, oW, oH, pLCPMap);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
transformSep (original, transformed, cx, cy, sx, sy, oW, oH);
|
transformSep (original, transformed, cx, cy, sx, sy, oW, oH, pLCPMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void calcVignettingParams(int oW, int oH, const VignettingParams& vignetting, double &w2, double &h2, double& maxRadius, double &v, double &b, double &mul)
|
void calcVignettingParams(int oW, int oH, const VignettingParams& vignetting, double &w2, double &h2, double& maxRadius, double &v, double &b, double &mul)
|
||||||
@ -209,6 +215,7 @@ void calcVignettingParams(int oW, int oH, const VignettingParams& vignetting, do
|
|||||||
mul = (1.0-v) / tanh(b);
|
mul = (1.0-v) / tanh(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Transform vignetting only
|
||||||
void ImProcFunctions::vignetting (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int oW, int oH) {
|
void ImProcFunctions::vignetting (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int oW, int oH) {
|
||||||
|
|
||||||
double vig_w2;
|
double vig_w2;
|
||||||
@ -234,7 +241,8 @@ void ImProcFunctions::vignetting (Imagefloat* original, Imagefloat* transformed,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#include "cubint.cc"
|
#include "cubint.cc"
|
||||||
void ImProcFunctions::transformNonSep (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH) {
|
// Transform WITHOUT scaling or CA, cubic interpolation
|
||||||
|
void ImProcFunctions::transformNonSep (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, const LCPMapper *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;
|
||||||
|
|
||||||
@ -247,14 +255,13 @@ void ImProcFunctions::transformNonSep (Imagefloat* original, Imagefloat* transfo
|
|||||||
calcVignettingParams(oW, oH, params->vignetting, vig_w2, vig_h2, maxRadius, v, b, mul);
|
calcVignettingParams(oW, oH, params->vignetting, vig_w2, vig_h2, maxRadius, v, b, mul);
|
||||||
|
|
||||||
// auxiliary variables for distortion correction
|
// auxiliary variables for distortion correction
|
||||||
|
bool needsDist = needsDistortion(); // for performance
|
||||||
double a = params->distortion.amount;
|
double a = params->distortion.amount;
|
||||||
|
|
||||||
// auxiliary variables for rotation
|
// auxiliary variables for rotation
|
||||||
double cost = cos(params->rotate.degree * RT_PI/180.0);
|
double cost = cos(params->rotate.degree * RT_PI/180.0);
|
||||||
double sint = sin(params->rotate.degree * RT_PI/180.0);
|
double sint = sin(params->rotate.degree * RT_PI/180.0);
|
||||||
|
|
||||||
bool dovign = params->vignetting.amount != 0;
|
|
||||||
|
|
||||||
// auxiliary variables for vertical perspective correction
|
// auxiliary variables for vertical perspective correction
|
||||||
double vpdeg = params->perspective.vertical / 100.0 * 45.0;
|
double vpdeg = params->perspective.vertical / 100.0 * 45.0;
|
||||||
double vpalpha = (90.0 - vpdeg) / 180.0 * RT_PI;
|
double vpalpha = (90.0 - vpdeg) / 180.0 * RT_PI;
|
||||||
@ -273,8 +280,11 @@ void ImProcFunctions::transformNonSep (Imagefloat* original, Imagefloat* transfo
|
|||||||
#pragma omp parallel for if (multiThread)
|
#pragma omp parallel for if (multiThread)
|
||||||
for (int y=0; y<transformed->height; y++) {
|
for (int y=0; y<transformed->height; y++) {
|
||||||
for (int x=0; x<transformed->width; x++) {
|
for (int x=0; x<transformed->width; x++) {
|
||||||
double x_d = ascale * (x + cx - w2); // centering x coord & scale
|
double x_d=x,y_d=y;
|
||||||
double y_d = ascale * (y + cy - h2); // centering y coord & scale
|
if (pLCPMap) pLCPMap->correctDistortion(x_d,y_d); // must be first transform
|
||||||
|
|
||||||
|
x_d = ascale * (x_d + cx - w2); // centering x coord & scale
|
||||||
|
y_d = ascale * (y_d + cy - h2); // centering y coord & scale
|
||||||
double vig_x_d = ascale * (x + cx - vig_w2); // centering x coord & scale
|
double vig_x_d = ascale * (x + cx - vig_w2); // centering x coord & scale
|
||||||
double vig_y_d = ascale * (y + cy - vig_h2); // centering y coord & scale
|
double vig_y_d = ascale * (y + cy - vig_h2); // centering y coord & scale
|
||||||
|
|
||||||
@ -291,14 +301,18 @@ void ImProcFunctions::transformNonSep (Imagefloat* original, Imagefloat* transfo
|
|||||||
double Dy = x_d * sint + y_d * cost;
|
double Dy = x_d * sint + y_d * cost;
|
||||||
|
|
||||||
// distortion correction
|
// distortion correction
|
||||||
double r = sqrt(Dx*Dx + Dy*Dy) / maxRadius;
|
double s = 1;
|
||||||
double s = 1.0 - a + a * r ;
|
if (needsDist) {
|
||||||
|
double r = sqrt(Dx*Dx + Dy*Dy) / maxRadius; // sqrt is slow
|
||||||
|
s = 1.0 - a + a * r ;
|
||||||
Dx *= s;
|
Dx *= s;
|
||||||
Dy *= s;
|
Dy *= s;
|
||||||
|
}
|
||||||
|
|
||||||
double vig_Dx = vig_x_d * cost - vig_y_d * sint;
|
double vig_Dx = vig_x_d * cost - vig_y_d * sint;
|
||||||
double vig_Dy = vig_x_d * sint + vig_y_d * cost;
|
double vig_Dy = vig_x_d * sint + vig_y_d * cost;
|
||||||
double r2 = sqrt(vig_Dx*vig_Dx + vig_Dy*vig_Dy);
|
|
||||||
|
double r2 = needsVignetting() ? sqrt(vig_Dx*vig_Dx + vig_Dy*vig_Dy) : 0;
|
||||||
|
|
||||||
// de-center
|
// de-center
|
||||||
Dx += w2;
|
Dx += w2;
|
||||||
@ -313,7 +327,7 @@ void ImProcFunctions::transformNonSep (Imagefloat* original, Imagefloat* transfo
|
|||||||
|
|
||||||
// multiplier for vignetting correction
|
// multiplier for vignetting correction
|
||||||
double vignmul = 1.0;
|
double vignmul = 1.0;
|
||||||
if (dovign)
|
if (needsVignetting())
|
||||||
vignmul /= (v + mul * tanh (b*(maxRadius-s*r2) / maxRadius));
|
vignmul /= (v + mul * tanh (b*(maxRadius-s*r2) / maxRadius));
|
||||||
|
|
||||||
if (yc > 0 && yc < original->height-2 && xc > 0 && xc < original->width-2) // all interpolation pixels inside image
|
if (yc > 0 && yc < original->height-2 && xc > 0 && xc < original->width-2) // all interpolation pixels inside image
|
||||||
@ -338,9 +352,9 @@ void ImProcFunctions::transformNonSep (Imagefloat* original, Imagefloat* transfo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Transform WITH scaling (opt.) and CA, cubic interpolation
|
||||||
#include "cubintch.cc"
|
#include "cubintch.cc"
|
||||||
void ImProcFunctions::transformSep (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH) {
|
void ImProcFunctions::transformSep (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, const LCPMapper *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;
|
||||||
|
|
||||||
@ -367,14 +381,13 @@ void ImProcFunctions::transformSep (Imagefloat* original, Imagefloat* transforme
|
|||||||
chtrans[2] = transformed->b;
|
chtrans[2] = transformed->b;
|
||||||
|
|
||||||
// auxiliary variables for distortion correction
|
// auxiliary variables for distortion correction
|
||||||
|
bool needsDist = needsDistortion(); // for performance
|
||||||
double a = params->distortion.amount;
|
double a = params->distortion.amount;
|
||||||
|
|
||||||
// auxiliary variables for rotation
|
// auxiliary variables for rotation
|
||||||
double cost = cos(params->rotate.degree * RT_PI/180.0);
|
double cost = cos(params->rotate.degree * RT_PI/180.0);
|
||||||
double sint = sin(params->rotate.degree * RT_PI/180.0);
|
double sint = sin(params->rotate.degree * RT_PI/180.0);
|
||||||
|
|
||||||
bool dovign = params->vignetting.amount != 0;
|
|
||||||
|
|
||||||
// auxiliary variables for vertical perspective correction
|
// auxiliary variables for vertical perspective correction
|
||||||
double vpdeg = params->perspective.vertical / 100.0 * 45.0;
|
double vpdeg = params->perspective.vertical / 100.0 * 45.0;
|
||||||
double vpalpha = (90.0 - vpdeg) / 180.0 * RT_PI;
|
double vpalpha = (90.0 - vpdeg) / 180.0 * RT_PI;
|
||||||
@ -395,8 +408,11 @@ void ImProcFunctions::transformSep (Imagefloat* original, Imagefloat* transforme
|
|||||||
#pragma omp parallel for if (multiThread)
|
#pragma omp parallel for if (multiThread)
|
||||||
for (int y=0; y<transformed->height; y++) {
|
for (int y=0; y<transformed->height; y++) {
|
||||||
for (int x=0; x<transformed->width; x++) {
|
for (int x=0; x<transformed->width; x++) {
|
||||||
double x_d = ascale * (x + cx - w2); // centering x coord & scale
|
double x_d=x,y_d=y;
|
||||||
double y_d = ascale * (y + cy - h2); // centering y coord & scale
|
if (pLCPMap) pLCPMap->correctDistortion(x_d,y_d); // must be first transform
|
||||||
|
|
||||||
|
x_d = ascale * (x_d + cx - w2); // centering x coord & scale
|
||||||
|
y_d = ascale * (y_d + cy - h2); // centering y coord & scale
|
||||||
double vig_x_d = ascale * (x + cx - vig_w2); // centering x coord & scale
|
double vig_x_d = ascale * (x + cx - vig_w2); // centering x coord & scale
|
||||||
double vig_y_d = ascale * (y + cy - vig_h2); // centering y coord & scale
|
double vig_y_d = ascale * (y + cy - vig_h2); // centering y coord & scale
|
||||||
|
|
||||||
@ -413,12 +429,15 @@ void ImProcFunctions::transformSep (Imagefloat* original, Imagefloat* transforme
|
|||||||
double Dyc = x_d * sint + y_d * cost;
|
double Dyc = x_d * sint + y_d * cost;
|
||||||
|
|
||||||
// distortion correction
|
// distortion correction
|
||||||
double r = sqrt(Dxc*Dxc + Dyc*Dyc) / maxRadius;
|
double s = 1;
|
||||||
double s = 1.0 - a + a * r ;
|
if (needsDist) {
|
||||||
|
double r = sqrt(Dxc*Dxc + Dyc*Dyc) / maxRadius; // sqrt is slow
|
||||||
|
s = 1.0 - a + a * r ;
|
||||||
|
}
|
||||||
|
|
||||||
double vig_Dx = vig_x_d * cost - vig_y_d * sint;
|
double vig_Dx = vig_x_d * cost - vig_y_d * sint;
|
||||||
double vig_Dy = vig_x_d * sint + vig_y_d * cost;
|
double vig_Dy = vig_x_d * sint + vig_y_d * cost;
|
||||||
double r2 = sqrt(vig_Dx*vig_Dx + vig_Dy*vig_Dy);
|
double r2 = needsVignetting() ? sqrt(vig_Dx*vig_Dx + vig_Dy*vig_Dy) : 0;
|
||||||
|
|
||||||
for (int c=0; c<3; c++) {
|
for (int c=0; c<3; c++) {
|
||||||
|
|
||||||
@ -438,7 +457,7 @@ void ImProcFunctions::transformSep (Imagefloat* original, Imagefloat* transforme
|
|||||||
|
|
||||||
// multiplier for vignetting correction
|
// multiplier for vignetting correction
|
||||||
double vignmul = 1.0;
|
double vignmul = 1.0;
|
||||||
if (dovign)
|
if (needsVignetting())
|
||||||
vignmul /= (v + mul * tanh (b*(maxRadius-s*r2) / maxRadius));
|
vignmul /= (v + mul * tanh (b*(maxRadius-s*r2) / maxRadius));
|
||||||
|
|
||||||
if (yc > 0 && yc < original->height-2 && xc > 0 && xc < original->width-2) // all interpolation pixels inside image
|
if (yc > 0 && yc < original->height-2 && xc > 0 && xc < original->width-2) // all interpolation pixels inside image
|
||||||
@ -459,8 +478,8 @@ void ImProcFunctions::transformSep (Imagefloat* original, Imagefloat* transforme
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImProcFunctions::simpltransform (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH) {
|
// Transform WITH scaling, WITHOUT CA, simple (and fast) interpolation. Used for preview
|
||||||
|
void ImProcFunctions::simpltransform (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, const LCPMapper *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;
|
||||||
|
|
||||||
@ -473,14 +492,13 @@ void ImProcFunctions::simpltransform (Imagefloat* original, Imagefloat* transfor
|
|||||||
calcVignettingParams(oW, oH, params->vignetting, vig_w2, vig_h2, maxRadius, v, b, mul);
|
calcVignettingParams(oW, oH, params->vignetting, vig_w2, vig_h2, maxRadius, v, b, mul);
|
||||||
|
|
||||||
// auxiliary variables for distortion correction
|
// auxiliary variables for distortion correction
|
||||||
|
bool needsDist = needsDistortion(); // for performance
|
||||||
double a = params->distortion.amount;
|
double a = params->distortion.amount;
|
||||||
|
|
||||||
// auxiliary variables for rotation
|
// auxiliary variables for rotation
|
||||||
double cost = cos(params->rotate.degree * RT_PI/180.0);
|
double cost = cos(params->rotate.degree * RT_PI/180.0);
|
||||||
double sint = sin(params->rotate.degree * RT_PI/180.0);
|
double sint = sin(params->rotate.degree * RT_PI/180.0);
|
||||||
|
|
||||||
bool dovign = params->vignetting.amount != 0;
|
|
||||||
|
|
||||||
// auxiliary variables for vertical perspective correction
|
// auxiliary variables for vertical perspective correction
|
||||||
double vpdeg = params->perspective.vertical / 100.0 * 45.0;
|
double vpdeg = params->perspective.vertical / 100.0 * 45.0;
|
||||||
double vpalpha = (90 - vpdeg) / 180.0 * RT_PI;
|
double vpalpha = (90 - vpdeg) / 180.0 * RT_PI;
|
||||||
@ -499,8 +517,11 @@ void ImProcFunctions::simpltransform (Imagefloat* original, Imagefloat* transfor
|
|||||||
#pragma omp parallel for if (multiThread)
|
#pragma omp parallel for if (multiThread)
|
||||||
for (int y=0; y<transformed->height; y++) {
|
for (int y=0; y<transformed->height; y++) {
|
||||||
for (int x=0; x<transformed->width; x++) {
|
for (int x=0; x<transformed->width; x++) {
|
||||||
double y_d = ascale * (y + cy - h2); // centering y coord & scale
|
double x_d=x,y_d=y;
|
||||||
double x_d = ascale * (x + cx - w2); // centering x coord & scale
|
if (pLCPMap) pLCPMap->correctDistortion(x_d,y_d); // must be first transform
|
||||||
|
|
||||||
|
y_d = ascale * (y_d + cy - h2); // centering y coord & scale
|
||||||
|
x_d = ascale * (x_d + cx - w2); // centering x coord & scale
|
||||||
double vig_x_d = ascale * (x + cx - vig_w2); // centering x coord & scale
|
double vig_x_d = ascale * (x + cx - vig_w2); // centering x coord & scale
|
||||||
double vig_y_d = ascale * (y + cy - vig_h2); // centering y coord & scale
|
double vig_y_d = ascale * (y + cy - vig_h2); // centering y coord & scale
|
||||||
|
|
||||||
@ -517,14 +538,17 @@ void ImProcFunctions::simpltransform (Imagefloat* original, Imagefloat* transfor
|
|||||||
double Dy = x_d * sint + y_d * cost;
|
double Dy = x_d * sint + y_d * cost;
|
||||||
|
|
||||||
// distortion correction
|
// distortion correction
|
||||||
double r = sqrt(Dx*Dx + Dy*Dy) / maxRadius;
|
double s = 1;
|
||||||
double s = 1.0 - a + a * r ;
|
if (needsDist) {
|
||||||
|
double r = sqrt(Dx*Dx + Dy*Dy) / maxRadius; // sqrt is slow
|
||||||
|
s = 1.0 - a + a * r ;
|
||||||
Dx *= s;
|
Dx *= s;
|
||||||
Dy *= s;
|
Dy *= s;
|
||||||
|
}
|
||||||
|
|
||||||
double vig_Dx = vig_x_d * cost - vig_y_d * sint;
|
double vig_Dx = vig_x_d * cost - vig_y_d * sint;
|
||||||
double vig_Dy = vig_x_d * sint + vig_y_d * cost;
|
double vig_Dy = vig_x_d * sint + vig_y_d * cost;
|
||||||
double r2 = sqrt(vig_Dx*vig_Dx + vig_Dy*vig_Dy);
|
double r2 = needsVignetting() ? sqrt(vig_Dx*vig_Dx + vig_Dy*vig_Dy) : 0;
|
||||||
|
|
||||||
// de-center
|
// de-center
|
||||||
Dx += w2;
|
Dx += w2;
|
||||||
@ -539,7 +563,7 @@ void ImProcFunctions::simpltransform (Imagefloat* original, Imagefloat* transfor
|
|||||||
|
|
||||||
// multiplier for vignetting correction
|
// multiplier for vignetting correction
|
||||||
double vignmul = 1.0;
|
double vignmul = 1.0;
|
||||||
if (dovign)
|
if (needsVignetting())
|
||||||
vignmul /= (v + mul * tanh (b*(maxRadius-s*r2) / maxRadius));
|
vignmul /= (v + mul * tanh (b*(maxRadius-s*r2) / maxRadius));
|
||||||
|
|
||||||
if (yc < original->height-1 && xc < original->width-1) { // all interpolation pixels inside image
|
if (yc < original->height-1 && xc < original->width-1) { // all interpolation pixels inside image
|
||||||
@ -605,8 +629,12 @@ bool ImProcFunctions::needsVignetting () {
|
|||||||
return params->vignetting.amount;
|
return params->vignetting.amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ImProcFunctions::needsLCP () {
|
||||||
|
return params->lensProf.lcpFile.length()>0;
|
||||||
|
}
|
||||||
|
|
||||||
bool ImProcFunctions::needsTransform () {
|
bool ImProcFunctions::needsTransform () {
|
||||||
return needsCA () || needsDistortion () || needsRotation () || needsPerspective () || needsVignetting ();
|
return needsCA () || needsDistortion () || needsRotation () || needsPerspective () || needsVignetting () || needsLCP();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
389
rtengine/lcp.cc
Normal file
389
rtengine/lcp.cc
Normal file
@ -0,0 +1,389 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of RawTherapee.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012 Oliver Duis <www.oliverduis.de>
|
||||||
|
*
|
||||||
|
* RawTherapee is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* RawTherapee is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#include "lcp.h"
|
||||||
|
#include "safegtk.h"
|
||||||
|
#include "iccmatrices.h"
|
||||||
|
#include "iccstore.h"
|
||||||
|
#include "rawimagesource.h"
|
||||||
|
#include "improcfun.h"
|
||||||
|
#include "rt_math.h"
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
// for GCC32
|
||||||
|
#ifndef _WIN32_IE
|
||||||
|
#define _WIN32_IE 0x0600
|
||||||
|
#endif
|
||||||
|
#include <shlobj.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using namespace rtengine;
|
||||||
|
using namespace rtexif;
|
||||||
|
|
||||||
|
|
||||||
|
LCPModelCommon::LCPModelCommon() {
|
||||||
|
focLenX=focLenY=-1; imgXCenter=imgYCenter=0.5;
|
||||||
|
for (int i=0;i<5;i++) param[i]=0;
|
||||||
|
scaleFac=1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LCPModelCommon::empty() const {
|
||||||
|
return focLenX<0 && focLenY<0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LCPModelCommon::print() const {
|
||||||
|
printf("focLen %g/%g; imgCenter %g/%g; scale %g\n",focLenX,focLenY,imgXCenter,imgYCenter,scaleFac);
|
||||||
|
printf("param: %g/%g/%g/%g/%g\n",param[0],param[1],param[2],param[3],param[4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
LCPPersModel::LCPPersModel() {
|
||||||
|
focLen=focDist=aperture=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LCPPersModel::print() const {
|
||||||
|
printf("--- PersModel focLen %g; focDist %g; aperture %g\n", focLen, focDist, aperture);
|
||||||
|
printf("Base:\n"); base.print();
|
||||||
|
if (!chromRG.empty()) { printf("ChromRG:\n"); chromRG.print(); }
|
||||||
|
if (!chromG.empty()) { printf("ChromG:\n"); chromG.print(); }
|
||||||
|
if (!chromBG.empty()) { printf("ChromBG:\n"); chromBG.print(); }
|
||||||
|
if (!vignette.empty()) { printf("Vignette:\n"); vignette.print(); }
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// if !vignette then geometric
|
||||||
|
LCPMapper::LCPMapper(LCPProfile* pProf, float focalLength, bool vignette, int fullWidth, int fullHeight, const CoarseTransformParams& coarse, int rawRotationDeg)
|
||||||
|
{
|
||||||
|
if (pProf==NULL) return;
|
||||||
|
|
||||||
|
pProf-> calcBasePerspectiveParams(focalLength, vignette, mc);
|
||||||
|
|
||||||
|
// determine in what the image with the RAW landscape in comparison (calibration target)
|
||||||
|
int rot = (coarse.rotate+rawRotationDeg) % 360;
|
||||||
|
|
||||||
|
swapXY = (rot==90 || rot==270);
|
||||||
|
mirrorX = (rot==90 || rot==180);
|
||||||
|
mirrorY = (rot==180 || rot==270);
|
||||||
|
|
||||||
|
// Mention that the Adobe technical paper has a bug here, the DMAX is handled differently for focLen and imgCenter
|
||||||
|
int Dmax=fullWidth; if (fullHeight>fullWidth) Dmax=fullHeight;
|
||||||
|
|
||||||
|
if (swapXY) {
|
||||||
|
x0 = (mirrorX ? 1-mc.imgYCenter : mc.imgYCenter) * fullWidth;
|
||||||
|
y0 = (mirrorY ? 1-mc.imgXCenter : mc.imgXCenter) * fullHeight;
|
||||||
|
fx = mc.focLenY * Dmax;
|
||||||
|
fy = mc.focLenX * Dmax;
|
||||||
|
} else {
|
||||||
|
x0 = (mirrorX ? 1-mc.imgXCenter : mc.imgXCenter) * fullWidth;
|
||||||
|
y0 = (mirrorY ? 1-mc.imgYCenter : mc.imgYCenter) * fullHeight;
|
||||||
|
fx = mc.focLenX * Dmax;
|
||||||
|
fy = mc.focLenY * Dmax;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void LCPMapper::correctDistortion(double& x, double& y) const {
|
||||||
|
double xd=(x-x0)/fx, yd=(y-y0)/fy;
|
||||||
|
|
||||||
|
double rsqr = xd*xd+yd*yd;
|
||||||
|
double rsqrrsqr = rsqr*rsqr; // speed
|
||||||
|
double commonFac = (mc.param[2]*rsqrrsqr*rsqr + mc.param[1]*rsqrrsqr + mc.param[0]*rsqr + 1.)
|
||||||
|
+ 2 * (mc.param[3] * yd + mc.param[4] * xd);
|
||||||
|
|
||||||
|
double xnew = xd * commonFac + mc.param[4] * rsqr;
|
||||||
|
double ynew = yd * commonFac + mc.param[3] * rsqr;
|
||||||
|
|
||||||
|
x = xnew * fx + x0;
|
||||||
|
y = ynew * fy + y0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float LCPMapper::correctVignette(double x, double y) const {
|
||||||
|
double xd=(x-x0)/fx, yd=(y-y0)/fy;
|
||||||
|
|
||||||
|
double rsqr = xd*xd+yd*yd;
|
||||||
|
double rsqrrsqr = rsqr*rsqr; // speed
|
||||||
|
double param0Sqr = mc.param[0]*mc.param[0];
|
||||||
|
|
||||||
|
return 1. - mc.param[0]*rsqr + (param0Sqr - mc.param[1]) *rsqrrsqr
|
||||||
|
- (param0Sqr*mc.param[0] - 2*mc.param[0]*mc.param[1] + mc.param[2]) *rsqrrsqr*rsqr
|
||||||
|
+ (param0Sqr*param0Sqr + mc.param[1]*mc.param[1]
|
||||||
|
+ 2*mc.param[0]*mc.param[2] - 3*mc.param[0]*mc.param[0]*mc.param[1]) *rsqrrsqr*rsqrrsqr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LCPProfile::LCPProfile(Glib::ustring fname) {
|
||||||
|
const int BufferSize=8192;
|
||||||
|
char buf[BufferSize];
|
||||||
|
|
||||||
|
XML_Parser parser = XML_ParserCreate(NULL);
|
||||||
|
if (!parser) throw "Couldn't allocate memory for XML parser";
|
||||||
|
|
||||||
|
XML_SetElementHandler(parser, XmlStartHandler, XmlEndHandler);
|
||||||
|
XML_SetCharacterDataHandler(parser, XmlTextHandler);
|
||||||
|
XML_SetUserData(parser, (void *)this);
|
||||||
|
|
||||||
|
|
||||||
|
isFisheye=inCamProfiles=firstLIDone=inPerspect=false;
|
||||||
|
|
||||||
|
FILE *pFile = safe_g_fopen(fname, "rb");
|
||||||
|
|
||||||
|
bool done;
|
||||||
|
do {
|
||||||
|
int bytesRead = (int)fread(buf, 1, BufferSize, pFile);
|
||||||
|
done=feof(pFile);
|
||||||
|
if (XML_Parse(parser, buf, bytesRead, done) == XML_STATUS_ERROR)
|
||||||
|
throw "Invalid XML in LCP file";
|
||||||
|
} while (!done);
|
||||||
|
|
||||||
|
XML_ParserFree(parser);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void LCPProfile::calcBasePerspectiveParams(float focalLength, bool vignette, LCPModelCommon& corr) {
|
||||||
|
// find the frames with the least distance, focal length wise
|
||||||
|
LCPPersModel *pLow=NULL, *pHigh=NULL;
|
||||||
|
|
||||||
|
std::list<LCPPersModel*>::const_iterator it;
|
||||||
|
for (it=persModels.begin(); it!=persModels.end(); ++it) {
|
||||||
|
float f=(*it)->focLen;
|
||||||
|
|
||||||
|
if ((!vignette && !(*it)->base.empty()) || (vignette && !(*it)->vignette.empty())) {
|
||||||
|
if (f <= focalLength && (pLow ==NULL || f > pLow->focLen)) pLow= (*it);
|
||||||
|
if (f >= focalLength && (pHigh==NULL || f < pHigh->focLen)) pHigh=(*it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pLow) pLow=pHigh; if (!pHigh) pHigh=pLow;
|
||||||
|
|
||||||
|
// average out the factors, linear interpolation
|
||||||
|
float facLow = 0, facHigh=0;
|
||||||
|
if (pLow && pHigh && pLow->focLen < pHigh->focLen) {
|
||||||
|
facLow = (pHigh->focLen-focalLength) / (pHigh->focLen-pLow->focLen);
|
||||||
|
facHigh = (focalLength-pLow->focLen) / (pHigh->focLen-pLow->focLen);
|
||||||
|
} else {
|
||||||
|
facLow=pHigh?0:1; facHigh=pHigh?1:0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LCPModelCommon& mLow =(vignette?pLow->vignette :pLow->base);
|
||||||
|
LCPModelCommon& mHigh=(vignette?pHigh->vignette:pHigh->base);
|
||||||
|
|
||||||
|
corr.focLenX = facLow * mLow.focLenX + facHigh * mHigh.focLenX;
|
||||||
|
corr.focLenY = facLow * mLow.focLenY + facHigh * mHigh.focLenY;
|
||||||
|
corr.imgXCenter = facLow * mLow.imgXCenter + facHigh * mHigh.imgXCenter;
|
||||||
|
corr.imgYCenter = facLow * mLow.imgYCenter + facHigh * mHigh.imgYCenter;
|
||||||
|
corr.scaleFac = facLow * mLow.scaleFac + facHigh * mHigh.scaleFac;
|
||||||
|
|
||||||
|
for (int i=0;i<5;i++) corr.param[i]= facLow * mLow.param[i] + facHigh * mHigh.param[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
void LCPProfile::print() const {
|
||||||
|
printf("=== Profile %s\n", profileName.c_str());
|
||||||
|
printf("RAW: %i; Fisheye: %i\n",isRaw,isFisheye);
|
||||||
|
std::list<LCPPersModel*>::const_iterator it;
|
||||||
|
for (it=persModels.begin(); it!=persModels.end(); ++it) (*it)->print();
|
||||||
|
}
|
||||||
|
|
||||||
|
void XMLCALL LCPProfile::XmlStartHandler(void *pLCPProfile, const char *el, const char **attr) {
|
||||||
|
LCPProfile *pProf=static_cast<LCPProfile*>(pLCPProfile);
|
||||||
|
|
||||||
|
// clean up tagname
|
||||||
|
char* src=strrchr(el,':');
|
||||||
|
if (src==NULL) src=const_cast<char*>(el); else src++;
|
||||||
|
|
||||||
|
strcpy(pProf->lastTag,src);
|
||||||
|
|
||||||
|
if (!strcmp("CameraProfiles",src)) pProf->inCamProfiles=true;
|
||||||
|
if (!pProf->inCamProfiles) return;
|
||||||
|
|
||||||
|
if (!strcmp("li",src)) {
|
||||||
|
pProf->pCurPersModel=new LCPPersModel();
|
||||||
|
pProf->pCurCommon=&pProf->pCurPersModel->base; // iterated to next tags within persModel
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp("PerspectiveModel",src)) {
|
||||||
|
pProf->firstLIDone=true; pProf->inPerspect=true;
|
||||||
|
return;
|
||||||
|
} else if (!strcmp("FisheyeModel",src)) {
|
||||||
|
pProf->firstLIDone=true; pProf->inPerspect=true;
|
||||||
|
pProf->isFisheye=true; // just misses third param, and different path, rest is the same
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move pointer to general section
|
||||||
|
if (pProf->inPerspect) {
|
||||||
|
if (!strcmp("ChromaticRedGreenModel",src))
|
||||||
|
pProf->pCurCommon=&pProf->pCurPersModel->chromRG;
|
||||||
|
else if (!strcmp("ChromaticGreenModel",src))
|
||||||
|
pProf->pCurCommon=&pProf->pCurPersModel->chromG;
|
||||||
|
else if (!strcmp("ChromaticBlueGreenModel",src))
|
||||||
|
pProf->pCurCommon=&pProf->pCurPersModel->chromBG;
|
||||||
|
else if (!strcmp("VignetteModel",src))
|
||||||
|
pProf->pCurCommon=&pProf->pCurPersModel->vignette;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void XMLCALL LCPProfile::XmlTextHandler(void *pLCPProfile, const XML_Char *s, int len) {
|
||||||
|
LCPProfile *pProf=static_cast<LCPProfile*>(pLCPProfile);
|
||||||
|
|
||||||
|
if (!pProf->inCamProfiles) return;
|
||||||
|
|
||||||
|
// Check if it contains non-whitespaces (there are several calls to this for one tag unfortunately)
|
||||||
|
bool onlyWhiteSpace=true;
|
||||||
|
int i=0;
|
||||||
|
while (i<len && onlyWhiteSpace) { onlyWhiteSpace=isspace(s[i]); i++; }
|
||||||
|
if (onlyWhiteSpace) return;
|
||||||
|
|
||||||
|
// convert to null terminated
|
||||||
|
char raw[len+1]; memcpy(raw,s,len); raw[len]=0;
|
||||||
|
char* tag=pProf->lastTag;
|
||||||
|
|
||||||
|
//printf("%s : %s\n",tag,raw);
|
||||||
|
|
||||||
|
// Common data section
|
||||||
|
if (!pProf->firstLIDone) {
|
||||||
|
// Generic tags are the same for all
|
||||||
|
if (!strcmp("ProfileName",tag))
|
||||||
|
pProf->profileName=Glib::ustring(raw);
|
||||||
|
else if (!strcmp("Model",tag))
|
||||||
|
pProf->camera=Glib::ustring(raw);
|
||||||
|
else if (!strcmp("Lens",tag))
|
||||||
|
pProf->lens=Glib::ustring(raw);
|
||||||
|
else if (!strcmp("CameraPrettyName",tag))
|
||||||
|
pProf->cameraPrettyName=Glib::ustring(raw);
|
||||||
|
else if (!strcmp("LensPrettyName",tag))
|
||||||
|
pProf->lensPrettyName=Glib::ustring(raw);
|
||||||
|
else if (!strcmp("CameraRawProfile",tag))
|
||||||
|
pProf->isRaw=!strcmp("True",raw);
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Now all floating points. Must replace local dot characters
|
||||||
|
struct lconv * lc=localeconv();
|
||||||
|
|
||||||
|
char* p=raw;
|
||||||
|
while (*p) {
|
||||||
|
if (*p=='.') *p=lc->decimal_point[0];
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perspective model base data
|
||||||
|
if (!strcmp("FocalLength",tag))
|
||||||
|
pProf->pCurPersModel->focLen=atof(raw);
|
||||||
|
else if (!strcmp("FocusDistance",tag))
|
||||||
|
pProf->pCurPersModel->focDist=atof(raw);
|
||||||
|
else if (!strcmp("ApertureValue",tag))
|
||||||
|
pProf->pCurPersModel->aperture=atof(raw);
|
||||||
|
|
||||||
|
// Section depended
|
||||||
|
if (!strcmp("FocalLengthX",tag))
|
||||||
|
pProf->pCurCommon->focLenX=atof(raw);
|
||||||
|
else if (!strcmp("FocalLengthY",tag))
|
||||||
|
pProf->pCurCommon->focLenY=atof(raw);
|
||||||
|
else if (!strcmp("ImageXCenter",tag))
|
||||||
|
pProf->pCurCommon->imgXCenter=atof(raw);
|
||||||
|
else if (!strcmp("ImageYCenter",tag))
|
||||||
|
pProf->pCurCommon->imgYCenter=atof(raw);
|
||||||
|
else if (!strcmp("ScaleFactor",tag))
|
||||||
|
pProf->pCurCommon->scaleFac=atof(raw);
|
||||||
|
else if (!strcmp("RadialDistortParam1",tag) || !strcmp("VignetteModelParam1",tag))
|
||||||
|
pProf->pCurCommon->param[0]=atof(raw);
|
||||||
|
else if (!strcmp("RadialDistortParam2",tag) || !strcmp("VignetteModelParam2",tag))
|
||||||
|
pProf->pCurCommon->param[1]=atof(raw);
|
||||||
|
else if (!strcmp("RadialDistortParam3",tag) || !strcmp("VignetteModelParam3",tag))
|
||||||
|
pProf->pCurCommon->param[2]=atof(raw);
|
||||||
|
else if (!strcmp("TangentialDistortParam1",tag))
|
||||||
|
pProf->pCurCommon->param[3]=atof(raw);
|
||||||
|
else if (!strcmp("TangentialDistortParam2",tag))
|
||||||
|
pProf->pCurCommon->param[4]=atof(raw);
|
||||||
|
}
|
||||||
|
|
||||||
|
void XMLCALL LCPProfile::XmlEndHandler(void *pLCPProfile, const char *el) {
|
||||||
|
LCPProfile *pProf=static_cast<LCPProfile*>(pLCPProfile);
|
||||||
|
|
||||||
|
if (strstr(el,":CameraProfiles")) pProf->inCamProfiles=false;
|
||||||
|
|
||||||
|
if (!pProf->inCamProfiles) return;
|
||||||
|
|
||||||
|
if (strstr(el,":PerspectiveModel") || strstr(el,":FisheyeModel"))
|
||||||
|
pProf->inPerspect=false;
|
||||||
|
else if (strstr(el, ":li")) {
|
||||||
|
pProf->persModels.push_back(pProf->pCurPersModel);
|
||||||
|
pProf->pCurPersModel=NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates as singleton
|
||||||
|
LCPStore* LCPStore::getInstance()
|
||||||
|
{
|
||||||
|
static LCPStore* instance_ = 0;
|
||||||
|
if ( instance_ == 0 )
|
||||||
|
{
|
||||||
|
static Glib::Mutex smutex_;
|
||||||
|
Glib::Mutex::Lock lock(smutex_);
|
||||||
|
if ( instance_ == 0 )
|
||||||
|
{
|
||||||
|
instance_ = new LCPStore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return instance_;
|
||||||
|
}
|
||||||
|
|
||||||
|
LCPProfile* LCPStore::getProfile (Glib::ustring filename) {
|
||||||
|
if (filename.length()==0) return NULL;
|
||||||
|
|
||||||
|
Glib::Mutex::Lock lock(mtx);
|
||||||
|
|
||||||
|
std::map<Glib::ustring, LCPProfile*>::iterator r = profileCache.find (filename);
|
||||||
|
if (r!=profileCache.end()) return r->second;
|
||||||
|
|
||||||
|
// Add profile
|
||||||
|
profileCache[filename]=new LCPProfile(filename);
|
||||||
|
//profileCache[filename]->print();
|
||||||
|
return profileCache[filename];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool LCPStore::isValidLCPFileName(Glib::ustring filename) const {
|
||||||
|
if (!safe_file_test (filename, Glib::FILE_TEST_EXISTS) || safe_file_test (filename, Glib::FILE_TEST_IS_DIR)) return false;
|
||||||
|
size_t pos=filename.find_last_of ('.');
|
||||||
|
return pos>0 && !filename.casefold().compare (pos, 4, ".lcp");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Glib::ustring LCPStore::getDefaultCommonDirectory() const {
|
||||||
|
Glib::ustring dir;
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
WCHAR pathW[MAX_PATH]={0}; char pathA[MAX_PATH];
|
||||||
|
|
||||||
|
if (SHGetSpecialFolderPathW(NULL,pathW,CSIDL_COMMON_APPDATA,false)) {
|
||||||
|
char pathA[MAX_PATH];
|
||||||
|
WideCharToMultiByte(CP_UTF8,0,pathW,-1,pathA,MAX_PATH,0,0);
|
||||||
|
Glib::ustring fullDir=Glib::ustring(pathA)+Glib::ustring("\\Adobe\\CameraRaw\\LensProfiles\\1.0");
|
||||||
|
if (safe_file_test(fullDir, Glib::FILE_TEST_IS_DIR)) dir=fullDir;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
printf("Sorry, default LCP directory are currently only configured on Windows\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return dir;
|
||||||
|
}
|
116
rtengine/lcp.h
Normal file
116
rtengine/lcp.h
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of RawTherapee.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012 Oliver Duis <www.oliverduis.de>
|
||||||
|
*
|
||||||
|
* RawTherapee is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* RawTherapee is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with RawTherapee. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LCP_
|
||||||
|
#define _LCP_
|
||||||
|
|
||||||
|
#include "imagefloat.h"
|
||||||
|
#include <glibmm.h>
|
||||||
|
#include <map>
|
||||||
|
#include <list>
|
||||||
|
#include <string>
|
||||||
|
#include <expat.h>
|
||||||
|
|
||||||
|
namespace rtengine {
|
||||||
|
// Perspective model common data, also used for Vignette and Fisheye
|
||||||
|
class LCPModelCommon {
|
||||||
|
public:
|
||||||
|
float focLenX, focLenY, imgXCenter, imgYCenter;
|
||||||
|
float param[5]; // k1..k5
|
||||||
|
float scaleFac;
|
||||||
|
|
||||||
|
LCPModelCommon();
|
||||||
|
bool empty() const; // is it empty?
|
||||||
|
void print() const; // printf all values
|
||||||
|
};
|
||||||
|
|
||||||
|
class LCPPersModel {
|
||||||
|
public:
|
||||||
|
float focLen, focDist, aperture; // this is what it refers to
|
||||||
|
|
||||||
|
LCPModelCommon base; // base perspective correction
|
||||||
|
LCPModelCommon chromRG, chromG, chromBG; // red/green, green, blue/green (may be empty)
|
||||||
|
LCPModelCommon vignette; // vignette (may be empty)
|
||||||
|
|
||||||
|
LCPPersModel();
|
||||||
|
void print() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class LCPProfile {
|
||||||
|
// Temporary data for parsing
|
||||||
|
bool inCamProfiles,firstLIDone,inPerspect;
|
||||||
|
char lastTag[256];
|
||||||
|
LCPPersModel* pCurPersModel;
|
||||||
|
LCPModelCommon* pCurCommon;
|
||||||
|
|
||||||
|
static void XMLCALL XmlStartHandler(void *pLCPProfile, const char *el, const char **attr);
|
||||||
|
static void XMLCALL XmlTextHandler (void *pLCPProfile, const XML_Char *s, int len);
|
||||||
|
static void XMLCALL XmlEndHandler (void *pLCPProfile, const char *el);
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Common data
|
||||||
|
Glib::ustring profileName, lensPrettyName, cameraPrettyName, lens, camera; // lens/camera(=model) can be auto-matched with DNG
|
||||||
|
bool isRaw,isFisheye;
|
||||||
|
|
||||||
|
// The correction frames
|
||||||
|
std::list<LCPPersModel*> persModels;
|
||||||
|
|
||||||
|
LCPProfile(Glib::ustring fname);
|
||||||
|
|
||||||
|
void calcBasePerspectiveParams(float focalLength, bool vignette, LCPModelCommon& corr); // Interpolates between the persModels frames
|
||||||
|
|
||||||
|
void print() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LCPStore {
|
||||||
|
Glib::Mutex mtx;
|
||||||
|
|
||||||
|
|
||||||
|
// Maps file name to profile as cache
|
||||||
|
std::map<Glib::ustring, LCPProfile*> profileCache;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Glib::ustring getDefaultCommonDirectory() const;
|
||||||
|
bool isValidLCPFileName(Glib::ustring filename) const;
|
||||||
|
LCPProfile* getProfile(Glib::ustring filename);
|
||||||
|
|
||||||
|
static LCPStore* getInstance();
|
||||||
|
};
|
||||||
|
|
||||||
|
#define lcpStore LCPStore::getInstance()
|
||||||
|
|
||||||
|
|
||||||
|
// Once precalculated class to correct a point
|
||||||
|
class LCPMapper {
|
||||||
|
double x0,y0,fx,fy;
|
||||||
|
LCPModelCommon mc;
|
||||||
|
bool swapXY;
|
||||||
|
bool mirrorX, mirrorY;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// precalculates the mapper.
|
||||||
|
LCPMapper(LCPProfile* pProf, float focalLength, bool vignette, int fullWidth, int fullHeight,
|
||||||
|
const CoarseTransformParams& coarse, int rawRotationDeg);
|
||||||
|
|
||||||
|
void correctDistortion(double& x, double& y) const; // MUST be the first stage
|
||||||
|
float correctVignette (double x, double y) const; // MUST be in RAW
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#endif
|
@ -106,7 +106,7 @@ enum ProcEvent {
|
|||||||
EvProfileChangeNotification=81,
|
EvProfileChangeNotification=81,
|
||||||
EvSHHighQuality=82,
|
EvSHHighQuality=82,
|
||||||
EvPerspCorr=83,
|
EvPerspCorr=83,
|
||||||
EvEqualizer=84, // obsolete
|
EvLCPFile=84,
|
||||||
EvEqlEnabled=85,// obsolete
|
EvEqlEnabled=85,// obsolete
|
||||||
EvIDNEnabled=86,
|
EvIDNEnabled=86,
|
||||||
EvIDNThresh=87,
|
EvIDNThresh=87,
|
||||||
|
@ -259,7 +259,6 @@ void ProcParams::setDefaults () {
|
|||||||
rotate.degree = 0;
|
rotate.degree = 0;
|
||||||
|
|
||||||
distortion.amount = 0;
|
distortion.amount = 0;
|
||||||
distortion.uselensfun = false;
|
|
||||||
|
|
||||||
perspective.horizontal = 0;
|
perspective.horizontal = 0;
|
||||||
perspective.vertical = 0;
|
perspective.vertical = 0;
|
||||||
@ -540,7 +539,9 @@ int ProcParams::save (Glib::ustring fname, Glib::ustring fname2, ParamsEdited* p
|
|||||||
|
|
||||||
// save distortion
|
// save distortion
|
||||||
if (!pedited || pedited->distortion.amount) keyFile.set_double ("Distortion", "Amount", distortion.amount);
|
if (!pedited || pedited->distortion.amount) keyFile.set_double ("Distortion", "Amount", distortion.amount);
|
||||||
if (!pedited || pedited->distortion.uselensfun) keyFile.set_boolean ("Distortion", "UseLensFun", distortion.uselensfun);
|
|
||||||
|
// lens profile
|
||||||
|
if (!pedited || pedited->lensProf.lcpFile) keyFile.set_string ("LensProfile", "LCPFile", lensProf.lcpFile);
|
||||||
|
|
||||||
// save perspective correction
|
// save perspective correction
|
||||||
if (!pedited || pedited->perspective.horizontal) keyFile.set_integer ("Perspective", "Horizontal", perspective.horizontal);
|
if (!pedited || pedited->perspective.horizontal) keyFile.set_integer ("Perspective", "Horizontal", perspective.horizontal);
|
||||||
@ -939,7 +940,11 @@ if (keyFile.has_group ("Common Properties for Transformations")) {
|
|||||||
// load distortion
|
// load distortion
|
||||||
if (keyFile.has_group ("Distortion")) {
|
if (keyFile.has_group ("Distortion")) {
|
||||||
if (keyFile.has_key ("Distortion", "Amount")) { distortion.amount = keyFile.get_double ("Distortion", "Amount"); if (pedited) pedited->distortion.amount = true; }
|
if (keyFile.has_key ("Distortion", "Amount")) { distortion.amount = keyFile.get_double ("Distortion", "Amount"); if (pedited) pedited->distortion.amount = true; }
|
||||||
if (keyFile.has_key ("Distortion", "UseLensFun")) { distortion.uselensfun = keyFile.get_boolean ("Distortion", "UseLensFun"); if (pedited) pedited->distortion.uselensfun = true; }
|
}
|
||||||
|
|
||||||
|
// lens profile
|
||||||
|
if (keyFile.has_group ("LensProfile")) {
|
||||||
|
if (keyFile.has_key ("LensProfile", "LCPFile")) { lensProf.lcpFile = keyFile.get_string ("LensProfile", "LCPFile"); if (pedited) pedited->lensProf.lcpFile = true; }
|
||||||
}
|
}
|
||||||
|
|
||||||
// load perspective correction
|
// load perspective correction
|
||||||
@ -1234,8 +1239,8 @@ bool ProcParams::operator== (const ProcParams& other) {
|
|||||||
&& coarse.vflip == other.coarse.vflip
|
&& coarse.vflip == other.coarse.vflip
|
||||||
&& rotate.degree == other.rotate.degree
|
&& rotate.degree == other.rotate.degree
|
||||||
&& commonTrans.autofill == other.commonTrans.autofill
|
&& commonTrans.autofill == other.commonTrans.autofill
|
||||||
&& distortion.uselensfun == other.distortion.uselensfun
|
|
||||||
&& distortion.amount == other.distortion.amount
|
&& distortion.amount == other.distortion.amount
|
||||||
|
&& lensProf.lcpFile == other.lensProf.lcpFile
|
||||||
&& perspective.horizontal == other.perspective.horizontal
|
&& perspective.horizontal == other.perspective.horizontal
|
||||||
&& perspective.vertical == other.perspective.vertical
|
&& perspective.vertical == other.perspective.vertical
|
||||||
&& cacorrection.red == other.cacorrection.red
|
&& cacorrection.red == other.cacorrection.red
|
||||||
|
@ -326,10 +326,16 @@ class RotateParams {
|
|||||||
class DistortionParams {
|
class DistortionParams {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool uselensfun;
|
|
||||||
double amount;
|
double amount;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Lens profile correction parameters
|
||||||
|
class LensProfParams {
|
||||||
|
|
||||||
|
public:
|
||||||
|
Glib::ustring lcpFile;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parameters of the perspective correction
|
* Parameters of the perspective correction
|
||||||
*/
|
*/
|
||||||
@ -527,6 +533,7 @@ class ProcParams {
|
|||||||
CommonTransformParams commonTrans; ///< Common transformation parameters (autofill)
|
CommonTransformParams commonTrans; ///< Common transformation parameters (autofill)
|
||||||
RotateParams rotate; ///< Rotation parameters
|
RotateParams rotate; ///< Rotation parameters
|
||||||
DistortionParams distortion; ///< Lens distortion correction parameters
|
DistortionParams distortion; ///< Lens distortion correction parameters
|
||||||
|
LensProfParams lensProf; ///< Lens correction profile parameters
|
||||||
PerspectiveParams perspective; ///< Perspective correction parameters
|
PerspectiveParams perspective; ///< Perspective correction parameters
|
||||||
CACorrParams cacorrection; ///< Lens c/a correction parameters
|
CACorrParams cacorrection; ///< Lens c/a correction parameters
|
||||||
VignettingParams vignetting; ///< Lens vignetting correction parameters
|
VignettingParams vignetting; ///< Lens vignetting correction parameters
|
||||||
|
@ -953,7 +953,7 @@ int RawImageSource::load (Glib::ustring fname, bool batch) {
|
|||||||
|
|
||||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
void RawImageSource::preprocess (const RAWParams &raw)
|
void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &lensProf, const CoarseTransformParams& coarse)
|
||||||
{
|
{
|
||||||
MyTime t1,t2;
|
MyTime t1,t2;
|
||||||
t1.set();
|
t1.set();
|
||||||
@ -979,7 +979,9 @@ void RawImageSource::preprocess (const RAWParams &raw)
|
|||||||
} else {
|
} else {
|
||||||
rif = ffm.searchFlatField( idata->getMake(), idata->getModel(),idata->getLens(),idata->getFocalLen(), idata->getFNumber(), idata->getDateTimeAsTS());
|
rif = ffm.searchFlatField( idata->getMake(), idata->getModel(),idata->getLens(),idata->getFocalLen(), idata->getFNumber(), idata->getDateTimeAsTS());
|
||||||
}
|
}
|
||||||
if( rif && settings->verbose) {
|
|
||||||
|
bool hasFlatField = (rif!=NULL);
|
||||||
|
if( hasFlatField && settings->verbose) {
|
||||||
printf( "Flat Field Correction:%s\n",rif->get_filename().c_str());
|
printf( "Flat Field Correction:%s\n",rif->get_filename().c_str());
|
||||||
}
|
}
|
||||||
copyOriginalPixels(raw, ri, rid, rif);
|
copyOriginalPixels(raw, ri, rid, rif);
|
||||||
@ -1012,6 +1014,22 @@ void RawImageSource::preprocess (const RAWParams &raw)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Correct vignetting of lens profile
|
||||||
|
if (!hasFlatField) {
|
||||||
|
LCPProfile *pLCPProf=lcpStore->getProfile(lensProf.lcpFile);
|
||||||
|
|
||||||
|
if (pLCPProf) {
|
||||||
|
LCPMapper *pLCPMap=new LCPMapper(pLCPProf, idata->getFocalLen(), true, W, H, coarse, ri->get_rotateDegree());
|
||||||
|
|
||||||
|
#pragma omp parallel
|
||||||
|
for (int y=0; y<H; y++) {
|
||||||
|
for (int x=0; x<W; x++) {
|
||||||
|
rawData[y][x]*=pLCPMap->correctVignette(x,y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
scaleColors( 0,0, W, H, raw);//+ + raw parameters for black level(raw.blackxx)
|
scaleColors( 0,0, W, H, raw);//+ + raw parameters for black level(raw.blackxx)
|
||||||
|
|
||||||
defGain = 0.0;//log(initialGain) / log(2.0);
|
defGain = 0.0;//log(initialGain) / log(2.0);
|
||||||
|
@ -135,7 +135,7 @@ class RawImageSource : public ImageSource {
|
|||||||
~RawImageSource ();
|
~RawImageSource ();
|
||||||
|
|
||||||
int load (Glib::ustring fname, bool batch = false);
|
int load (Glib::ustring fname, bool batch = false);
|
||||||
void preprocess (const RAWParams &raw);
|
void preprocess (const RAWParams &raw, const LensProfParams &lensProf, const CoarseTransformParams& coarse);
|
||||||
void demosaic (const RAWParams &raw);
|
void demosaic (const RAWParams &raw);
|
||||||
void flushRawData ();
|
void flushRawData ();
|
||||||
void flushRGB ();
|
void flushRGB ();
|
||||||
@ -160,6 +160,7 @@ class RawImageSource : public ImageSource {
|
|||||||
|
|
||||||
void getFullSize (int& w, int& h, int tr = TR_NONE);
|
void getFullSize (int& w, int& h, int tr = TR_NONE);
|
||||||
void getSize (int tran, PreviewProps pp, int& w, int& h);
|
void getSize (int tran, PreviewProps pp, int& w, int& h);
|
||||||
|
int getRotateDegree() const { return ri->get_rotateDegree(); }
|
||||||
|
|
||||||
ImageData* getImageData () { return idata; }
|
ImageData* getImageData () { return idata; }
|
||||||
void setProgressListener (ProgressListener* pl) { plistener = pl; }
|
void setProgressListener (ProgressListener* pl) { plistener = pl; }
|
||||||
|
@ -104,7 +104,7 @@ RESIZE, // EvResizeEnabled
|
|||||||
ALL, // EvProfileChangeNotification
|
ALL, // EvProfileChangeNotification
|
||||||
RETINEX, // EvShrHighQuality
|
RETINEX, // EvShrHighQuality
|
||||||
TRANSFORM, // EvPerspCorr
|
TRANSFORM, // EvPerspCorr
|
||||||
0, // EvEqualizer: obsolete
|
DARKFRAME, // EvLCPFile
|
||||||
0, // EvEqlEnabled:obsolete
|
0, // EvEqlEnabled:obsolete
|
||||||
IMPULSEDENOISE, // EvIDNEnabled,
|
IMPULSEDENOISE, // EvIDNEnabled,
|
||||||
IMPULSEDENOISE, // EvIDNThresh,
|
IMPULSEDENOISE, // EvIDNThresh,
|
||||||
|
@ -576,7 +576,7 @@ IImage8* Thumbnail::quickProcessImage (const procparams::ProcParams& params, int
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Full thumbnail processing, second stage if complete profile exists
|
// Full thumbnail processing, second stage if complete profile exists
|
||||||
IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rheight, TypeInterpolation interp, std::string camName, double& myscale) {
|
IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rheight, TypeInterpolation interp, std::string camName, double focalLen, double& myscale) {
|
||||||
|
|
||||||
// compute WB multipliers
|
// compute WB multipliers
|
||||||
ColorTemp currWB = ColorTemp (params.wb.temperature, params.wb.green, params.wb.method);
|
ColorTemp currWB = ColorTemp (params.wb.temperature, params.wb.green, params.wb.method);
|
||||||
@ -698,7 +698,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei
|
|||||||
// perform transform
|
// perform transform
|
||||||
if (ipf.needsTransform()) {
|
if (ipf.needsTransform()) {
|
||||||
Imagefloat* trImg = new Imagefloat (fw, fh);
|
Imagefloat* trImg = new Imagefloat (fw, fh);
|
||||||
ipf.transform (baseImg, trImg, 0, 0, 0, 0, fw, fh);
|
ipf.transform (baseImg, trImg, 0, 0, 0, 0, fw, fh, focalLen, 0); // Raw rotate degree not detectable here
|
||||||
delete baseImg;
|
delete baseImg;
|
||||||
baseImg = trImg;
|
baseImg = trImg;
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ namespace rtengine {
|
|||||||
static void cleanupGamma ();
|
static void cleanupGamma ();
|
||||||
void init ();
|
void init ();
|
||||||
|
|
||||||
IImage8* processImage (const procparams::ProcParams& pparams, int rheight, TypeInterpolation interp, std::string camName, double& scale);
|
IImage8* processImage (const procparams::ProcParams& pparams, int rheight, TypeInterpolation interp, std::string camName, double focalLen, double& scale);
|
||||||
IImage8* quickProcessImage (const procparams::ProcParams& pparams, int rheight, TypeInterpolation interp, double& scale);
|
IImage8* quickProcessImage (const procparams::ProcParams& pparams, int rheight, TypeInterpolation interp, double& scale);
|
||||||
int getImageWidth (const procparams::ProcParams& pparams, int rheight, float &ratio);
|
int getImageWidth (const procparams::ProcParams& pparams, int rheight, float &ratio);
|
||||||
void getDimensions (int& w, int& h, double& scaleFac);
|
void getDimensions (int& w, int& h, double& scaleFac);
|
||||||
|
@ -91,7 +91,7 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
|
|||||||
ImProcFunctions ipf (¶ms, true);
|
ImProcFunctions ipf (¶ms, true);
|
||||||
|
|
||||||
PreviewProps pp (0, 0, fw, fh, 1);
|
PreviewProps pp (0, 0, fw, fh, 1);
|
||||||
imgsrc->preprocess( params.raw);
|
imgsrc->preprocess( params.raw, params.lensProf, params.coarse);
|
||||||
if (pl) pl->setProgress (0.20);
|
if (pl) pl->setProgress (0.20);
|
||||||
imgsrc->demosaic( params.raw);
|
imgsrc->demosaic( params.raw);
|
||||||
if (pl) pl->setProgress (0.30);
|
if (pl) pl->setProgress (0.30);
|
||||||
@ -115,7 +115,7 @@ IImage16* processImage (ProcessingJob* pjob, int& errorCode, ProgressListener* p
|
|||||||
// perform transform (excepted resizing)
|
// perform transform (excepted resizing)
|
||||||
if (ipf.needsTransform()) {
|
if (ipf.needsTransform()) {
|
||||||
Imagefloat* trImg = new Imagefloat (fw, fh);
|
Imagefloat* trImg = new Imagefloat (fw, fh);
|
||||||
ipf.transform (baseImg, trImg, 0, 0, 0, 0, fw, fh);
|
ipf.transform (baseImg, trImg, 0, 0, 0, 0, fw, fh, imgsrc->getMetaData()->getFocalLen(), imgsrc->getRotateDegree());
|
||||||
delete baseImg;
|
delete baseImg;
|
||||||
baseImg = trImg;
|
baseImg = trImg;
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ set (BASESOURCEFILES
|
|||||||
coarsepanel.cc cacorrection.cc hlrec.cc chmixer.cc
|
coarsepanel.cc cacorrection.cc hlrec.cc chmixer.cc
|
||||||
resize.cc icmpanel.cc crop.cc shadowshighlights.cc
|
resize.cc icmpanel.cc crop.cc shadowshighlights.cc
|
||||||
impulsedenoise.cc dirpyrdenoise.cc epd.cc
|
impulsedenoise.cc dirpyrdenoise.cc epd.cc
|
||||||
exifpanel.cc toolpanel.cc
|
exifpanel.cc toolpanel.cc lensprofile.cc
|
||||||
sharpening.cc vibrance.cc rgbcurves.cc
|
sharpening.cc vibrance.cc rgbcurves.cc
|
||||||
whitebalance.cc vignetting.cc rotate.cc distortion.cc
|
whitebalance.cc vignetting.cc rotate.cc distortion.cc
|
||||||
crophandler.cc dirbrowser.cc
|
crophandler.cc dirbrowser.cc
|
||||||
@ -40,9 +40,9 @@ if (WIN32)
|
|||||||
#set_target_properties (rth PROPERTIES LINK_FLAGS "-mwindows")
|
#set_target_properties (rth PROPERTIES LINK_FLAGS "-mwindows")
|
||||||
else (WIN32)
|
else (WIN32)
|
||||||
include_directories (${EXTRA_INCDIR} ${GLIB2_INCLUDE_DIRS} ${GLIBMM_INCLUDE_DIRS}
|
include_directories (${EXTRA_INCDIR} ${GLIB2_INCLUDE_DIRS} ${GLIBMM_INCLUDE_DIRS}
|
||||||
${GTK_INCLUDE_DIRS} ${GTKMM_INCLUDE_DIRS} ${GIO_INCLUDE_DIRS} ${GIOMM_INCLUDE_DIRS} ${IPTCDATA_INCLUDE_DIRS} ${LCMS_INCLUDE_DIRS} ${GTHREAD_INCLUDE_DIRS} ${GOBJECT_INCLUDE_DIRS} )
|
${GTK_INCLUDE_DIRS} ${GTKMM_INCLUDE_DIRS} ${GIO_INCLUDE_DIRS} ${GIOMM_INCLUDE_DIRS} ${IPTCDATA_INCLUDE_DIRS} ${LCMS_INCLUDE_DIRS} ${EXPAT_INCLUDE_DIRS} ${GTHREAD_INCLUDE_DIRS} ${GOBJECT_INCLUDE_DIRS} )
|
||||||
link_directories (${EXTRA_LIBDIR} ${GLIB2_LIBRARY_DIRS} ${GLIBMM_LIBRARY_DIRS}
|
link_directories (${EXTRA_LIBDIR} ${GLIB2_LIBRARY_DIRS} ${GLIBMM_LIBRARY_DIRS}
|
||||||
${GTK_LIBRARY_DIRS} ${GTKMM_LIBRARY_DIRS} ${GIO_LIBRARY_DIRS} ${GIOMM_LIBRARY_DIRS} ${IPTCDATA_LIBRARY_DIRS} ${LCMS_LIBRARY_DIRS} ${GTHREAD_LIBRARY_DIRS} ${GOBJECT_LIBRARY_DIRS})
|
${GTK_LIBRARY_DIRS} ${GTKMM_LIBRARY_DIRS} ${GIO_LIBRARY_DIRS} ${GIOMM_LIBRARY_DIRS} ${IPTCDATA_LIBRARY_DIRS} ${LCMS_LIBRARY_DIRS} ${EXPAT_LIBRARY_DIRS} ${GTHREAD_LIBRARY_DIRS} ${GOBJECT_LIBRARY_DIRS})
|
||||||
endif (WIN32)
|
endif (WIN32)
|
||||||
# create config.h which defines where data are stored
|
# create config.h which defines where data are stored
|
||||||
configure_file (${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_SOURCE_DIR}/config.h)
|
configure_file (${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_SOURCE_DIR}/config.h)
|
||||||
@ -53,6 +53,6 @@ set_target_properties (rth PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS}" OUTPUT_
|
|||||||
#target_link_libraries (rth rtengine ${JPEG_LIBRARIES} ${PNG_LIBRARIES} ${ZLIB_LIBRARIES} ${TIFF_LIBRARIES} ${EXTRA_LIB} ${GOBJECT_LIBRARIES} ${GTHREAD_LIBRARIES}
|
#target_link_libraries (rth rtengine ${JPEG_LIBRARIES} ${PNG_LIBRARIES} ${ZLIB_LIBRARIES} ${TIFF_LIBRARIES} ${EXTRA_LIB} ${GOBJECT_LIBRARIES} ${GTHREAD_LIBRARIES}
|
||||||
# ${GLIB2_LIBRARIES} ${GLIBMM_LIBRARIES} ${GTK_LIBRARIES} ${GTKMM_LIBRARIES} ${GIO_LIBRARIES} ${GIOMM_LIBRARIES} ${LCMS_LIBRARIES} ${IPTCDATA_LIBRARIES})
|
# ${GLIB2_LIBRARIES} ${GLIBMM_LIBRARIES} ${GTK_LIBRARIES} ${GTKMM_LIBRARIES} ${GIO_LIBRARIES} ${GIOMM_LIBRARIES} ${LCMS_LIBRARIES} ${IPTCDATA_LIBRARIES})
|
||||||
target_link_libraries (rth rtengine ${JPEG_LIBRARIES} ${PNG_LIBRARIES} ${ZLIB_LIBRARIES} ${TIFF_LIBRARIES} ${GOBJECT_LIBRARIES} ${GTHREAD_LIBRARIES}
|
target_link_libraries (rth rtengine ${JPEG_LIBRARIES} ${PNG_LIBRARIES} ${ZLIB_LIBRARIES} ${TIFF_LIBRARIES} ${GOBJECT_LIBRARIES} ${GTHREAD_LIBRARIES}
|
||||||
${GLIB2_LIBRARIES} ${GLIBMM_LIBRARIES} ${GTK_LIBRARIES} ${GTKMM_LIBRARIES} ${GIO_LIBRARIES} ${GIOMM_LIBRARIES} ${LCMS_LIBRARIES} ${IPTCDATA_LIBRARIES} ${EXTRA_LIB_RTGUI})
|
${GLIB2_LIBRARIES} ${GLIBMM_LIBRARIES} ${GTK_LIBRARIES} ${GTKMM_LIBRARIES} ${GIO_LIBRARIES} ${GIOMM_LIBRARIES} ${LCMS_LIBRARIES} ${EXPAT_LIBRARIES} ${IPTCDATA_LIBRARIES} ${EXTRA_LIB_RTGUI})
|
||||||
install (TARGETS rth DESTINATION ${BINDIR})
|
install (TARGETS rth DESTINATION ${BINDIR})
|
||||||
|
|
||||||
|
@ -134,8 +134,8 @@ void ParamsEdited::set (bool v) {
|
|||||||
coarse.vflip = v;
|
coarse.vflip = v;
|
||||||
commonTrans.autofill = v;
|
commonTrans.autofill = v;
|
||||||
rotate.degree = v;
|
rotate.degree = v;
|
||||||
distortion.uselensfun = v;
|
|
||||||
distortion.amount = v;
|
distortion.amount = v;
|
||||||
|
lensProf.lcpFile = v;
|
||||||
perspective.horizontal = v;
|
perspective.horizontal = v;
|
||||||
perspective.vertical = v;
|
perspective.vertical = v;
|
||||||
cacorrection.red = v;
|
cacorrection.red = v;
|
||||||
@ -327,8 +327,8 @@ void ParamsEdited::initFrom (const std::vector<rtengine::procparams::ProcParams>
|
|||||||
coarse.vflip = coarse.vflip && p.coarse.vflip == other.coarse.vflip;
|
coarse.vflip = coarse.vflip && p.coarse.vflip == other.coarse.vflip;
|
||||||
commonTrans.autofill = commonTrans.autofill && p.commonTrans.autofill == other.commonTrans.autofill;
|
commonTrans.autofill = commonTrans.autofill && p.commonTrans.autofill == other.commonTrans.autofill;
|
||||||
rotate.degree = rotate.degree && p.rotate.degree == other.rotate.degree;
|
rotate.degree = rotate.degree && p.rotate.degree == other.rotate.degree;
|
||||||
distortion.uselensfun = distortion.uselensfun && p.distortion.uselensfun == other.distortion.uselensfun;
|
|
||||||
distortion.amount = distortion.amount && p.distortion.amount == other.distortion.amount;
|
distortion.amount = distortion.amount && p.distortion.amount == other.distortion.amount;
|
||||||
|
lensProf.lcpFile = lensProf.lcpFile && p.lensProf.lcpFile == other.lensProf.lcpFile;
|
||||||
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;
|
||||||
cacorrection.red = cacorrection.red && p.cacorrection.red == other.cacorrection.red;
|
cacorrection.red = cacorrection.red && p.cacorrection.red == other.cacorrection.red;
|
||||||
@ -519,8 +519,8 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten
|
|||||||
if (coarse.vflip) toEdit.coarse.vflip = mods.coarse.vflip ? !toEdit.coarse.vflip : toEdit.coarse.vflip;
|
if (coarse.vflip) toEdit.coarse.vflip = mods.coarse.vflip ? !toEdit.coarse.vflip : toEdit.coarse.vflip;
|
||||||
if (commonTrans.autofill) toEdit.commonTrans.autofill = mods.commonTrans.autofill;
|
if (commonTrans.autofill) toEdit.commonTrans.autofill = mods.commonTrans.autofill;
|
||||||
if (rotate.degree) toEdit.rotate.degree = dontforceSet && options.baBehav[ADDSET_ROTATE_DEGREE] ? toEdit.rotate.degree + mods.rotate.degree : mods.rotate.degree;
|
if (rotate.degree) toEdit.rotate.degree = dontforceSet && options.baBehav[ADDSET_ROTATE_DEGREE] ? toEdit.rotate.degree + mods.rotate.degree : mods.rotate.degree;
|
||||||
if (distortion.uselensfun) toEdit.distortion.uselensfun = mods.distortion.uselensfun;
|
|
||||||
if (distortion.amount) toEdit.distortion.amount = dontforceSet && options.baBehav[ADDSET_DIST_AMOUNT] ? toEdit.distortion.amount + mods.distortion.amount : mods.distortion.amount;
|
if (distortion.amount) toEdit.distortion.amount = dontforceSet && options.baBehav[ADDSET_DIST_AMOUNT] ? toEdit.distortion.amount + mods.distortion.amount : mods.distortion.amount;
|
||||||
|
if (lensProf.lcpFile) toEdit.lensProf.lcpFile = mods.lensProf.lcpFile;
|
||||||
if (perspective.horizontal) toEdit.perspective.horizontal = dontforceSet && options.baBehav[ADDSET_PERSPECTIVE] ? toEdit.perspective.horizontal + mods.perspective.horizontal : mods.perspective.horizontal;
|
if (perspective.horizontal) toEdit.perspective.horizontal = dontforceSet && options.baBehav[ADDSET_PERSPECTIVE] ? toEdit.perspective.horizontal + mods.perspective.horizontal : mods.perspective.horizontal;
|
||||||
if (perspective.vertical) toEdit.perspective.vertical = dontforceSet && options.baBehav[ADDSET_PERSPECTIVE] ? toEdit.perspective.vertical + mods.perspective.vertical : mods.perspective.vertical;
|
if (perspective.vertical) toEdit.perspective.vertical = dontforceSet && options.baBehav[ADDSET_PERSPECTIVE] ? toEdit.perspective.vertical + mods.perspective.vertical : mods.perspective.vertical;
|
||||||
if (cacorrection.red) toEdit.cacorrection.red = dontforceSet && options.baBehav[ADDSET_CA] ? toEdit.cacorrection.red + mods.cacorrection.red : mods.cacorrection.red;
|
if (cacorrection.red) toEdit.cacorrection.red = dontforceSet && options.baBehav[ADDSET_CA] ? toEdit.cacorrection.red + mods.cacorrection.red : mods.cacorrection.red;
|
||||||
|
@ -243,10 +243,14 @@ class RotateParamsEdited {
|
|||||||
class DistortionParamsEdited {
|
class DistortionParamsEdited {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool uselensfun;
|
|
||||||
bool amount;
|
bool amount;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class LensProfParamsEdited {
|
||||||
|
public:
|
||||||
|
bool lcpFile;
|
||||||
|
};
|
||||||
|
|
||||||
class PerspectiveParamsEdited {
|
class PerspectiveParamsEdited {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -386,6 +390,7 @@ class ParamsEdited {
|
|||||||
CommonTransformParamsEdited commonTrans;
|
CommonTransformParamsEdited commonTrans;
|
||||||
RotateParamsEdited rotate;
|
RotateParamsEdited rotate;
|
||||||
DistortionParamsEdited distortion;
|
DistortionParamsEdited distortion;
|
||||||
|
LensProfParamsEdited lensProf;
|
||||||
PerspectiveParamsEdited perspective;
|
PerspectiveParamsEdited perspective;
|
||||||
CACorrParamsEdited cacorrection;
|
CACorrParamsEdited cacorrection;
|
||||||
VignettingParamsEdited vignetting;
|
VignettingParamsEdited vignetting;
|
||||||
|
@ -70,6 +70,7 @@ PartialPasteDlg::PartialPasteDlg (Glib::ustring title) {
|
|||||||
distortion = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_DISTORTION")));
|
distortion = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_DISTORTION")));
|
||||||
cacorr = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_CACORRECTION")));
|
cacorr = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_CACORRECTION")));
|
||||||
vignetting = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_VIGNETTING")));
|
vignetting = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_VIGNETTING")));
|
||||||
|
lcp = Gtk::manage (new Gtk::CheckButton (M("TP_LENSPROFILE_LABEL")));
|
||||||
|
|
||||||
// options in composition:
|
// options in composition:
|
||||||
coarserot = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_COARSETRANS")));
|
coarserot = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_COARSETRANS")));
|
||||||
@ -149,6 +150,7 @@ PartialPasteDlg::PartialPasteDlg (Glib::ustring title) {
|
|||||||
vboxes[3]->pack_start (*distortion, Gtk::PACK_SHRINK, 2);
|
vboxes[3]->pack_start (*distortion, Gtk::PACK_SHRINK, 2);
|
||||||
vboxes[3]->pack_start (*cacorr, Gtk::PACK_SHRINK, 2);
|
vboxes[3]->pack_start (*cacorr, Gtk::PACK_SHRINK, 2);
|
||||||
vboxes[3]->pack_start (*vignetting, Gtk::PACK_SHRINK, 2);
|
vboxes[3]->pack_start (*vignetting, Gtk::PACK_SHRINK, 2);
|
||||||
|
vboxes[3]->pack_start (*lcp, Gtk::PACK_SHRINK, 2);
|
||||||
|
|
||||||
vboxes[4]->pack_start (*composition, Gtk::PACK_SHRINK, 2);
|
vboxes[4]->pack_start (*composition, Gtk::PACK_SHRINK, 2);
|
||||||
vboxes[4]->pack_start (*hseps[4], Gtk::PACK_SHRINK, 2);
|
vboxes[4]->pack_start (*hseps[4], Gtk::PACK_SHRINK, 2);
|
||||||
@ -260,6 +262,7 @@ PartialPasteDlg::PartialPasteDlg (Glib::ustring title) {
|
|||||||
distortionConn = distortion->signal_toggled().connect (sigc::bind (sigc::mem_fun(*lens, &Gtk::CheckButton::set_inconsistent), true));
|
distortionConn = distortion->signal_toggled().connect (sigc::bind (sigc::mem_fun(*lens, &Gtk::CheckButton::set_inconsistent), true));
|
||||||
cacorrConn = cacorr->signal_toggled().connect (sigc::bind (sigc::mem_fun(*lens, &Gtk::CheckButton::set_inconsistent), true));
|
cacorrConn = cacorr->signal_toggled().connect (sigc::bind (sigc::mem_fun(*lens, &Gtk::CheckButton::set_inconsistent), true));
|
||||||
vignettingConn = vignetting->signal_toggled().connect (sigc::bind (sigc::mem_fun(*lens, &Gtk::CheckButton::set_inconsistent), true));
|
vignettingConn = vignetting->signal_toggled().connect (sigc::bind (sigc::mem_fun(*lens, &Gtk::CheckButton::set_inconsistent), true));
|
||||||
|
lcpConn = lcp->signal_toggled().connect (sigc::bind (sigc::mem_fun(*lens, &Gtk::CheckButton::set_inconsistent), true));
|
||||||
|
|
||||||
coarserotConn = coarserot->signal_toggled().connect (sigc::bind (sigc::mem_fun(*composition, &Gtk::CheckButton::set_inconsistent), true));
|
coarserotConn = coarserot->signal_toggled().connect (sigc::bind (sigc::mem_fun(*composition, &Gtk::CheckButton::set_inconsistent), true));
|
||||||
finerotConn = finerot->signal_toggled().connect (sigc::bind (sigc::mem_fun(*composition, &Gtk::CheckButton::set_inconsistent), true));
|
finerotConn = finerot->signal_toggled().connect (sigc::bind (sigc::mem_fun(*composition, &Gtk::CheckButton::set_inconsistent), true));
|
||||||
@ -495,16 +498,19 @@ void PartialPasteDlg::lensToggled () {
|
|||||||
distortionConn.block (true);
|
distortionConn.block (true);
|
||||||
cacorrConn.block (true);
|
cacorrConn.block (true);
|
||||||
vignettingConn.block (true);
|
vignettingConn.block (true);
|
||||||
|
lcpConn.block (true);
|
||||||
|
|
||||||
lens->set_inconsistent (false);
|
lens->set_inconsistent (false);
|
||||||
|
|
||||||
distortion->set_active (lens->get_active ());
|
distortion->set_active (lens->get_active ());
|
||||||
cacorr->set_active (lens->get_active ());
|
cacorr->set_active (lens->get_active ());
|
||||||
vignetting->set_active (lens->get_active ());
|
vignetting->set_active (lens->get_active ());
|
||||||
|
lcp->set_active (lens->get_active ());
|
||||||
|
|
||||||
distortionConn.block (false);
|
distortionConn.block (false);
|
||||||
cacorrConn.block (false);
|
cacorrConn.block (false);
|
||||||
vignettingConn.block (false);
|
vignettingConn.block (false);
|
||||||
|
lcpConn.block (false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PartialPasteDlg::compositionToggled () {
|
void PartialPasteDlg::compositionToggled () {
|
||||||
@ -600,6 +606,7 @@ void PartialPasteDlg::applyPaste (rtengine::procparams::ProcParams* dstPP, Param
|
|||||||
if (!distortion->get_active ()) filterPE.distortion = falsePE.distortion;
|
if (!distortion->get_active ()) filterPE.distortion = falsePE.distortion;
|
||||||
if (!cacorr->get_active ()) filterPE.cacorrection = falsePE.cacorrection;
|
if (!cacorr->get_active ()) filterPE.cacorrection = falsePE.cacorrection;
|
||||||
if (!vignetting->get_active ()) filterPE.vignetting = falsePE.vignetting;
|
if (!vignetting->get_active ()) filterPE.vignetting = falsePE.vignetting;
|
||||||
|
if (!lcp->get_active ()) filterPE.lensProf = falsePE.lensProf;
|
||||||
|
|
||||||
if (!coarserot->get_active ()) filterPE.coarse = falsePE.coarse;
|
if (!coarserot->get_active ()) filterPE.coarse = falsePE.coarse;
|
||||||
if (!finerot->get_active ()) filterPE.rotate = falsePE.rotate;
|
if (!finerot->get_active ()) filterPE.rotate = falsePE.rotate;
|
||||||
|
@ -66,6 +66,7 @@ class PartialPasteDlg : public Gtk::Dialog {
|
|||||||
Gtk::CheckButton* distortion;
|
Gtk::CheckButton* distortion;
|
||||||
Gtk::CheckButton* cacorr;
|
Gtk::CheckButton* cacorr;
|
||||||
Gtk::CheckButton* vignetting;
|
Gtk::CheckButton* vignetting;
|
||||||
|
Gtk::CheckButton* lcp;
|
||||||
|
|
||||||
// options in composition:
|
// options in composition:
|
||||||
Gtk::CheckButton* coarserot;
|
Gtk::CheckButton* coarserot;
|
||||||
@ -109,7 +110,7 @@ class PartialPasteDlg : public Gtk::Dialog {
|
|||||||
sigc::connection wbConn, exposureConn, hlrecConn, shConn, labcurveConn;
|
sigc::connection wbConn, exposureConn, hlrecConn, shConn, labcurveConn;
|
||||||
sigc::connection sharpenConn, gradsharpenConn, microcontrastConn, impdenConn, dirpyrdenConn, waveqConn, defringeConn, epdConn, dirpyreqConn;
|
sigc::connection sharpenConn, gradsharpenConn, microcontrastConn, impdenConn, dirpyrdenConn, waveqConn, defringeConn, epdConn, dirpyreqConn;
|
||||||
sigc::connection vibranceConn, chmixerConn, hsveqConn, rgbcurvesConn;
|
sigc::connection vibranceConn, chmixerConn, hsveqConn, rgbcurvesConn;
|
||||||
sigc::connection distortionConn, cacorrConn, vignettingConn;
|
sigc::connection distortionConn, cacorrConn, vignettingConn, lcpConn;
|
||||||
sigc::connection coarserotConn, finerotConn, cropConn, resizeConn, perspectiveConn, commonTransConn;
|
sigc::connection coarserotConn, finerotConn, cropConn, resizeConn, perspectiveConn, commonTransConn;
|
||||||
sigc::connection exifchConn, iptcConn, icmConn, gamcsconn;
|
sigc::connection exifchConn, iptcConn, icmConn, gamcsconn;
|
||||||
sigc::connection df_fileConn, df_AutoSelectConn, ff_fileConn, ff_AutoSelectConn, ff_BlurRadiusConn, ff_BlurTypeConn;
|
sigc::connection df_fileConn, df_AutoSelectConn, ff_fileConn, ff_AutoSelectConn, ff_BlurRadiusConn, ff_BlurTypeConn;
|
||||||
|
@ -468,7 +468,7 @@ rtengine::IImage8* Thumbnail::processThumbImage (const rtengine::procparams::Pro
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Full thumbnail: apply profile
|
// Full thumbnail: apply profile
|
||||||
image = tpp->processImage (pparams, h, rtengine::TI_Bilinear, cfs.camera, scale );
|
image = tpp->processImage (pparams, h, rtengine::TI_Bilinear, cfs.camera, cfs.focalLen, scale );
|
||||||
}
|
}
|
||||||
|
|
||||||
tpp->getDimensions(lastW,lastH,lastScale);
|
tpp->getDimensions(lastW,lastH,lastScale);
|
||||||
@ -493,7 +493,7 @@ rtengine::IImage8* Thumbnail::upgradeThumbImage (const rtengine::procparams::Pro
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
rtengine::IImage8* image = tpp->processImage (pparams, h, rtengine::TI_Bilinear, cfs.camera, scale );
|
rtengine::IImage8* image = tpp->processImage (pparams, h, rtengine::TI_Bilinear, cfs.camera, cfs.focalLen, scale );
|
||||||
tpp->getDimensions(lastW,lastH,lastScale);
|
tpp->getDimensions(lastW,lastH,lastScale);
|
||||||
|
|
||||||
delete tpp;
|
delete tpp;
|
||||||
|
@ -52,6 +52,7 @@ ToolPanelCoordinator::ToolPanelCoordinator () : ipc(NULL) {
|
|||||||
lcurve = Gtk::manage (new LCurve ());
|
lcurve = Gtk::manage (new LCurve ());
|
||||||
rgbcurves = Gtk::manage (new RGBCurves ());
|
rgbcurves = Gtk::manage (new RGBCurves ());
|
||||||
lensgeom = Gtk::manage (new LensGeometry ());
|
lensgeom = Gtk::manage (new LensGeometry ());
|
||||||
|
lensProf = Gtk::manage (new LensProfilePanel ());
|
||||||
distortion = Gtk::manage (new Distortion ());
|
distortion = Gtk::manage (new Distortion ());
|
||||||
rotate = Gtk::manage (new Rotate ());
|
rotate = Gtk::manage (new Rotate ());
|
||||||
vibrance = Gtk::manage (new Vibrance ());
|
vibrance = Gtk::manage (new Vibrance ());
|
||||||
@ -97,6 +98,7 @@ ToolPanelCoordinator::ToolPanelCoordinator () : ipc(NULL) {
|
|||||||
addPanel (transformPanel, lensgeom, M("TP_LENSGEOM_LABEL")); toolPanels.push_back (lensgeom);
|
addPanel (transformPanel, lensgeom, M("TP_LENSGEOM_LABEL")); toolPanels.push_back (lensgeom);
|
||||||
addPanel (lensgeom->getPackBox(), rotate, M("TP_ROTATE_LABEL")); toolPanels.push_back (rotate);
|
addPanel (lensgeom->getPackBox(), rotate, M("TP_ROTATE_LABEL")); toolPanels.push_back (rotate);
|
||||||
addPanel (lensgeom->getPackBox(), perspective, M("TP_PERSPECTIVE_LABEL")); toolPanels.push_back (perspective);
|
addPanel (lensgeom->getPackBox(), perspective, M("TP_PERSPECTIVE_LABEL")); toolPanels.push_back (perspective);
|
||||||
|
addPanel (lensgeom->getPackBox(), lensProf, M("TP_LENSPROFILE_LABEL")); toolPanels.push_back (lensProf);
|
||||||
addPanel (lensgeom->getPackBox(), distortion, M("TP_DISTORTION_LABEL")); toolPanels.push_back (distortion);
|
addPanel (lensgeom->getPackBox(), distortion, M("TP_DISTORTION_LABEL")); toolPanels.push_back (distortion);
|
||||||
addPanel (lensgeom->getPackBox(), cacorrection, M("TP_CACORRECTION_LABEL")); toolPanels.push_back (cacorrection);
|
addPanel (lensgeom->getPackBox(), cacorrection, M("TP_CACORRECTION_LABEL")); toolPanels.push_back (cacorrection);
|
||||||
addPanel (lensgeom->getPackBox(), vignetting, M("TP_VIGNETTING_LABEL")); toolPanels.push_back (vignetting);
|
addPanel (lensgeom->getPackBox(), vignetting, M("TP_VIGNETTING_LABEL")); toolPanels.push_back (vignetting);
|
||||||
|
@ -45,6 +45,7 @@
|
|||||||
#include "chmixer.h"
|
#include "chmixer.h"
|
||||||
#include "hlrec.h"
|
#include "hlrec.h"
|
||||||
#include "cacorrection.h"
|
#include "cacorrection.h"
|
||||||
|
#include "lensprofile.h"
|
||||||
#include "distortion.h"
|
#include "distortion.h"
|
||||||
#include "perspective.h"
|
#include "perspective.h"
|
||||||
#include "rotate.h"
|
#include "rotate.h"
|
||||||
@ -83,6 +84,7 @@ class ToolPanelCoordinator : public ToolPanelListener,
|
|||||||
WhiteBalance* whitebalance;
|
WhiteBalance* whitebalance;
|
||||||
Vignetting* vignetting;
|
Vignetting* vignetting;
|
||||||
LensGeometry* lensgeom;
|
LensGeometry* lensgeom;
|
||||||
|
LensProfilePanel* lensProf;
|
||||||
Rotate* rotate;
|
Rotate* rotate;
|
||||||
Distortion* distortion;
|
Distortion* distortion;
|
||||||
PerspCorrection* perspective;
|
PerspCorrection* perspective;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user