merge with dev
This commit is contained in:
commit
9786ec0687
@ -7,6 +7,7 @@ Processor: ${PROC_LABEL}
|
||||
System: ${SYSTEM}
|
||||
Bit depth: ${PROC_BIT_DEPTH}
|
||||
Gtkmm: V${GTKMM_VERSION}
|
||||
Lensfun: V${LENSFUN_VERSION}
|
||||
Build type: ${BUILD_TYPE}
|
||||
Build flags: ${CXX_FLAGS}
|
||||
Link flags: ${LFLAGS}
|
||||
|
@ -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)
|
||||
@ -389,7 +390,8 @@ set(ABOUT_COMMAND_WITH_ARGS ${CMAKE_COMMAND}
|
||||
-DBUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
|
||||
-DGTKMM_VERSION:STRING=${GTKMM_VERSION}
|
||||
-DOPTION_OMP:STRING=${OPTION_OMP}
|
||||
-DWITH_MYFILE_MMAP:STRING=${WITH_MYFILE_MMAP})
|
||||
-DWITH_MYFILE_MMAP:STRING=${WITH_MYFILE_MMAP}
|
||||
-DLENSFUN_VERSION:STRING=${LENSFUN_VERSION})
|
||||
|
||||
if(WIN32)
|
||||
list(APPEND ABOUT_COMMAND_WITH_ARGS -DSYSTEM:STRING=Windows
|
||||
|
@ -281,9 +281,9 @@ HISTORY_MSG_30;RLD - Radius
|
||||
HISTORY_MSG_31;RLD - Amount
|
||||
HISTORY_MSG_32;RLD - Damping
|
||||
HISTORY_MSG_33;RLD - Iterations
|
||||
HISTORY_MSG_34;LCP distortion correction
|
||||
HISTORY_MSG_35;LCP vignetting correction
|
||||
HISTORY_MSG_36;LCP CA correction
|
||||
HISTORY_MSG_34;Lens Correction - Distortion
|
||||
HISTORY_MSG_35;Lens Correction - Vignetting
|
||||
HISTORY_MSG_36;Lens Correction - CA
|
||||
HISTORY_MSG_37;Exposure - Auto levels
|
||||
HISTORY_MSG_38;White Balance - Method
|
||||
HISTORY_MSG_39;WB - Temperature
|
||||
@ -332,7 +332,7 @@ HISTORY_MSG_81;Resize
|
||||
HISTORY_MSG_82;Profile changed
|
||||
HISTORY_MSG_83;S/H - Sharp mask
|
||||
HISTORY_MSG_84;Perspective correction
|
||||
HISTORY_MSG_85;LCP
|
||||
HISTORY_MSG_85;Lens Correction - LCP file
|
||||
HISTORY_MSG_86;RGB Curves - Luminosity mode
|
||||
HISTORY_MSG_87;Impulse Noise Reduction
|
||||
HISTORY_MSG_88;Impulse NR threshold
|
||||
@ -731,94 +731,97 @@ HISTORY_MSG_481;CAM02 - Temp scene
|
||||
HISTORY_MSG_482;CAM02 - Green scene
|
||||
HISTORY_MSG_483;CAM02 - Yb scene
|
||||
HISTORY_MSG_484;CAM02 - Auto Yb scene
|
||||
HISTORY_MSG_485;Local L*a*b*
|
||||
HISTORY_MSG_486;Local - Bottom
|
||||
HISTORY_MSG_487;Local - Right
|
||||
HISTORY_MSG_488;Local - Center
|
||||
HISTORY_MSG_489;Local - Lightness/
|
||||
HISTORY_MSG_490;Local - Lightness
|
||||
HISTORY_MSG_491;Local - Contrast
|
||||
HISTORY_MSG_492;Local - Chrominance
|
||||
HISTORY_MSG_493;Local - Transition
|
||||
HISTORY_MSG_494;Local - Avoid color shift
|
||||
HISTORY_MSG_495;Local - Top
|
||||
HISTORY_MSG_496;Local - Left
|
||||
HISTORY_MSG_497;Local - Method
|
||||
HISTORY_MSG_498;Local - Color Inverse
|
||||
HISTORY_MSG_499;Local - Radius
|
||||
HISTORY_MSG_500;Local - Blur Inverse
|
||||
HISTORY_MSG_501;Local - Noise
|
||||
HISTORY_MSG_502;Local - Scope
|
||||
HISTORY_MSG_503;Local - Retinex method
|
||||
HISTORY_MSG_504;Local - Retinex strength
|
||||
HISTORY_MSG_505;Local - Retinex radius
|
||||
HISTORY_MSG_506;Local - Retinex contrast
|
||||
HISTORY_MSG_507;Local - Retinex Gain curve
|
||||
HISTORY_MSG_508;Local - Retinex chroma
|
||||
HISTORY_MSG_509;Local - Retinex Inverse
|
||||
HISTORY_MSG_510;Local - Hue scope
|
||||
HISTORY_MSG_511;Local - Spot
|
||||
HISTORY_MSG_512;Local - Blur Luminance only
|
||||
HISTORY_MSG_513;Local - Update GUI and Mip -1
|
||||
HISTORY_MSG_514;Local - Sh Radius
|
||||
HISTORY_MSG_515;Local - Sh Amount
|
||||
HISTORY_MSG_516;Local - Sh Damping
|
||||
HISTORY_MSG_517;Local - Sh Iterations
|
||||
HISTORY_MSG_518;Local - Sh Scope
|
||||
HISTORY_MSG_519;Local - Sh Inverse
|
||||
HISTORY_MSG_520;Local - Spot size
|
||||
HISTORY_MSG_521;Local - artifacts theshold
|
||||
HISTORY_MSG_522;Local - artifacts iterations
|
||||
HISTORY_MSG_523;Local - Quality
|
||||
HISTORY_MSG_524;Local - Noise lum f
|
||||
HISTORY_MSG_525;Local - Noise lum c
|
||||
HISTORY_MSG_526;Local - Noise chro f
|
||||
HISTORY_MSG_527;Local - Noise chro c
|
||||
HISTORY_MSG_528;Local - cbdl threshold
|
||||
HISTORY_MSG_529;Local - cbdl mult
|
||||
HISTORY_MSG_530;Local - cbdl scope
|
||||
HISTORY_MSG_531;Local - Blur scope
|
||||
HISTORY_MSG_532;Local - TM strength
|
||||
HISTORY_MSG_533;Local - TM gamma
|
||||
HISTORY_MSG_534;Local - TM edge stopping
|
||||
HISTORY_MSG_535;Local - TM scale
|
||||
HISTORY_MSG_536;Local - TM Reweighting
|
||||
HISTORY_MSG_537;Local - TM scope
|
||||
HISTORY_MSG_538;Local - Update GUI and Mip -2
|
||||
HISTORY_MSG_539;Local - Update GUI and Mip -3
|
||||
HISTORY_MSG_540;Local - LL Curve
|
||||
HISTORY_MSG_541;Local - Color and light
|
||||
HISTORY_MSG_542;Local - Blur and noise
|
||||
HISTORY_MSG_543;Local - Tone mapping
|
||||
HISTORY_MSG_544;Local - Retinex
|
||||
HISTORY_MSG_545;Local - Sharpening
|
||||
HISTORY_MSG_546;Local - CBDL
|
||||
HISTORY_MSG_547;Local - Denoise
|
||||
HISTORY_MSG_548;Local - LH Curve
|
||||
HISTORY_MSG_549;Local - Enable super
|
||||
HISTORY_MSG_550;Local - CC curve
|
||||
HISTORY_MSG_551;Local - curve method
|
||||
HISTORY_MSG_552;Local - hueref
|
||||
HISTORY_MSG_553;Local - chromaref
|
||||
HISTORY_MSG_554;Local - lumaref
|
||||
HISTORY_MSG_555;Local - H curve
|
||||
HISTORY_MSG_556;Local - Vibrance
|
||||
HISTORY_MSG_557;Local - Vib H curve
|
||||
HISTORY_MSG_558;Local - Vib Protect skin tones
|
||||
HISTORY_MSG_559;Local - Vib avoid colorshift
|
||||
HISTORY_MSG_560;Local - Vib link
|
||||
HISTORY_MSG_561;Local - Vib Pastel
|
||||
HISTORY_MSG_562;Local - Vib Saturated
|
||||
HISTORY_MSG_563;Local - Vib Threshold
|
||||
HISTORY_MSG_564;Local - Vib Scope
|
||||
HISTORY_MSG_565;Local - Exposure
|
||||
HISTORY_MSG_566;Local - Exp Compensation
|
||||
HISTORY_MSG_567;Local - Exp Hlcompr
|
||||
HISTORY_MSG_568;Local - Exp hlcomprthresh
|
||||
HISTORY_MSG_569;Local - Exp black
|
||||
HISTORY_MSG_570;Local - Exp Shcompr
|
||||
HISTORY_MSG_571;Local - Exp Scope
|
||||
HISTORY_MSG_572;Local - Exp Contrast curve
|
||||
HISTORY_MSG_485;Lens Correction
|
||||
HISTORY_MSG_486;Lens Correction - Camera
|
||||
HISTORY_MSG_487;Lens Correction - Lens
|
||||
HISTORY_MSG_488;Local L*a*b*
|
||||
HISTORY_MSG_489;Local - Bottom
|
||||
HISTORY_MSG_490;Local - Right
|
||||
HISTORY_MSG_491;Local - Center
|
||||
HISTORY_MSG_492;Local - Lightness/
|
||||
HISTORY_MSG_493;Local - Lightness
|
||||
HISTORY_MSG_494;Local - Contrast
|
||||
HISTORY_MSG_495;Local - Chrominance
|
||||
HISTORY_MSG_496;Local - Transition
|
||||
HISTORY_MSG_497;Local - Avoid color shift
|
||||
HISTORY_MSG_498;Local - Top
|
||||
HISTORY_MSG_499;Local - Left
|
||||
HISTORY_MSG_500;Local - Method
|
||||
HISTORY_MSG_501;Local - Color Inverse
|
||||
HISTORY_MSG_502;Local - Radius
|
||||
HISTORY_MSG_503;Local - Blur Inverse
|
||||
HISTORY_MSG_504;Local - Noise
|
||||
HISTORY_MSG_505;Local - Scope
|
||||
HISTORY_MSG_506;Local - Retinex method
|
||||
HISTORY_MSG_507;Local - Retinex strength
|
||||
HISTORY_MSG_508;Local - Retinex radius
|
||||
HISTORY_MSG_509;Local - Retinex contrast
|
||||
HISTORY_MSG_510;Local - Retinex Gain curve
|
||||
HISTORY_MSG_511;Local - Retinex chroma
|
||||
HISTORY_MSG_512;Local - Retinex Inverse
|
||||
HISTORY_MSG_513;Local - Hue scope
|
||||
HISTORY_MSG_514;Local - Spot
|
||||
HISTORY_MSG_515;Local - Blur Luminance only
|
||||
HISTORY_MSG_516;Local - Update GUI and Mip -1
|
||||
HISTORY_MSG_517;Local - Sh Radius
|
||||
HISTORY_MSG_518;Local - Sh Amount
|
||||
HISTORY_MSG_519;Local - Sh Damping
|
||||
HISTORY_MSG_520;Local - Sh Iterations
|
||||
HISTORY_MSG_521;Local - Sh Scope
|
||||
HISTORY_MSG_522;Local - Sh Inverse
|
||||
HISTORY_MSG_523;Local - Spot size
|
||||
HISTORY_MSG_524;Local - artifacts theshold
|
||||
HISTORY_MSG_525;Local - artifacts iterations
|
||||
HISTORY_MSG_526;Local - Quality
|
||||
HISTORY_MSG_527;Local - Noise lum f
|
||||
HISTORY_MSG_528;Local - Noise lum c
|
||||
HISTORY_MSG_529;Local - Noise chro f
|
||||
HISTORY_MSG_530;Local - Noise chro c
|
||||
HISTORY_MSG_531;Local - cbdl threshold
|
||||
HISTORY_MSG_532;Local - cbdl mult
|
||||
HISTORY_MSG_533;Local - cbdl scope
|
||||
HISTORY_MSG_534;Local - Blur scope
|
||||
HISTORY_MSG_535;Local - TM strength
|
||||
HISTORY_MSG_536;Local - TM gamma
|
||||
HISTORY_MSG_537;Local - TM edge stopping
|
||||
HISTORY_MSG_538;Local - TM scale
|
||||
HISTORY_MSG_539;Local - TM Reweighting
|
||||
HISTORY_MSG_540;Local - TM scope
|
||||
HISTORY_MSG_541;Local - Update GUI and Mip -2
|
||||
HISTORY_MSG_542;Local - Update GUI and Mip -3
|
||||
HISTORY_MSG_543;Local - LL Curve
|
||||
HISTORY_MSG_544;Local - Color and light
|
||||
HISTORY_MSG_545;Local - Blur and noise
|
||||
HISTORY_MSG_546;Local - Tone mapping
|
||||
HISTORY_MSG_547;Local - Retinex
|
||||
HISTORY_MSG_548;Local - Sharpening
|
||||
HISTORY_MSG_549;Local - CBDL
|
||||
HISTORY_MSG_550;Local - Denoise
|
||||
HISTORY_MSG_551;Local - LH Curve
|
||||
HISTORY_MSG_552;Local - Enable super
|
||||
HISTORY_MSG_553;Local - CC curve
|
||||
HISTORY_MSG_554;Local - curve method
|
||||
HISTORY_MSG_555;Local - hueref
|
||||
HISTORY_MSG_556;Local - chromaref
|
||||
HISTORY_MSG_557;Local - lumaref
|
||||
HISTORY_MSG_558;Local - H curve
|
||||
HISTORY_MSG_559;Local - Vibrance
|
||||
HISTORY_MSG_560;Local - Vib H curve
|
||||
HISTORY_MSG_561;Local - Vib Protect skin tones
|
||||
HISTORY_MSG_562;Local - Vib avoid colorshift
|
||||
HISTORY_MSG_563;Local - Vib link
|
||||
HISTORY_MSG_564;Local - Vib Pastel
|
||||
HISTORY_MSG_565;Local - Vib Saturated
|
||||
HISTORY_MSG_566;Local - Vib Threshold
|
||||
HISTORY_MSG_567;Local - Vib Scope
|
||||
HISTORY_MSG_568;Local - Exposure
|
||||
HISTORY_MSG_569;Local - Exp Compensation
|
||||
HISTORY_MSG_570;Local - Exp Hlcompr
|
||||
HISTORY_MSG_571;Local - Exp hlcomprthresh
|
||||
HISTORY_MSG_572;Local - Exp black
|
||||
HISTORY_MSG_573;Local - Exp Shcompr
|
||||
HISTORY_MSG_574;Local - Exp Scope
|
||||
HISTORY_MSG_575;Local - Exp Contrast curve
|
||||
HISTORY_NEWSNAPSHOT;Add
|
||||
HISTORY_NEWSNAPSHOT_TOOLTIP;Shortcut: <b>Alt-s</b>
|
||||
HISTORY_SNAPSHOT;Snapshot
|
||||
@ -993,9 +996,9 @@ PARTIALPASTE_IMPULSEDENOISE;Impulse noise reduction
|
||||
PARTIALPASTE_IPTCINFO;IPTC
|
||||
PARTIALPASTE_LABCURVE;L*a*b* adjustments
|
||||
PARTIALPASTE_LENSGROUP;Lens Related Settings
|
||||
PARTIALPASTE_LENSPROFILE;Lens correction profile
|
||||
PARTIALPASTE_LOCALLAB;Local L*a*b*
|
||||
PARTIALPASTE_LOCGROUP;Local
|
||||
PARTIALPASTE_LENSPROFILE;Profiled lens correction
|
||||
PARTIALPASTE_METAGROUP;Metadata
|
||||
PARTIALPASTE_PCVIGNETTE;Vignette filter
|
||||
PARTIALPASTE_PERSPECTIVE;Perspective
|
||||
@ -1774,7 +1777,7 @@ TP_LABCURVE_RSTPRO_TOOLTIP;Works on the Chromaticity slider and the CC curve.
|
||||
TP_LENSGEOM_AUTOCROP;Auto-Crop
|
||||
TP_LENSGEOM_FILL;Auto-fill
|
||||
TP_LENSGEOM_LABEL;Lens / Geometry
|
||||
TP_LENSPROFILE_LABEL;Lens Correction Profile
|
||||
TP_LENSPROFILE_LABEL;Profiled Lens Correction
|
||||
TP_LENSPROFILE_USECA;Chromatic aberration correction
|
||||
TP_LENSPROFILE_USEDIST;Distortion correction
|
||||
TP_LENSPROFILE_USEVIGN;Vignetting correction
|
||||
@ -2359,3 +2362,7 @@ ZOOMPANEL_ZOOMFITCROPSCREEN;Fit crop to screen\nShortcut: <b>Alt</b>-<b>f</b>
|
||||
ZOOMPANEL_ZOOMFITSCREEN;Fit whole image to screen\nShortcut: <b>f</b>
|
||||
ZOOMPANEL_ZOOMIN;Zoom In\nShortcut: <b>+</b>
|
||||
ZOOMPANEL_ZOOMOUT;Zoom Out\nShortcut: <b>-</b>
|
||||
LENSPROFILE_CORRECTION_AUTOMATCH;Auto-matched correction parameters
|
||||
LENSPROFILE_CORRECTION_MANUAL;Manual correction parameters
|
||||
LENSPROFILE_CORRECTION_LCPFILE;LCP File
|
||||
LENSPROFILE_LENS_WARNING;Warning: the crop factor used for lens profiling is larger than the crop factor of the camera, the results might be wrong.
|
@ -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"
|
||||
@ -110,6 +111,7 @@ set(RTENGINESOURCEFILES
|
||||
slicer.cc
|
||||
stdimagesource.cc
|
||||
utils.cc
|
||||
rtlensfun.cc
|
||||
)
|
||||
|
||||
if(NOT WITH_SYSTEM_KLT)
|
||||
@ -154,6 +156,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)
|
||||
|
@ -178,6 +178,8 @@ void Ciecam02::curveJ (double br, double contr, int db, LUTf & outCurve, LUTu &
|
||||
for (int i = 0; i < (db * 32768); i++) {
|
||||
outCurve[i] = db * 32768.0 * dcurve[i];
|
||||
}
|
||||
// printf("double out500=%f out15000=%f\n", outCurve[500], outCurve[15000]);
|
||||
|
||||
}
|
||||
|
||||
void Ciecam02::curveJfloat (float br, float contr, const LUTu & histogram, LUTf & outCurve)
|
||||
@ -268,6 +270,8 @@ void Ciecam02::curveJfloat (float br, float contr, const LUTu & histogram, LUTf
|
||||
}
|
||||
|
||||
outCurve *= 32767.f;
|
||||
//printf("out500=%f out15000=%f\n", outCurve[500], outCurve[15000]);
|
||||
//outCurve.dump("brig");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -305,7 +305,7 @@ rtengine::CLUTStore& rtengine::CLUTStore::getInstance()
|
||||
return instance;
|
||||
}
|
||||
|
||||
std::shared_ptr<rtengine::HaldCLUT> rtengine::CLUTStore::getClut(const Glib::ustring& filename)
|
||||
std::shared_ptr<rtengine::HaldCLUT> rtengine::CLUTStore::getClut(const Glib::ustring& filename) const
|
||||
{
|
||||
std::shared_ptr<rtengine::HaldCLUT> result;
|
||||
|
||||
|
@ -57,14 +57,14 @@ class CLUTStore final :
|
||||
public:
|
||||
static CLUTStore& getInstance();
|
||||
|
||||
std::shared_ptr<HaldCLUT> getClut(const Glib::ustring& filename);
|
||||
std::shared_ptr<HaldCLUT> getClut(const Glib::ustring& filename) const;
|
||||
|
||||
void clearCache();
|
||||
|
||||
private:
|
||||
CLUTStore();
|
||||
|
||||
Cache<Glib::ustring, std::shared_ptr<HaldCLUT>> cache;
|
||||
mutable Cache<Glib::ustring, std::shared_ptr<HaldCLUT>> cache;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -2562,6 +2562,12 @@ void CLASS kodak_radc_load_raw()
|
||||
((short *)buf)[i] = 2048;
|
||||
for (row=0; row < height; row+=4) {
|
||||
FORC3 mul[c] = getbits(6);
|
||||
FORC3 {
|
||||
if (!mul[c]) {
|
||||
mul[c] = 1;
|
||||
derror();
|
||||
}
|
||||
}
|
||||
FORC3 {
|
||||
val = ((0x1000000/last[c] + 0x7ff) >> 12) * mul[c];
|
||||
s = val > 65564 ? 10:12;
|
||||
|
@ -708,9 +708,7 @@ void Crop::update (int todo)
|
||||
|
||||
if (needstransform)
|
||||
parent->ipf.transform (baseCrop, transCrop, cropx / skip, cropy / skip, trafx / skip, trafy / skip, skips (parent->fw, skip), skips (parent->fh, skip), parent->getFullWidth(), parent->getFullHeight(),
|
||||
parent->imgsrc->getMetaData()->getFocalLen(), parent->imgsrc->getMetaData()->getFocalLen35mm(),
|
||||
parent->imgsrc->getMetaData()->getFocusDist(),
|
||||
parent->imgsrc->getMetaData()->getFNumber(),
|
||||
parent->imgsrc->getMetaData(),
|
||||
parent->imgsrc->getRotateDegree(), false);
|
||||
else {
|
||||
baseCrop->copyData (transCrop);
|
||||
@ -1754,8 +1752,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
|
||||
|
@ -3,9 +3,10 @@
|
||||
// Green Equilibration via directional average
|
||||
//
|
||||
// copyright (c) 2008-2010 Emil Martinec <ejmartin@uchicago.edu>
|
||||
// optimized for speed 2017 Ingo Weyrich <heckflosse67@gmx.de>
|
||||
//
|
||||
//
|
||||
// code dated: February 12, 2011
|
||||
// code dated: August 25, 2017
|
||||
//
|
||||
// green_equil_RT.cc is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
@ -21,18 +22,72 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////
|
||||
#define TS 256 // Tile size
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <ctime>
|
||||
|
||||
|
||||
#include "rt_math.h"
|
||||
#include "rawimagesource.h"
|
||||
#include "opthelper.h"
|
||||
|
||||
namespace rtengine
|
||||
{
|
||||
|
||||
void RawImageSource::green_equilibrate_global(array2D<float> &rawData)
|
||||
{
|
||||
// global correction
|
||||
int ng1 = 0, ng2 = 0;
|
||||
double avgg1 = 0., avgg2 = 0.;
|
||||
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for reduction(+: ng1, ng2, avgg1, avgg2) schedule(dynamic,16)
|
||||
#endif
|
||||
|
||||
for (int i = border; i < H - border; i++) {
|
||||
double avgg = 0.;
|
||||
|
||||
for (int j = border + ((FC(i, border) & 1) ^ 1); j < W - border; j += 2) {
|
||||
avgg += rawData[i][j];
|
||||
}
|
||||
|
||||
int ng = (W - 2 * border + (FC(i, border) & 1)) / 2;
|
||||
|
||||
if (i & 1) {
|
||||
avgg2 += avgg;
|
||||
ng2 += ng;
|
||||
} else {
|
||||
avgg1 += avgg;
|
||||
ng1 += ng;
|
||||
}
|
||||
}
|
||||
|
||||
// Avoid division by zero
|
||||
if(ng1 == 0 || avgg1 == 0.0) {
|
||||
ng1 = 1;
|
||||
avgg1 = 1.0;
|
||||
}
|
||||
if(ng2 == 0 || avgg2 == 0.0) {
|
||||
ng2 = 1;
|
||||
avgg2 = 1.0;
|
||||
}
|
||||
|
||||
double corrg1 = (avgg1 / ng1 + avgg2 / ng2) / 2.0 / (avgg1 / ng1);
|
||||
double corrg2 = (avgg1 / ng1 + avgg2 / ng2) / 2.0 / (avgg2 / ng2);
|
||||
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for schedule(dynamic,16)
|
||||
#endif
|
||||
|
||||
for (int i = border; i < H - border; i++) {
|
||||
double corrg = (i & 1) ? corrg2 : corrg1;
|
||||
|
||||
for (int j = border + ((FC(i, border) & 1) ^ 1); j < W - border; j += 2) {
|
||||
rawData[i][j] *= corrg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//void green_equilibrate()//for dcraw implementation
|
||||
void RawImageSource::green_equilibrate(float thresh, array2D<float> &rawData)
|
||||
{
|
||||
@ -42,15 +97,29 @@ void RawImageSource::green_equilibrate(float thresh, array2D<float> &rawData)
|
||||
int height = H, width = W;
|
||||
|
||||
// local variables
|
||||
float** rawptr = rawData;
|
||||
array2D<float> cfa (width, height, rawptr);
|
||||
//array2D<int> checker (width,height,ARRAY2D_CLEAR_DATA);
|
||||
array2D<float> cfa(width / 2 + (width & 1), height);
|
||||
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for schedule(dynamic,16)
|
||||
#endif
|
||||
|
||||
//int verbose=1;
|
||||
for (int i = 0; i < height; ++i) {
|
||||
int j = (FC(i, 0) & 1) ^ 1;
|
||||
#ifdef __SSE2__
|
||||
|
||||
static const float eps = 1.0; //tolerance to avoid dividing by zero
|
||||
for (; j < width - 7; j += 8) {
|
||||
STVFU(cfa[i][j >> 1], LC2VFU(rawData[i][j]));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
for (; j < width; j += 2) {
|
||||
cfa[i][j >> 1] = rawData[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
constexpr float eps = 1.f; //tolerance to avoid dividing by zero
|
||||
const float thresh6 = 6 * thresh;
|
||||
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
// Fill G interpolated values with border interpolation and input values
|
||||
@ -59,94 +128,118 @@ void RawImageSource::green_equilibrate(float thresh, array2D<float> &rawData)
|
||||
//int counter, vtest;
|
||||
|
||||
//The green equilibration algorithm starts here
|
||||
/*
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for
|
||||
#endif
|
||||
for (int rr=1; rr < height-1; rr++)
|
||||
for (int cc=3-(FC(rr,2)&1); cc < width-2; cc+=2) {
|
||||
|
||||
float pcorr = (cfa[rr+1][cc+1]-cfa[rr][cc])*(cfa[rr-1][cc-1]-cfa[rr][cc]);
|
||||
float mcorr = (cfa[rr-1][cc+1]-cfa[rr][cc])*(cfa[rr+1][cc-1]-cfa[rr][cc]);
|
||||
|
||||
if (pcorr>0 && mcorr>0) {checker[rr][cc]=1;} else {checker[rr][cc]=0;}
|
||||
|
||||
checker[rr][cc]=1;//test what happens if we always interpolate
|
||||
}
|
||||
|
||||
counter=vtest=0;
|
||||
*/
|
||||
//now smooth the cfa data
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for schedule(dynamic,16)
|
||||
#pragma omp parallel
|
||||
#endif
|
||||
{
|
||||
#ifdef __SSE2__
|
||||
vfloat zd5v = F2V(0.5f);
|
||||
vfloat onev = F2V(1.f);
|
||||
vfloat threshv = F2V(thresh);
|
||||
vfloat thresh6v = F2V(thresh6);
|
||||
vfloat epsv = F2V(eps);
|
||||
#endif
|
||||
#ifdef _OPENMP
|
||||
#pragma omp for schedule(dynamic,16)
|
||||
#endif
|
||||
|
||||
for (int rr = 4; rr < height - 4; rr++)
|
||||
for (int cc = 5 - (FC(rr, 2) & 1); cc < width - 6; cc += 2) {
|
||||
//if (checker[rr][cc]) {
|
||||
//%%%%%%%%%%%%%%%%%%%%%%
|
||||
//neighbor checking code from Manuel Llorens Garcia
|
||||
float o1_1 = cfa[(rr - 1)][cc - 1];
|
||||
float o1_2 = cfa[(rr - 1)][cc + 1];
|
||||
float o1_3 = cfa[(rr + 1)][cc - 1];
|
||||
float o1_4 = cfa[(rr + 1)][cc + 1];
|
||||
float o2_1 = cfa[(rr - 2)][cc];
|
||||
float o2_2 = cfa[(rr + 2)][cc];
|
||||
float o2_3 = cfa[(rr)][cc - 2];
|
||||
float o2_4 = cfa[(rr)][cc + 2];
|
||||
for (int rr = 4; rr < height - 4; rr++) {
|
||||
int cc = 5 - (FC(rr, 2) & 1);
|
||||
#ifdef __SSE2__
|
||||
|
||||
float d1 = (o1_1 + o1_2 + o1_3 + o1_4) * 0.25f;
|
||||
float d2 = (o2_1 + o2_2 + o2_3 + o2_4) * 0.25f;
|
||||
for (; cc < width - 12; cc += 8) {
|
||||
//neighbour checking code from Manuel Llorens Garcia
|
||||
vfloat o1_1 = LVFU(cfa[rr - 1][(cc - 1) >> 1]);
|
||||
vfloat o1_2 = LVFU(cfa[rr - 1][(cc + 1) >> 1]);
|
||||
vfloat o1_3 = LVFU(cfa[rr + 1][(cc - 1) >> 1]);
|
||||
vfloat o1_4 = LVFU(cfa[rr + 1][(cc + 1) >> 1]);
|
||||
vfloat o2_1 = LVFU(cfa[rr - 2][cc >> 1]);
|
||||
vfloat o2_2 = LVFU(cfa[rr + 2][cc >> 1]);
|
||||
vfloat o2_3 = LVFU(cfa[rr][(cc >> 1) - 1]);
|
||||
vfloat o2_4 = LVFU(cfa[rr][(cc >> 1) + 1]);
|
||||
|
||||
float c1 = (fabs(o1_1 - o1_2) + fabs(o1_1 - o1_3) + fabs(o1_1 - o1_4) + fabs(o1_2 - o1_3) + fabs(o1_3 - o1_4) + fabs(o1_2 - o1_4)) / 6.f;
|
||||
float c2 = (fabs(o2_1 - o2_2) + fabs(o2_1 - o2_3) + fabs(o2_1 - o2_4) + fabs(o2_2 - o2_3) + fabs(o2_3 - o2_4) + fabs(o2_2 - o2_4)) / 6.f;
|
||||
//%%%%%%%%%%%%%%%%%%%%%%
|
||||
vfloat d1 = (o1_1 + o1_2 + o1_3 + o1_4);
|
||||
vfloat d2 = (o2_1 + o2_2 + o2_3 + o2_4);
|
||||
|
||||
//vote1=(checker[rr-2][cc]+checker[rr][cc-2]+checker[rr][cc+2]+checker[rr+2][cc]);
|
||||
//vote2=(checker[rr+1][cc-1]+checker[rr+1][cc+1]+checker[rr-1][cc-1]+checker[rr-1][cc+1]);
|
||||
//if ((vote1==0 || vote2==0) && (c1+c2)<2*thresh*fabs(d1-d2)) vtest++;
|
||||
//if (vote1>0 && vote2>0 && (c1+c2)<4*thresh*fabs(d1-d2)) {
|
||||
if ((c1 + c2) < 4 * thresh * fabs(d1 - d2)) {
|
||||
vfloat c1 = (vabsf(o1_1 - o1_2) + vabsf(o1_1 - o1_3) + vabsf(o1_1 - o1_4) + vabsf(o1_2 - o1_3) + vabsf(o1_3 - o1_4) + vabsf(o1_2 - o1_4));
|
||||
vfloat c2 = (vabsf(o2_1 - o2_2) + vabsf(o2_1 - o2_3) + vabsf(o2_1 - o2_4) + vabsf(o2_2 - o2_3) + vabsf(o2_3 - o2_4) + vabsf(o2_2 - o2_4));
|
||||
|
||||
vmask mask1 = vmaskf_lt(c1 + c2, thresh6v * vabsf(d1 - d2));
|
||||
|
||||
if (_mm_movemask_ps((vfloat)mask1)) { // if for any of the 4 pixels the condition is true, do the maths for all 4 pixels and mask the unused out at the end
|
||||
//pixel interpolation
|
||||
float gin = cfa[rr][cc];
|
||||
vfloat gin = LVFU(cfa[rr][cc >> 1]);
|
||||
|
||||
float gse = (cfa[rr + 1][cc + 1]) + 0.5f * (cfa[rr][cc] - cfa[rr + 2][cc + 2]);
|
||||
float gnw = (cfa[rr - 1][cc - 1]) + 0.5f * (cfa[rr][cc] - cfa[rr - 2][cc - 2]);
|
||||
float gne = (cfa[rr - 1][cc + 1]) + 0.5f * (cfa[rr][cc] - cfa[rr - 2][cc + 2]);
|
||||
float gsw = (cfa[rr + 1][cc - 1]) + 0.5f * (cfa[rr][cc] - cfa[rr + 2][cc - 2]);
|
||||
vfloat gmp2p2 = gin - LVFU(cfa[rr + 2][(cc >> 1) + 1]);
|
||||
vfloat gmm2m2 = gin - LVFU(cfa[rr - 2][(cc >> 1) - 1]);
|
||||
vfloat gmm2p2 = gin - LVFU(cfa[rr - 2][(cc >> 1) + 1]);
|
||||
vfloat gmp2m2 = gin - LVFU(cfa[rr + 2][(cc >> 1) - 1]);
|
||||
|
||||
vfloat gse = o1_4 + zd5v * gmp2p2;
|
||||
vfloat gnw = o1_1 + zd5v * gmm2m2;
|
||||
vfloat gne = o1_2 + zd5v * gmm2p2;
|
||||
vfloat gsw = o1_3 + zd5v * gmp2m2;
|
||||
|
||||
vfloat wtse = onev / (epsv + SQRV(gmp2p2) + SQRV(LVFU(cfa[rr + 3][(cc + 3) >> 1]) - o1_4));
|
||||
vfloat wtnw = onev / (epsv + SQRV(gmm2m2) + SQRV(LVFU(cfa[rr - 3][(cc - 3) >> 1]) - o1_1));
|
||||
vfloat wtne = onev / (epsv + SQRV(gmm2p2) + SQRV(LVFU(cfa[rr - 3][(cc + 3) >> 1]) - o1_2));
|
||||
vfloat wtsw = onev / (epsv + SQRV(gmp2m2) + SQRV(LVFU(cfa[rr + 3][(cc - 3) >> 1]) - o1_3));
|
||||
|
||||
float wtse = 1.0f / (eps + SQR(cfa[rr + 2][cc + 2] - cfa[rr][cc]) + SQR(cfa[rr + 3][cc + 3] - cfa[rr + 1][cc + 1]));
|
||||
float wtnw = 1.0f / (eps + SQR(cfa[rr - 2][cc - 2] - cfa[rr][cc]) + SQR(cfa[rr - 3][cc - 3] - cfa[rr - 1][cc - 1]));
|
||||
float wtne = 1.0f / (eps + SQR(cfa[rr - 2][cc + 2] - cfa[rr][cc]) + SQR(cfa[rr - 3][cc + 3] - cfa[rr - 1][cc + 1]));
|
||||
float wtsw = 1.0f / (eps + SQR(cfa[rr + 2][cc - 2] - cfa[rr][cc]) + SQR(cfa[rr + 3][cc - 3] - cfa[rr + 1][cc - 1]));
|
||||
vfloat ginterp = (gse * wtse + gnw * wtnw + gne * wtne + gsw * wtsw) / (wtse + wtnw + wtne + wtsw);
|
||||
|
||||
vfloat val = vself(vmaskf_lt(ginterp - gin, threshv * (ginterp + gin)), zd5v * (ginterp + gin), gin);
|
||||
val = vself(mask1, val, gin);
|
||||
STC2VFU(rawData[rr][cc], val);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
for (; cc < width - 6; cc += 2) {
|
||||
//neighbour checking code from Manuel Llorens Garcia
|
||||
float o1_1 = cfa[rr - 1][(cc - 1) >> 1];
|
||||
float o1_2 = cfa[rr - 1][(cc + 1) >> 1];
|
||||
float o1_3 = cfa[rr + 1][(cc - 1) >> 1];
|
||||
float o1_4 = cfa[rr + 1][(cc + 1) >> 1];
|
||||
float o2_1 = cfa[rr - 2][cc >> 1];
|
||||
float o2_2 = cfa[rr + 2][cc >> 1];
|
||||
float o2_3 = cfa[rr][(cc - 2) >> 1];
|
||||
float o2_4 = cfa[rr][(cc + 2) >> 1];
|
||||
|
||||
float d1 = (o1_1 + o1_2) + (o1_3 + o1_4);
|
||||
float d2 = (o2_1 + o2_2) + (o2_3 + o2_4);
|
||||
|
||||
float c1 = (fabs(o1_1 - o1_2) + fabs(o1_1 - o1_3) + fabs(o1_1 - o1_4) + fabs(o1_2 - o1_3) + fabs(o1_3 - o1_4) + fabs(o1_2 - o1_4));
|
||||
float c2 = (fabs(o2_1 - o2_2) + fabs(o2_1 - o2_3) + fabs(o2_1 - o2_4) + fabs(o2_2 - o2_3) + fabs(o2_3 - o2_4) + fabs(o2_2 - o2_4));
|
||||
|
||||
if (c1 + c2 < thresh6 * fabs(d1 - d2)) {
|
||||
//pixel interpolation
|
||||
float gin = cfa[rr][cc >> 1];
|
||||
|
||||
float gmp2p2 = gin - cfa[rr + 2][(cc + 2) >> 1];
|
||||
float gmm2m2 = gin - cfa[rr - 2][(cc - 2) >> 1];
|
||||
float gmm2p2 = gin - cfa[rr - 2][(cc + 2) >> 1];
|
||||
float gmp2m2 = gin - cfa[rr + 2][(cc - 2) >> 1];
|
||||
|
||||
float gse = o1_4 + 0.5f * gmp2p2;
|
||||
float gnw = o1_1 + 0.5f * gmm2m2;
|
||||
float gne = o1_2 + 0.5f * gmm2p2;
|
||||
float gsw = o1_3 + 0.5f * gmp2m2;
|
||||
|
||||
float wtse = 1.f / (eps + SQR(gmp2p2) + SQR(cfa[rr + 3][(cc + 3) >> 1] - o1_4));
|
||||
float wtnw = 1.f / (eps + SQR(gmm2m2) + SQR(cfa[rr - 3][(cc - 3) >> 1] - o1_1));
|
||||
float wtne = 1.f / (eps + SQR(gmm2p2) + SQR(cfa[rr - 3][(cc + 3) >> 1] - o1_2));
|
||||
float wtsw = 1.f / (eps + SQR(gmp2m2) + SQR(cfa[rr + 3][(cc - 3) >> 1] - o1_3));
|
||||
|
||||
float ginterp = (gse * wtse + gnw * wtnw + gne * wtne + gsw * wtsw) / (wtse + wtnw + wtne + wtsw);
|
||||
|
||||
if ( ((ginterp - gin) < thresh * (ginterp + gin)) ) {
|
||||
if (ginterp - gin < thresh * (ginterp + gin)) {
|
||||
rawData[rr][cc] = 0.5f * (ginterp + gin);
|
||||
//counter++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// }
|
||||
}
|
||||
|
||||
//printf("pixfix count= %d; vtest= %d \n",counter,vtest);
|
||||
// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
|
||||
// done
|
||||
/*t2 = clock();
|
||||
dt = ((double)(t2-t1)) / CLOCKS_PER_SEC;
|
||||
if (verbose) {
|
||||
fprintf(stderr,_("elapsed time = %5.3fs\n"),dt);
|
||||
}*/
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#undef TS
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -512,8 +512,8 @@ 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(),
|
||||
imgsrc->getMetaData()->getFocalLen35mm(), imgsrc->getMetaData()->getFocusDist(), imgsrc->getMetaData()->getFNumber(), imgsrc->getRotateDegree(), false);
|
||||
ipf.transform (orig_prev, oprevi, 0, 0, 0, 0, pW, pH, fw, fh,
|
||||
imgsrc->getMetaData(), imgsrc->getRotateDegree(), false);
|
||||
else {
|
||||
orig_prev->copyData (oprevi);
|
||||
}
|
||||
@ -3820,10 +3820,10 @@ 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);
|
||||
const std::shared_ptr<LCPProfile> pLCPProf = LCPStore::getInstance()->getProfile (params.lensProf.lcpFile);
|
||||
|
||||
if (pLCPProf) pLCPMap = new LCPMapper (pLCPProf, imgsrc->getMetaData()->getFocalLen(), imgsrc->getMetaData()->getFocalLen35mm(), imgsrc->getMetaData()->getFocusDist(),
|
||||
0, false, params.lensProf.useDist, fullw, fullh, params.coarse, imgsrc->getRotateDegree());
|
||||
@ -3921,8 +3921,8 @@ void ImProcCoordinator::saveInputICCReference (const Glib::ustring & fname, bool
|
||||
|
||||
if (ipf.needsTransform()) {
|
||||
Imagefloat* trImg = new Imagefloat (fW, fH);
|
||||
ipf.transform (im, trImg, 0, 0, 0, 0, fW, fH, fW, fH, imgsrc->getMetaData()->getFocalLen(), imgsrc->getMetaData()->getFocalLen35mm(),
|
||||
imgsrc->getMetaData()->getFocusDist(), imgsrc->getMetaData()->getFNumber(), imgsrc->getRotateDegree(), true);
|
||||
ipf.transform (im, trImg, 0, 0, 0, 0, fW, fH, fW, fH,
|
||||
imgsrc->getMetaData(), imgsrc->getRotateDegree(), true);
|
||||
delete im;
|
||||
im = trImg;
|
||||
}
|
||||
|
@ -847,6 +847,7 @@ void ImProcFunctions::ciecam_02 (CieImage* ncie, double adap, int begh, int endh
|
||||
} else if (curveMode == ColorAppearanceParams::TC_MODE_BRIGHT) {
|
||||
//attention! Brightness curves are open - unlike Lightness or Lab or RGB==> rendering and algoritms will be different
|
||||
float coef = ((aw + 4.f) * (4.f / c)) / 100.f;
|
||||
float Qanc = Qpro;
|
||||
float Qq = (float) Qpro * 327.68f * (1.f / coef);
|
||||
float Qold100 = (float) Qpro / coef;
|
||||
|
||||
@ -872,8 +873,15 @@ void ImProcFunctions::ciecam_02 (CieImage* ncie, double adap, int begh, int endh
|
||||
Qq = 0.7f * (Qq - Qold) + Qold; // not zero ==>artifacts
|
||||
}
|
||||
|
||||
Qpro = (double) (Qq * (coef) / 327.68f);
|
||||
Jpro = 100.* (Qpro * Qpro) / ((4.0 / c) * (4.0 / c) * (aw + 4.0) * (aw + 4.0));
|
||||
if (Qold == 0.f) {
|
||||
Qold = 0.001f;
|
||||
}
|
||||
|
||||
Qpro = Qanc * (Qq / Qold);
|
||||
Jpro = Jpro * SQR (Qq / Qold);
|
||||
|
||||
// Qpro = (double) (Qq * (coef) / 327.68f);
|
||||
// Jpro = 100.* (Qpro * Qpro) / ((4.0 / c) * (4.0 / c) * (aw + 4.0) * (aw + 4.0));
|
||||
t1B = true;
|
||||
|
||||
if (Jpro < 1.) {
|
||||
@ -928,6 +936,7 @@ void ImProcFunctions::ciecam_02 (CieImage* ncie, double adap, int begh, int endh
|
||||
}
|
||||
|
||||
} else if (curveMode2 == ColorAppearanceParams::TC_MODE_BRIGHT) { //
|
||||
float Qanc = Qpro;
|
||||
float coef = ((aw + 4.f) * (4.f / c)) / 100.f;
|
||||
float Qq = (float) Qpro * 327.68f * (1.f / coef);
|
||||
float Qold100 = (float) Qpro / coef;
|
||||
@ -954,8 +963,16 @@ void ImProcFunctions::ciecam_02 (CieImage* ncie, double adap, int begh, int endh
|
||||
Qq = 0.7f * (Qq - Qold) + Qold; // not zero ==>artifacts
|
||||
}
|
||||
|
||||
Qpro = (double) (Qq * (coef) / 327.68f);
|
||||
Jpro = 100.* (Qpro * Qpro) / ((4.0 / c) * (4.0 / c) * (aw + 4.0) * (aw + 4.0));
|
||||
if (Qold == 0.f) {
|
||||
Qold = 0.001f;
|
||||
}
|
||||
|
||||
// Qpro = (float) (Qq * (coef) / 327.68f);
|
||||
Qpro = Qanc * (Qq / Qold);
|
||||
Jpro = Jpro * SQR (Qq / Qold);
|
||||
|
||||
// Qpro = (double) (Qq * (coef) / 327.68f);
|
||||
// Jpro = 100.* (Qpro * Qpro) / ((4.0 / c) * (4.0 / c) * (aw + 4.0) * (aw + 4.0));
|
||||
t2B = true;
|
||||
|
||||
if (t1L) { //to workaround the problem if we modify curve1-lightnees after curve2 brightness(the cat that bites its own tail!) in fact it's another type of curve only for this case
|
||||
@ -1682,10 +1699,11 @@ void ImProcFunctions::ciecam_02float (CieImage* ncie, float adap, int begh, int
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if (alg >= 2 && la < 200.f) {
|
||||
la = 200.f;
|
||||
}
|
||||
|
||||
*/
|
||||
const float la2 = float (params->colorappearance.adaplum);
|
||||
|
||||
// level of adaptation
|
||||
@ -1776,6 +1794,7 @@ void ImProcFunctions::ciecam_02float (CieImage* ncie, float adap, int begh, int
|
||||
}
|
||||
|
||||
float sum = 0.f;
|
||||
float sumQ = 0.f;
|
||||
|
||||
#ifdef _OPENMP
|
||||
const int numThreads = min (max (width * height / 65536, 1), omp_get_max_threads());
|
||||
@ -1795,7 +1814,7 @@ void ImProcFunctions::ciecam_02float (CieImage* ncie, float adap, int begh, int
|
||||
hist16Qthr.clear();
|
||||
}
|
||||
|
||||
#pragma omp for reduction(+:sum)
|
||||
#pragma omp for reduction(+:sum,sumQ)
|
||||
|
||||
for (int i = 0; i < height; i++)
|
||||
for (int j = 0; j < width; j++) { //rough correspondence between L and J
|
||||
@ -1840,11 +1859,26 @@ void ImProcFunctions::ciecam_02float (CieImage* ncie, float adap, int begh, int
|
||||
hist16Jthr[ (int) ((koef * lab->L[i][j]))]++; //evaluate histogram luminance L # J
|
||||
}
|
||||
|
||||
//estimation of wh only with La
|
||||
float whestim = 500.f;
|
||||
|
||||
if (la < 200.f) {
|
||||
whestim = 200.f;
|
||||
} else if (la < 2500.f) {
|
||||
whestim = 350.f;
|
||||
} else {
|
||||
whestim = 500.f;
|
||||
}
|
||||
|
||||
if (needQ) {
|
||||
hist16Qthr[ (int) (sqrtf ((koef * (lab->L[i][j])) * 32768.f))]++; //for brightness Q : approximation for Q=wh*sqrt(J/100) J not equal L
|
||||
hist16Qthr[CLIP ((int) (32768.f * sqrt ((koef * (lab->L[i][j])) / 32768.f)))]++; //for brightness Q : approximation for Q=wh*sqrt(J/100) J not equal L
|
||||
//perhaps needs to introduce whestim ??
|
||||
// hist16Qthr[ (int) (sqrtf ((koef * (lab->L[i][j])) * 32768.f))]++; //for brightness Q : approximation for Q=wh*sqrt(J/100) J not equal L
|
||||
}
|
||||
|
||||
sum += koef * lab->L[i][j]; //evaluate mean J to calculate Yb
|
||||
sumQ += whestim * sqrt ((koef * (lab->L[i][j])) / 32768.f);
|
||||
//can be used in case of...
|
||||
}
|
||||
|
||||
#pragma omp critical
|
||||
@ -1858,12 +1892,14 @@ void ImProcFunctions::ciecam_02float (CieImage* ncie, float adap, int begh, int
|
||||
}
|
||||
|
||||
}
|
||||
float meanQ;
|
||||
|
||||
if (std::isnan (mean)) {
|
||||
mean = (sum / ((height) * width)) / 327.68f; //for Yb for all image...if one day "pipette" we can adapt Yb for each zone
|
||||
}
|
||||
}
|
||||
meanQ = (sumQ / ((height) * width));//in case of
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//evaluate lightness, contrast
|
||||
@ -1938,6 +1974,8 @@ void ImProcFunctions::ciecam_02float (CieImage* ncie, float adap, int begh, int
|
||||
|
||||
float cz, wh, pfl;
|
||||
Ciecam02::initcam1float (gamu, yb, pilot, f, la, xw, yw, zw, n, d, nbb, ncb, cz, aw, wh, pfl, fl, c);
|
||||
//printf ("wh=%f \n", wh);
|
||||
|
||||
const float pow1 = pow_F ( 1.64f - pow_F ( 0.29f, n ), 0.73f );
|
||||
float nj, nbbj, ncbj, czj, awj, flj;
|
||||
Ciecam02::initcam2float (gamu, yb2, pilotout, f2, la2, xw2, yw2, zw2, nj, dj, nbbj, ncbj, czj, awj, flj);
|
||||
@ -1955,7 +1993,7 @@ void ImProcFunctions::ciecam_02float (CieImage* ncie, float adap, int begh, int
|
||||
const bool LabPassOne = ! ((params->colorappearance.tonecie && (epdEnabled)) || (params->sharpening.enabled && settings->autocielab && execsharp)
|
||||
|| (params->dirpyrequalizer.enabled && settings->autocielab) || (params->defringe.enabled && settings->autocielab) || (params->sharpenMicro.enabled && settings->autocielab)
|
||||
|| (params->impulseDenoise.enabled && settings->autocielab) || (params->colorappearance.badpixsl > 0 && settings->autocielab));
|
||||
|
||||
//printf("coQ=%f\n", coefQ);
|
||||
|
||||
if (needJ) {
|
||||
if (!CAMBrightCurveJ) {
|
||||
@ -1976,7 +2014,7 @@ void ImProcFunctions::ciecam_02float (CieImage* ncie, float adap, int begh, int
|
||||
|
||||
if (CAMBrightCurveQ.dirty) {
|
||||
Ciecam02::curveJfloat (params->colorappearance.qbright, params->colorappearance.qcontrast, hist16Q, CAMBrightCurveQ);//brightness and contrast Q
|
||||
CAMBrightCurveQ /= coefQ;
|
||||
// CAMBrightCurveQ /= coefQ;
|
||||
CAMBrightCurveQ.dirty = false;
|
||||
}
|
||||
}
|
||||
@ -2126,7 +2164,11 @@ void ImProcFunctions::ciecam_02float (CieImage* ncie, float adap, int begh, int
|
||||
Qpro = QproFactor * sqrtf (Jpro);
|
||||
Cpro = (spro * spro * Qpro) / (10000.0f);
|
||||
} else if (alg == 2) {
|
||||
Qpro = CAMBrightCurveQ[ (float) (Qpro * coefQ)]; //brightness and contrast
|
||||
//printf("Qp0=%f ", Qpro);
|
||||
|
||||
Qpro = CAMBrightCurveQ[ (float) (Qpro * coefQ)] / coefQ; //brightness and contrast
|
||||
//printf("Qpaf=%f ", Qpro);
|
||||
|
||||
float Mp, sres;
|
||||
Mp = Mpro / 100.0f;
|
||||
Ciecam02::curvecolorfloat (mchr, Mp, sres, 2.5f);
|
||||
@ -2140,7 +2182,7 @@ void ImProcFunctions::ciecam_02float (CieImage* ncie, float adap, int begh, int
|
||||
Qpro = (Qpro == 0.f ? epsil : Qpro); // avoid division by zero
|
||||
spro = 100.0f * sqrtf ( Mpro / Qpro );
|
||||
} else { /*if(alg == 3) */
|
||||
Qpro = CAMBrightCurveQ[ (float) (Qpro * coefQ)]; //brightness and contrast
|
||||
Qpro = CAMBrightCurveQ[ (float) (Qpro * coefQ)] / coefQ; //brightness and contrast
|
||||
|
||||
float Mp, sres;
|
||||
Mp = Mpro / 100.0f;
|
||||
@ -2217,6 +2259,7 @@ void ImProcFunctions::ciecam_02float (CieImage* ncie, float adap, int begh, int
|
||||
} else if (curveMode == ColorAppearanceParams::TC_MODE_BRIGHT) {
|
||||
//attention! Brightness curves are open - unlike Lightness or Lab or RGB==> rendering and algoritms will be different
|
||||
float coef = ((aw + 4.f) * (4.f / c)) / 100.f;
|
||||
float Qanc = Qpro;
|
||||
float Qq = (float) Qpro * 327.68f * (1.f / coef);
|
||||
float Qold100 = (float) Qpro / coef;
|
||||
|
||||
@ -2242,8 +2285,13 @@ void ImProcFunctions::ciecam_02float (CieImage* ncie, float adap, int begh, int
|
||||
Qq = 0.7f * (Qq - Qold) + Qold; // not zero ==>artifacts
|
||||
}
|
||||
|
||||
Qpro = (float) (Qq * (coef) / 327.68f);
|
||||
Jpro = 100.f * (Qpro * Qpro) / ((4.0f / c) * (4.0f / c) * (aw + 4.0f) * (aw + 4.0f));
|
||||
if (Qold == 0.f) {
|
||||
Qold = 0.001f;
|
||||
}
|
||||
|
||||
Qpro = Qanc * (Qq / Qold);
|
||||
// Jpro = 100.f * (Qpro * Qpro) / ((4.0f / c) * (4.0f / c) * (aw + 4.0f) * (aw + 4.0f));
|
||||
Jpro = Jpro * SQR (Qq / Qold);
|
||||
|
||||
if (Jpro < 1.f) {
|
||||
Jpro = 1.f;
|
||||
@ -2291,6 +2339,8 @@ void ImProcFunctions::ciecam_02float (CieImage* ncie, float adap, int begh, int
|
||||
}
|
||||
|
||||
} else if (curveMode2 == ColorAppearanceParams::TC_MODE_BRIGHT) { //
|
||||
float Qanc = Qpro;
|
||||
|
||||
float coef = ((aw + 4.f) * (4.f / c)) / 100.f;
|
||||
float Qq = (float) Qpro * 327.68f * (1.f / coef);
|
||||
float Qold100 = (float) Qpro / coef;
|
||||
@ -2317,8 +2367,15 @@ void ImProcFunctions::ciecam_02float (CieImage* ncie, float adap, int begh, int
|
||||
Qq = 0.7f * (Qq - Qold) + Qold; // not zero ==>artifacts
|
||||
}
|
||||
|
||||
Qpro = (float) (Qq * (coef) / 327.68f);
|
||||
Jpro = 100.f * (Qpro * Qpro) / ((4.0f / c) * (4.0f / c) * (aw + 4.0f) * (aw + 4.0f));
|
||||
if (Qold == 0.f) {
|
||||
Qold = 0.001f;
|
||||
}
|
||||
|
||||
// Qpro = (float) (Qq * (coef) / 327.68f);
|
||||
Qpro = Qanc * (Qq / Qold);
|
||||
Jpro = Jpro * SQR (Qq / Qold);
|
||||
|
||||
// Jpro = 100.f * (Qpro * Qpro) / ((4.0f / c) * (4.0f / c) * (aw + 4.0f) * (aw + 4.0f));
|
||||
|
||||
if (t1L) { //to workaround the problem if we modify curve1-lightnees after curve2 brightness(the cat that bites its own tail!) in fact it's another type of curve only for this case
|
||||
coef = 2.f; //adapt Q to J approximation
|
||||
|
@ -54,9 +54,13 @@ class ImProcFunctions
|
||||
|
||||
void calcVignettingParams (int oW, int oH, const VignettingParams& vignetting, double &w2, double &h2, double& maxRadius, double &v, double &b, double &mul);
|
||||
|
||||
void transformPreview (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const LCPMapper *pLCPMap);
|
||||
enum TransformMode {
|
||||
TRANSFORM_PREVIEW,
|
||||
TRANSFORM_HIGH_QUALITY,
|
||||
TRANSFORM_HIGH_QUALITY_FULLIMAGE
|
||||
};
|
||||
void transformLuminanceOnly (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int oW, int oH, int fW, int fH);
|
||||
void transformHighQuality (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const LCPMapper *pLCPMap, bool fullImage);
|
||||
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);
|
||||
@ -70,6 +74,7 @@ class ImProcFunctions
|
||||
bool needsGradient ();
|
||||
bool needsVignetting ();
|
||||
bool needsLCP ();
|
||||
bool needsLensfun();
|
||||
// static cmsUInt8Number* Mempro = NULL;
|
||||
|
||||
|
||||
@ -236,8 +241,7 @@ public:
|
||||
void colorCurve (LabImage* lold, LabImage* lnew);
|
||||
void sharpening (LabImage* lab, float** buffer, SharpeningParams &sharpenParam);
|
||||
void sharpeningcam (CieImage* ncie, float** buffer);
|
||||
void transform (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH,
|
||||
double focalLen, double focalLen35mm, float focusDist, double fNumber, int rawRotationDeg, bool fullImage);
|
||||
void transform (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const ImageMetaData *metadata, int rawRotationDeg, bool fullImage);
|
||||
float resizeScale (const ProcParams* params, int fw, int fh, int &imw, int &imh);
|
||||
void lab2monitorRgb (LabImage* lab, Image8* image);
|
||||
void resize (Image16* src, Image16* dst, float dScale);
|
||||
@ -381,11 +385,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,18 +87,6 @@ float normn (float a, float b, int n)
|
||||
}
|
||||
|
||||
|
||||
void correct_distortion(const rtengine::LCPMapper *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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace rtengine
|
||||
@ -107,7 +96,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;
|
||||
@ -157,7 +146,7 @@ bool ImProcFunctions::transCoord (int W, int H, const std::vector<Coord2D> &src,
|
||||
double x_d = src[i].x, y_d = src[i].y;
|
||||
|
||||
if (pLCPMap && params->lensProf.useDist) {
|
||||
correct_distortion (pLCPMap, x_d, y_d, 0, 0, ascale);
|
||||
pLCPMap->correctDistortion(x_d, y_d, 0, 0, ascale);
|
||||
} else {
|
||||
x_d *= ascale;
|
||||
y_d *= ascale;
|
||||
@ -209,7 +198,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;
|
||||
|
||||
@ -307,32 +296,44 @@ bool ImProcFunctions::transCoord (int W, int H, int x, int y, int w, int h, int&
|
||||
}
|
||||
|
||||
void ImProcFunctions::transform (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH,
|
||||
double focalLen, double focalLen35mm, float focusDist, double fNumber, int rawRotationDeg, bool fullImage)
|
||||
const ImageMetaData *metadata,
|
||||
int rawRotationDeg, bool fullImage)
|
||||
{
|
||||
double focalLen = metadata->getFocalLen();
|
||||
double focalLen35mm = metadata->getFocalLen35mm();
|
||||
float focusDist = metadata->getFocusDist();
|
||||
double fNumber = metadata->getFNumber();
|
||||
|
||||
LCPMapper *pLCPMap = nullptr;
|
||||
std::unique_ptr<const LensCorrection> pLCPMap;
|
||||
|
||||
if (needsLCP()) { // don't check focal length to allow distortion correction for lenses without chip
|
||||
LCPProfile *pLCPProf = lcpStore->getProfile (params->lensProf.lcpFile);
|
||||
if (needsLensfun()) {
|
||||
pLCPMap = std::move(LFDatabase::findModifier(params->lensProf, metadata, oW, oH, params->coarse, rawRotationDeg));
|
||||
} else if (needsLCP()) { // don't check focal length to allow distortion correction for lenses without chip
|
||||
const std::shared_ptr<LCPProfile> pLCPProf = LCPStore::getInstance()->getProfile (params->lensProf.lcpFile);
|
||||
|
||||
if (pLCPProf) {
|
||||
pLCPMap = new LCPMapper (pLCPProf, focalLen, focalLen35mm,
|
||||
pLCPMap.reset(
|
||||
new LCPMapper (pLCPProf, focalLen, focalLen35mm,
|
||||
focusDist, fNumber, false,
|
||||
params->lensProf.useDist,
|
||||
oW, oH, params->coarse, rawRotationDeg);
|
||||
oW, oH, params->coarse, rawRotationDeg
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
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 if (!needsCA() && scale != 1) {
|
||||
transformPreview (original, transformed, cx, cy, sx, sy, oW, oH, fW, fH, pLCPMap);
|
||||
} else {
|
||||
transformHighQuality (original, transformed, cx, cy, sx, sy, oW, oH, fW, fH, pLCPMap, fullImage);
|
||||
TransformMode mode;
|
||||
if (!needsCA() && scale != 1) {
|
||||
mode = TRANSFORM_PREVIEW;
|
||||
} else if (!fullImage) {
|
||||
mode = TRANSFORM_HIGH_QUALITY;
|
||||
} else {
|
||||
mode = TRANSFORM_HIGH_QUALITY_FULLIMAGE;
|
||||
}
|
||||
|
||||
if (pLCPMap) {
|
||||
delete pLCPMap;
|
||||
transformGeneral(mode, original, transformed, cx, cy, sx, sy, oW, oH, fW, fH, pLCPMap.get());
|
||||
}
|
||||
}
|
||||
|
||||
@ -721,9 +722,8 @@ void ImProcFunctions::transformLuminanceOnly (Imagefloat* original, Imagefloat*
|
||||
}
|
||||
}
|
||||
|
||||
// Transform WITH scaling (opt.) and CA, cubic interpolation
|
||||
void ImProcFunctions::transformHighQuality (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH,
|
||||
const LCPMapper *pLCPMap, bool fullImage)
|
||||
|
||||
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;
|
||||
@ -781,17 +781,38 @@ void ImProcFunctions::transformHighQuality (Imagefloat* original, Imagefloat* tr
|
||||
oH * tan (hpalpha) * sqrt (SQR (4 * maxRadius) + SQR (oH * tan (hpalpha)))) / (SQR (maxRadius) * 8)));
|
||||
double hpcospt = (hpdeg >= 0 ? 1.0 : -1.0) * cos (hpteta), hptanpt = tan (hpteta);
|
||||
|
||||
double ascale = params->commonTrans.autofill ? getTransformAutoFill (oW, oH, true /*fullImage*/ ? pLCPMap : nullptr) : 1.0;
|
||||
double ascale = params->commonTrans.autofill ? getTransformAutoFill (oW, oH, pLCPMap) : 1.0;
|
||||
|
||||
// smaller crop images are a problem, so only when processing fully
|
||||
bool enableLCPCA = pLCPMap && params->lensProf.useCA && fullImage && pLCPMap->enableCA;
|
||||
bool enableLCPDist = pLCPMap && params->lensProf.useDist; // && fullImage;
|
||||
bool enableLCPCA = false;
|
||||
bool enableLCPDist = false;
|
||||
bool enableCA = false;
|
||||
|
||||
switch (mode) {
|
||||
case ImProcFunctions::TRANSFORM_HIGH_QUALITY_FULLIMAGE: {
|
||||
enableLCPCA = pLCPMap && params->lensProf.useCA && pLCPMap->isCACorrectionAvailable();
|
||||
}
|
||||
//no break on purpose
|
||||
|
||||
case ImProcFunctions::TRANSFORM_HIGH_QUALITY: {
|
||||
enableLCPDist = pLCPMap && params->lensProf.useDist;
|
||||
if (enableLCPCA) {
|
||||
enableLCPDist = false;
|
||||
}
|
||||
enableCA = enableLCPCA || needsCA();
|
||||
}
|
||||
//no break on purpose
|
||||
|
||||
bool enableCA = enableLCPCA || needsCA();
|
||||
default:
|
||||
case ImProcFunctions::TRANSFORM_PREVIEW: {
|
||||
enableLCPDist = pLCPMap && params->lensProf.useDist;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!enableCA) {
|
||||
chDist[0] = 0.0;
|
||||
}
|
||||
|
||||
// main cycle
|
||||
bool darkening = (params->vignetting.amount <= 0.0);
|
||||
@ -802,7 +823,7 @@ void ImProcFunctions::transformHighQuality (Imagefloat* original, Imagefloat* tr
|
||||
double x_d = x, y_d = y;
|
||||
|
||||
if (enableLCPDist) {
|
||||
correct_distortion(pLCPMap, x_d, y_d, cx, cy, ascale); // must be first transform
|
||||
pLCPMap->correctDistortion(x_d, y_d, cx, cy, ascale); // must be first transform
|
||||
} else {
|
||||
x_d *= ascale;
|
||||
y_d *= ascale;
|
||||
@ -895,6 +916,10 @@ void ImProcFunctions::transformHighQuality (Imagefloat* original, Imagefloat* tr
|
||||
// all interpolation pixels inside image
|
||||
if (enableCA) {
|
||||
interpolateTransformChannelsCubic (chOrig[c], xc - 1, yc - 1, Dx, Dy, & (chTrans[c][y][x]), vignmul);
|
||||
} else if (mode == ImProcFunctions::TRANSFORM_PREVIEW) {
|
||||
transformed->r (y, x) = vignmul * (original->r (yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->r (yc, xc + 1) * Dx * (1.0 - Dy) + original->r (yc + 1, xc) * (1.0 - Dx) * Dy + original->r (yc + 1, xc + 1) * Dx * Dy);
|
||||
transformed->g (y, x) = vignmul * (original->g (yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->g (yc, xc + 1) * Dx * (1.0 - Dy) + original->g (yc + 1, xc) * (1.0 - Dx) * Dy + original->g (yc + 1, xc + 1) * Dx * Dy);
|
||||
transformed->b (y, x) = vignmul * (original->b (yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->b (yc, xc + 1) * Dx * (1.0 - Dy) + original->b (yc + 1, xc) * (1.0 - Dx) * Dy + original->b (yc + 1, xc + 1) * Dx * Dy);
|
||||
} else {
|
||||
interpolateTransformCubic (original, xc - 1, yc - 1, Dx, Dy, & (transformed->r (y, x)), & (transformed->g (y, x)), & (transformed->b (y, x)), vignmul);
|
||||
}
|
||||
@ -928,168 +953,8 @@ void ImProcFunctions::transformHighQuality (Imagefloat* original, Imagefloat* tr
|
||||
}
|
||||
}
|
||||
|
||||
// Transform WITH scaling, WITHOUT CA, simple (and fast) interpolation. Used for preview
|
||||
void ImProcFunctions::transformPreview (Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const LCPMapper *pLCPMap)
|
||||
{
|
||||
|
||||
double w2 = (double) oW / 2.0 - 0.5;
|
||||
double h2 = (double) oH / 2.0 - 0.5;
|
||||
|
||||
double vig_w2, vig_h2, maxRadius, v, b, mul;
|
||||
calcVignettingParams (oW, oH, params->vignetting, vig_w2, vig_h2, maxRadius, v, b, mul);
|
||||
|
||||
struct grad_params gp;
|
||||
|
||||
if (needsGradient()) {
|
||||
calcGradientParams (oW, oH, params->gradient, gp);
|
||||
}
|
||||
|
||||
struct pcv_params pcv;
|
||||
|
||||
if (needsPCVignetting()) {
|
||||
calcPCVignetteParams (fW, fH, oW, oH, params->pcvignette, params->crop, pcv);
|
||||
}
|
||||
|
||||
// auxiliary variables for distortion correction
|
||||
bool needsDist = needsDistortion(); // for performance
|
||||
double distAmount = params->distortion.amount;
|
||||
|
||||
// auxiliary variables for rotation
|
||||
double cost = cos (params->rotate.degree * rtengine::RT_PI / 180.0);
|
||||
double sint = sin (params->rotate.degree * rtengine::RT_PI / 180.0);
|
||||
|
||||
// auxiliary variables for vertical perspective correction
|
||||
double vpdeg = params->perspective.vertical / 100.0 * 45.0;
|
||||
double vpalpha = (90 - vpdeg) / 180.0 * rtengine::RT_PI;
|
||||
double vpteta = fabs (vpalpha - rtengine::RT_PI / 2) < 3e-4 ? 0.0 : acos ((vpdeg > 0 ? 1.0 : -1.0) * sqrt ((-oW * oW * tan (vpalpha) * tan (vpalpha) + (vpdeg > 0 ? 1.0 : -1.0) * oW * tan (vpalpha) * sqrt (16 * maxRadius * maxRadius + oW * oW * tan (vpalpha) * tan (vpalpha))) / (maxRadius * maxRadius * 8)));
|
||||
double vpcospt = (vpdeg >= 0 ? 1.0 : -1.0) * cos (vpteta), vptanpt = tan (vpteta);
|
||||
|
||||
// auxiliary variables for horizontal perspective correction
|
||||
double hpdeg = params->perspective.horizontal / 100.0 * 45.0;
|
||||
double hpalpha = (90 - hpdeg) / 180.0 * rtengine::RT_PI;
|
||||
double hpteta = fabs (hpalpha - rtengine::RT_PI / 2) < 3e-4 ? 0.0 : acos ((hpdeg > 0 ? 1.0 : -1.0) * sqrt ((-oH * oH * tan (hpalpha) * tan (hpalpha) + (hpdeg > 0 ? 1.0 : -1.0) * oH * tan (hpalpha) * sqrt (16 * maxRadius * maxRadius + oH * oH * tan (hpalpha) * tan (hpalpha))) / (maxRadius * maxRadius * 8)));
|
||||
double hpcospt = (hpdeg >= 0 ? 1.0 : -1.0) * cos (hpteta), hptanpt = tan (hpteta);
|
||||
|
||||
double ascale = params->commonTrans.autofill ? getTransformAutoFill (oW, oH, pLCPMap) : 1.0;
|
||||
|
||||
bool darkening = (params->vignetting.amount <= 0.0);
|
||||
|
||||
// main cycle
|
||||
#pragma omp parallel for if (multiThread)
|
||||
|
||||
for (int y = 0; y < transformed->getHeight(); y++) {
|
||||
for (int x = 0; x < transformed->getWidth(); x++) {
|
||||
double x_d = x, y_d = y;
|
||||
|
||||
if (pLCPMap && params->lensProf.useDist) {
|
||||
correct_distortion(pLCPMap, x_d, y_d, cx, cy, ascale); // must be first transform
|
||||
} else {
|
||||
x_d *= ascale;
|
||||
y_d *= ascale;
|
||||
}
|
||||
|
||||
x_d += ascale * (cx - w2); // centering x coord & scale
|
||||
y_d += ascale * (cy - h2); // centering y coord & scale
|
||||
|
||||
double vig_x_d = 0., vig_y_d = 0.;
|
||||
|
||||
if (needsVignetting()) {
|
||||
vig_x_d = ascale * (x + cx - vig_w2); // centering x coord & scale
|
||||
vig_y_d = ascale * (y + cy - vig_h2); // centering y coord & scale
|
||||
}
|
||||
|
||||
if (needsPerspective()) {
|
||||
// horizontal perspective transformation
|
||||
y_d *= maxRadius / (maxRadius + x_d * hptanpt);
|
||||
x_d *= maxRadius * hpcospt / (maxRadius + x_d * hptanpt);
|
||||
|
||||
// vertical perspective transformation
|
||||
x_d *= maxRadius / (maxRadius - y_d * vptanpt);
|
||||
y_d *= maxRadius * vpcospt / (maxRadius - y_d * vptanpt);
|
||||
}
|
||||
|
||||
// rotate
|
||||
double Dx = x_d * cost - y_d * sint;
|
||||
double Dy = x_d * sint + y_d * cost;
|
||||
|
||||
// distortion correction
|
||||
double s = 1;
|
||||
|
||||
if (needsDist) {
|
||||
double r = sqrt (Dx * Dx + Dy * Dy) / maxRadius; // sqrt is slow
|
||||
s = 1.0 - distAmount + distAmount * r ;
|
||||
Dx *= s;
|
||||
Dy *= s;
|
||||
}
|
||||
|
||||
double r2 = 0.;
|
||||
|
||||
if (needsVignetting()) {
|
||||
double vig_Dx = vig_x_d * cost - vig_y_d * sint;
|
||||
double vig_Dy = vig_x_d * sint + vig_y_d * cost;
|
||||
r2 = sqrt (vig_Dx * vig_Dx + vig_Dy * vig_Dy);
|
||||
}
|
||||
|
||||
// de-center
|
||||
Dx += w2;
|
||||
Dy += h2;
|
||||
|
||||
// Extract integer and fractions of source screen coordinates
|
||||
int xc = (int)Dx;
|
||||
Dx -= (double)xc;
|
||||
xc -= sx;
|
||||
int yc = (int)Dy;
|
||||
Dy -= (double)yc;
|
||||
yc -= sy;
|
||||
|
||||
// Convert only valid pixels
|
||||
if (yc >= 0 && yc < original->getHeight() && xc >= 0 && xc < original->getWidth()) {
|
||||
|
||||
// multiplier for vignetting correction
|
||||
double vignmul = 1.0;
|
||||
|
||||
if (needsVignetting()) {
|
||||
if (darkening) {
|
||||
vignmul /= std::max (v + mul * tanh (b * (maxRadius - s * r2) / maxRadius), 0.001);
|
||||
} else {
|
||||
vignmul = v + mul * tanh (b * (maxRadius - s * r2) / maxRadius);
|
||||
}
|
||||
}
|
||||
|
||||
if (needsGradient()) {
|
||||
vignmul *= calcGradientFactor (gp, cx + x, cy + y);
|
||||
}
|
||||
|
||||
if (needsPCVignetting()) {
|
||||
vignmul *= calcPCVignetteFactor (pcv, cx + x, cy + y);
|
||||
}
|
||||
|
||||
if (yc < original->getHeight() - 1 && xc < original->getWidth() - 1) {
|
||||
// all interpolation pixels inside image
|
||||
transformed->r (y, x) = vignmul * (original->r (yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->r (yc, xc + 1) * Dx * (1.0 - Dy) + original->r (yc + 1, xc) * (1.0 - Dx) * Dy + original->r (yc + 1, xc + 1) * Dx * Dy);
|
||||
transformed->g (y, x) = vignmul * (original->g (yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->g (yc, xc + 1) * Dx * (1.0 - Dy) + original->g (yc + 1, xc) * (1.0 - Dx) * Dy + original->g (yc + 1, xc + 1) * Dx * Dy);
|
||||
transformed->b (y, x) = vignmul * (original->b (yc, xc) * (1.0 - Dx) * (1.0 - Dy) + original->b (yc, xc + 1) * Dx * (1.0 - Dy) + original->b (yc + 1, xc) * (1.0 - Dx) * Dy + original->b (yc + 1, xc + 1) * Dx * Dy);
|
||||
} else {
|
||||
// edge pixels
|
||||
int y1 = LIM (yc, 0, original->getHeight() - 1);
|
||||
int y2 = LIM (yc + 1, 0, original->getHeight() - 1);
|
||||
int x1 = LIM (xc, 0, original->getWidth() - 1);
|
||||
int x2 = LIM (xc + 1, 0, original->getWidth() - 1);
|
||||
transformed->r (y, x) = vignmul * (original->r (y1, x1) * (1.0 - Dx) * (1.0 - Dy) + original->r (y1, x2) * Dx * (1.0 - Dy) + original->r (y2, x1) * (1.0 - Dx) * Dy + original->r (y2, x2) * Dx * Dy);
|
||||
transformed->g (y, x) = vignmul * (original->g (y1, x1) * (1.0 - Dx) * (1.0 - Dy) + original->g (y1, x2) * Dx * (1.0 - Dy) + original->g (y2, x1) * (1.0 - Dx) * Dy + original->g (y2, x2) * Dx * Dy);
|
||||
transformed->b (y, x) = vignmul * (original->b (y1, x1) * (1.0 - Dx) * (1.0 - Dy) + original->b (y1, x2) * Dx * (1.0 - Dy) + original->b (y2, x1) * (1.0 - Dx) * Dy + original->b (y2, x2) * Dx * Dy);
|
||||
}
|
||||
} else {
|
||||
// not valid (source pixel x,y not inside source image, etc.)
|
||||
transformed->r (y, x) = 0;
|
||||
transformed->g (y, x) = 0;
|
||||
transformed->b (y, x) = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
@ -1150,12 +1015,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();
|
||||
}
|
||||
|
||||
|
||||
|
1617
rtengine/lcp.cc
1617
rtengine/lcp.cc
File diff suppressed because it is too large
Load Diff
170
rtengine/lcp.h
170
rtengine/lcp.h
@ -21,27 +21,45 @@
|
||||
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include <glibmm.h>
|
||||
#include <expat.h>
|
||||
|
||||
#include "cache.h"
|
||||
#include "imagefloat.h"
|
||||
#include "opthelper.h"
|
||||
|
||||
namespace rtengine
|
||||
{
|
||||
|
||||
enum class LCPCorrectionMode {
|
||||
VIGNETTE,
|
||||
DISTORTION,
|
||||
CA
|
||||
};
|
||||
|
||||
// Perspective model common data, also used for Vignette and Fisheye
|
||||
class LCPModelCommon final
|
||||
{
|
||||
public:
|
||||
LCPModelCommon();
|
||||
|
||||
bool empty() const; // is it empty
|
||||
void print() const; // printf all values
|
||||
void merge(const LCPModelCommon& a, const LCPModelCommon& b, float facA);
|
||||
void prepareParams(int fullWidth, int fullHeight, float focalLength, float focalLength35mm, float sensorFormatFactor, bool swapXY, bool mirrorX, bool mirrorY);
|
||||
void prepareParams(
|
||||
int fullWidth,
|
||||
int fullHeight,
|
||||
float focalLength,
|
||||
float focalLength35mm,
|
||||
float sensorFormatFactor,
|
||||
bool swapXY,
|
||||
bool mirrorX,
|
||||
bool mirrorY
|
||||
);
|
||||
|
||||
//private:
|
||||
using Param = std::array<float, 5>;
|
||||
@ -66,97 +84,125 @@ public:
|
||||
VignParam vign_param;
|
||||
};
|
||||
|
||||
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();
|
||||
bool hasModeData(int mode) const;
|
||||
void print() const;
|
||||
};
|
||||
|
||||
|
||||
class LCPProfile
|
||||
{
|
||||
// Temporary data for parsing
|
||||
bool inCamProfiles, firstLIDone, inPerspect, inAlternateLensID, inAlternateLensNames;
|
||||
char lastTag[256], inInvalidTag[256];
|
||||
LCPPersModel* pCurPersModel;
|
||||
LCPModelCommon* pCurCommon;
|
||||
public:
|
||||
explicit LCPProfile(const Glib::ustring& fname);
|
||||
~LCPProfile();
|
||||
|
||||
void calcParams(
|
||||
LCPCorrectionMode mode,
|
||||
float focalLength,
|
||||
float focusDist,
|
||||
float aperture,
|
||||
LCPModelCommon* pCorr1,
|
||||
LCPModelCommon* pCorr2,
|
||||
LCPModelCommon *pCorr3
|
||||
) const; // Interpolates between the persModels frames
|
||||
|
||||
void print() const;
|
||||
|
||||
//private:
|
||||
// Common data
|
||||
Glib::ustring profileName;
|
||||
Glib::ustring lensPrettyName;
|
||||
Glib::ustring cameraPrettyName;
|
||||
Glib::ustring lens;
|
||||
Glib::ustring camera; // lens/camera(=model) can be auto-matched with DNG
|
||||
bool isRaw;
|
||||
bool isFisheye;
|
||||
float sensorFormatFactor;
|
||||
int persModelCount;
|
||||
|
||||
private:
|
||||
class LCPPersModel;
|
||||
|
||||
int filterBadFrames(LCPCorrectionMode mode, double maxAvgDevFac, int minFramesLeft);
|
||||
|
||||
void handle_text(const std::string& text);
|
||||
|
||||
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);
|
||||
|
||||
int filterBadFrames(double maxAvgDevFac, int minFramesLeft);
|
||||
// Temporary data for parsing
|
||||
bool inCamProfiles;
|
||||
bool firstLIDone;
|
||||
bool inPerspect;
|
||||
bool inAlternateLensID;
|
||||
bool inAlternateLensNames;
|
||||
char lastTag[256];
|
||||
char inInvalidTag[256];
|
||||
LCPPersModel* pCurPersModel;
|
||||
LCPModelCommon* pCurCommon;
|
||||
|
||||
void handle_text(std::string text);
|
||||
std::ostringstream textbuf;
|
||||
|
||||
public:
|
||||
// Common data
|
||||
Glib::ustring profileName, lensPrettyName, cameraPrettyName, lens, camera; // lens/camera(=model) can be auto-matched with DNG
|
||||
bool isRaw, isFisheye;
|
||||
float sensorFormatFactor;
|
||||
int persModelCount;
|
||||
|
||||
// The correction frames
|
||||
static const int MaxPersModelCount = 3000;
|
||||
static constexpr int MaxPersModelCount = 3000;
|
||||
LCPPersModel* aPersModel[MaxPersModelCount]; // Do NOT use std::list or something, it's buggy in GCC!
|
||||
|
||||
explicit LCPProfile(const Glib::ustring &fname);
|
||||
~LCPProfile();
|
||||
|
||||
void calcParams(int mode, float focalLength, float focusDist, float aperture, LCPModelCommon *pCorr1, LCPModelCommon *pCorr2, LCPModelCommon *pCorr3) const; // Interpolates between the persModels frames
|
||||
|
||||
void print() const;
|
||||
};
|
||||
|
||||
class LCPStore
|
||||
{
|
||||
MyMutex mtx;
|
||||
public:
|
||||
static LCPStore* getInstance();
|
||||
|
||||
bool isValidLCPFileName(const Glib::ustring& filename) const;
|
||||
std::shared_ptr<LCPProfile> getProfile(const Glib::ustring& filename) const;
|
||||
Glib::ustring getDefaultCommonDirectory() const;
|
||||
|
||||
private:
|
||||
LCPStore(unsigned int _cache_size = 32);
|
||||
|
||||
// Maps file name to profile as cache
|
||||
std::map<Glib::ustring, LCPProfile*> profileCache;
|
||||
|
||||
public:
|
||||
~LCPStore();
|
||||
Glib::ustring getDefaultCommonDirectory() const;
|
||||
bool isValidLCPFileName(Glib::ustring filename) const;
|
||||
LCPProfile* getProfile(Glib::ustring filename);
|
||||
|
||||
static LCPStore* getInstance();
|
||||
mutable Cache<Glib::ustring, std::shared_ptr<LCPProfile>> cache;
|
||||
};
|
||||
|
||||
#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 isCACorrectionAvailable() 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
|
||||
{
|
||||
public:
|
||||
// Precalculates the mapper
|
||||
LCPMapper(
|
||||
const std::shared_ptr<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, int cx, int cy, double scale) const; // MUST be the first stage
|
||||
bool isCACorrectionAvailable() const;
|
||||
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:
|
||||
bool enableCA; // is the mapper capable if CA correction?
|
||||
bool useCADist; // should the distortion in the CA info be used?
|
||||
bool swapXY;
|
||||
LCPModelCommon mc;
|
||||
LCPModelCommon chrom[3]; // in order RedGreen/Green/BlueGreen
|
||||
bool isFisheye;
|
||||
|
||||
public:
|
||||
bool enableCA; // is the mapper capable if CA correction?
|
||||
|
||||
// precalculates the mapper.
|
||||
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 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;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -511,94 +511,97 @@ enum ProcEvent {
|
||||
EvCATgreensc = 481,
|
||||
EvCATybscen = 482,
|
||||
EvCATAutoyb = 483,
|
||||
EvlocallabEnabled = 484,
|
||||
EvlocallablocY = 485,
|
||||
EvlocallablocX = 486,
|
||||
EvlocallabCenter = 487,
|
||||
EvlocallabDegree = 488,
|
||||
Evlocallablightness = 489,
|
||||
Evlocallabcontrast = 490,
|
||||
Evlocallabchroma = 491,
|
||||
Evlocallabtransit = 492,
|
||||
Evlocallabavoid = 493,
|
||||
EvlocallablocYT = 494,
|
||||
EvlocallablocXL = 495,
|
||||
EvlocallabSmet = 496,
|
||||
Evlocallabinvers = 497,
|
||||
Evlocallabradius = 498,
|
||||
Evlocallabinversrad = 499,
|
||||
Evlocallabstrength = 500,
|
||||
Evlocallabsensi = 501,
|
||||
EvlocallabretinexMethod = 502,
|
||||
Evlocallabstr = 503,
|
||||
Evlocallabneigh = 504,
|
||||
Evlocallabvart = 505,
|
||||
EvlocallabCTgainCurve = 506,
|
||||
Evlocallabchrrt = 507,
|
||||
Evlocallabinversret = 508,
|
||||
Evlocallabsensih = 509,
|
||||
Evlocallabnbspot = 510,
|
||||
Evlocallabactivlum = 511,
|
||||
Evlocallabanbspot = 512,
|
||||
Evlocallabsharradius = 513,
|
||||
Evlocallabsharamount = 514,
|
||||
Evlocallabshardamping = 515,
|
||||
Evlocallabshariter = 516,
|
||||
Evlocallabsensis = 517,
|
||||
Evlocallabinverssha = 518,
|
||||
Evlocallabcircrad = 519,
|
||||
Evlocallabthres = 520,
|
||||
Evlocallabproxi = 521,
|
||||
EvlocallabqualityMethod = 522,
|
||||
Evlocallabnoiselumf = 523,
|
||||
Evlocallabnoiselumc = 524,
|
||||
Evlocallabnoisechrof = 525,
|
||||
Evlocallabnoisechroc = 526,
|
||||
EvlocallabThresho = 527,
|
||||
EvlocallabEqualizer = 528,
|
||||
Evlocallabsensicb = 529,
|
||||
Evlocallabsensibn = 530,
|
||||
Evlocallabstren = 531,
|
||||
Evlocallabgamma = 532,
|
||||
Evlocallabestop = 533,
|
||||
Evlocallabscaltm = 534,
|
||||
Evlocallabrewei = 535,
|
||||
Evlocallabsensitm = 536,
|
||||
EvlocallabCTgainCurverab = 537,
|
||||
Evlocallabretrab = 538,
|
||||
Evlocallabllshape = 539,
|
||||
EvLocenacolor = 540,
|
||||
EvLocenablur = 541,
|
||||
EvLocenatonemap = 542,
|
||||
EvLocenareti = 543,
|
||||
EvLocenasharp = 544,
|
||||
EvLocenacbdl = 545,
|
||||
EvLocenadenoi = 546,
|
||||
EvlocallabLHshape = 547,
|
||||
Evlocallabcurvactiv = 548,
|
||||
Evlocallabccshape = 549,
|
||||
EvlocallabqualitycurveMethod = 550,
|
||||
Evlocallabhueref = 551,
|
||||
Evlocallabchromaref = 552,
|
||||
Evlocallablumaref = 553,
|
||||
EvlocallabHHshape = 554,
|
||||
EvLocenavibrance = 555,
|
||||
EvlocallabSkinTonesCurve = 556,
|
||||
EvlocallabProtectSkins = 557,
|
||||
EvlocallabAvoidColorShift = 558,
|
||||
EvlocallabPastSatTog = 559,
|
||||
EvlocallabPastels = 560,
|
||||
EvlocallabSaturated = 561,
|
||||
EvlocallabPastSatThreshold = 562,
|
||||
Evlocallabsensiv = 563,
|
||||
EvLocenaexpose = 564,
|
||||
Evlocallabexpcomp = 565,
|
||||
Evlocallabhlcompr = 566,
|
||||
Evlocallabhlcomprthresh = 567,
|
||||
Evlocallabblack = 568,
|
||||
Evlocallabshcompr = 569,
|
||||
Evlocallabsensiex = 570,
|
||||
Evlocallabshape = 571,
|
||||
EvLensCorrMode = 484,
|
||||
EvLensCorrLensfunCamera = 485,
|
||||
EvLensCorrLensfunLens = 486,
|
||||
EvlocallabEnabled = 487,
|
||||
EvlocallablocY = 488,
|
||||
EvlocallablocX = 489,
|
||||
EvlocallabCenter = 490,
|
||||
EvlocallabDegree = 491,
|
||||
Evlocallablightness = 492,
|
||||
Evlocallabcontrast = 493,
|
||||
Evlocallabchroma = 494,
|
||||
Evlocallabtransit = 495,
|
||||
Evlocallabavoid = 496,
|
||||
EvlocallablocYT = 497,
|
||||
EvlocallablocXL = 498,
|
||||
EvlocallabSmet = 499,
|
||||
Evlocallabinvers = 500,
|
||||
Evlocallabradius = 501,
|
||||
Evlocallabinversrad = 502,
|
||||
Evlocallabstrength = 503,
|
||||
Evlocallabsensi = 504,
|
||||
EvlocallabretinexMethod = 505,
|
||||
Evlocallabstr = 506,
|
||||
Evlocallabneigh = 507,
|
||||
Evlocallabvart = 508,
|
||||
EvlocallabCTgainCurve = 509,
|
||||
Evlocallabchrrt = 510,
|
||||
Evlocallabinversret = 511,
|
||||
Evlocallabsensih = 512,
|
||||
Evlocallabnbspot = 513,
|
||||
Evlocallabactivlum = 514,
|
||||
Evlocallabanbspot = 515,
|
||||
Evlocallabsharradius = 516,
|
||||
Evlocallabsharamount = 517,
|
||||
Evlocallabshardamping = 518,
|
||||
Evlocallabshariter = 519,
|
||||
Evlocallabsensis = 520,
|
||||
Evlocallabinverssha = 521,
|
||||
Evlocallabcircrad = 522,
|
||||
Evlocallabthres = 523,
|
||||
Evlocallabproxi = 524,
|
||||
EvlocallabqualityMethod = 525,
|
||||
Evlocallabnoiselumf = 526,
|
||||
Evlocallabnoiselumc = 527,
|
||||
Evlocallabnoisechrof = 528,
|
||||
Evlocallabnoisechroc = 529,
|
||||
EvlocallabThresho = 530,
|
||||
EvlocallabEqualizer = 531,
|
||||
Evlocallabsensicb = 532,
|
||||
Evlocallabsensibn = 533,
|
||||
Evlocallabstren = 534,
|
||||
Evlocallabgamma = 535,
|
||||
Evlocallabestop = 536,
|
||||
Evlocallabscaltm = 537,
|
||||
Evlocallabrewei = 538,
|
||||
Evlocallabsensitm = 539,
|
||||
EvlocallabCTgainCurverab = 540,
|
||||
Evlocallabretrab = 541,
|
||||
Evlocallabllshape = 542,
|
||||
EvLocenacolor = 543,
|
||||
EvLocenablur = 544,
|
||||
EvLocenatonemap = 545,
|
||||
EvLocenareti = 546,
|
||||
EvLocenasharp = 547,
|
||||
EvLocenacbdl = 548,
|
||||
EvLocenadenoi = 549,
|
||||
EvlocallabLHshape = 550,
|
||||
Evlocallabcurvactiv = 551,
|
||||
Evlocallabccshape = 552,
|
||||
EvlocallabqualitycurveMethod = 553,
|
||||
Evlocallabhueref = 554,
|
||||
Evlocallabchromaref = 555,
|
||||
Evlocallablumaref = 556,
|
||||
EvlocallabHHshape = 557,
|
||||
EvLocenavibrance = 558,
|
||||
EvlocallabSkinTonesCurve = 559,
|
||||
EvlocallabProtectSkins = 560,
|
||||
EvlocallabAvoidColorShift = 561,
|
||||
EvlocallabPastSatTog = 562,
|
||||
EvlocallabPastels = 563,
|
||||
EvlocallabSaturated = 564,
|
||||
EvlocallabPastSatThreshold = 565,
|
||||
Evlocallabsensiv = 566,
|
||||
EvLocenaexpose = 567,
|
||||
Evlocallabexpcomp = 568,
|
||||
Evlocallabhlcompr = 569,
|
||||
Evlocallabhlcomprthresh = 570,
|
||||
Evlocallabblack = 571,
|
||||
Evlocallabshcompr = 572,
|
||||
Evlocallabsensiex = 573,
|
||||
Evlocallabshape = 574,
|
||||
|
||||
NUMOFEVENTS
|
||||
|
||||
|
@ -922,6 +922,11 @@ void LensProfParams::setDefaults()
|
||||
lcpFile = "";
|
||||
useDist = useVign = true;
|
||||
useCA = false;
|
||||
useLensfun = false;
|
||||
lfAutoMatch = true;
|
||||
lfCameraMake = "";
|
||||
lfCameraModel = "";
|
||||
lfLens = "";
|
||||
}
|
||||
|
||||
void CoarseTransformParams::setDefaults()
|
||||
@ -2827,6 +2832,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);
|
||||
@ -7197,6 +7218,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
|
||||
@ -9813,6 +9869,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
|
||||
|
@ -836,6 +836,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()
|
||||
{
|
||||
@ -844,6 +849,7 @@ public:
|
||||
void setDefaults();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Parameters of the perspective correction
|
||||
*/
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "dcp.h"
|
||||
#include "rt_math.h"
|
||||
#include "improcfun.h"
|
||||
#include "rtlensfun.h"
|
||||
#ifdef _OPENMP
|
||||
#include <omp.h>
|
||||
#endif
|
||||
@ -1863,11 +1864,19 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le
|
||||
|
||||
// Correct vignetting of lens profile
|
||||
if (!hasFlatField && lensProf.useVign) {
|
||||
LCPProfile *pLCPProf = lcpStore->getProfile (lensProf.lcpFile);
|
||||
std::unique_ptr<LensCorrection> pmap;
|
||||
if (lensProf.useLensfun) {
|
||||
pmap = std::move(LFDatabase::findModifier(lensProf, idata, W, H, coarse, -1));
|
||||
} else {
|
||||
const std::shared_ptr<LCPProfile> pLCPProf = LCPStore::getInstance()->getProfile(lensProf.lcpFile);
|
||||
|
||||
if (pLCPProf) { // don't check focal length to allow distortion correction for lenses without chip, also pass dummy focal length 1 in case of 0
|
||||
LCPMapper map (pLCPProf, max (idata->getFocalLen(), 1.0), idata->getFocalLen35mm(), idata->getFocusDist(), idata->getFNumber(), true, false, W, H, coarse, -1);
|
||||
pmap.reset(new LCPMapper(pLCPProf, max(idata->getFocalLen(), 1.0), idata->getFocalLen35mm(), idata->getFocusDist(), idata->getFNumber(), true, false, W, H, coarse, -1));
|
||||
}
|
||||
}
|
||||
|
||||
if (pmap) {
|
||||
LensCorrection &map = *pmap;
|
||||
if (ri->getSensorType() == ST_BAYER || ri->getSensorType() == ST_FUJI_XTRANS || ri->get_colors() == 1) {
|
||||
if (numFrames == 4) {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
@ -1921,41 +1930,15 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le
|
||||
}
|
||||
}
|
||||
|
||||
// check if it is an olympus E camera, if yes, compute G channel pre-compensation factors
|
||||
// check if it is an olympus E camera or green equilibration is enabled. If yes, compute G channel pre-compensation factors
|
||||
if ( ri->getSensorType() == ST_BAYER && (raw.bayersensor.greenthresh || (((idata->getMake().size() >= 7 && idata->getMake().substr(0, 7) == "OLYMPUS" && idata->getModel()[0] == 'E') || (idata->getMake().size() >= 9 && idata->getMake().substr(0, 9) == "Panasonic")) && raw.bayersensor.method != RAWParams::BayerSensor::methodstring[ RAWParams::BayerSensor::vng4])) ) {
|
||||
// global correction
|
||||
int ng1 = 0, ng2 = 0, i = 0;
|
||||
double avgg1 = 0., avgg2 = 0.;
|
||||
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for default(shared) private(i) reduction(+: ng1, ng2, avgg1, avgg2)
|
||||
#endif
|
||||
|
||||
for (i = border; i < H - border; i++)
|
||||
for (int j = border; j < W - border; j++)
|
||||
if (ri->ISGREEN (i, j)) {
|
||||
if (i & 1) {
|
||||
avgg2 += rawData[i][j];
|
||||
ng2++;
|
||||
if(numFrames == 4) {
|
||||
for(int i = 0; i < 4; ++i) {
|
||||
green_equilibrate_global(*rawDataFrames[i]);
|
||||
}
|
||||
} else {
|
||||
avgg1 += rawData[i][j];
|
||||
ng1++;
|
||||
}
|
||||
}
|
||||
|
||||
double corrg1 = ((double)avgg1 / ng1 + (double)avgg2 / ng2) / 2.0 / ((double)avgg1 / ng1);
|
||||
double corrg2 = ((double)avgg1 / ng1 + (double)avgg2 / ng2) / 2.0 / ((double)avgg2 / ng2);
|
||||
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for default(shared)
|
||||
#endif
|
||||
|
||||
for (int i = border; i < H - border; i++)
|
||||
for (int j = border; j < W - border; j++)
|
||||
if (ri->ISGREEN (i, j)) {
|
||||
float currData;
|
||||
currData = (float) (rawData[i][j] * ((i & 1) ? corrg2 : corrg1));
|
||||
rawData[i][j] = (currData);
|
||||
green_equilibrate_global(rawData);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1967,10 +1950,10 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le
|
||||
|
||||
if(numFrames == 4) {
|
||||
for(int i = 0; i < 4; ++i) {
|
||||
green_equilibrate (0.01 * (raw.bayersensor.greenthresh), *rawDataFrames[i]);
|
||||
green_equilibrate(0.01 * raw.bayersensor.greenthresh, *rawDataFrames[i]);
|
||||
}
|
||||
} else {
|
||||
green_equilibrate (0.01 * (raw.bayersensor.greenthresh), rawData);
|
||||
green_equilibrate(0.01 * raw.bayersensor.greenthresh, rawData);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -233,6 +233,7 @@ protected:
|
||||
|
||||
void cfa_linedn (float linenoiselevel);//Emil's line denoise
|
||||
|
||||
void green_equilibrate_global (array2D<float> &rawData);
|
||||
void green_equilibrate (float greenthresh, array2D<float> &rawData);//Emil's green equilibration
|
||||
|
||||
void nodemosaic(bool bw);
|
||||
|
@ -511,6 +511,9 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
|
||||
LUMINANCECURVE, // EvCATgreensc
|
||||
LUMINANCECURVE, // EvCATybscen
|
||||
LUMINANCECURVE, // EvCATAutoyb
|
||||
DARKFRAME, // EvLensCorrMode
|
||||
DARKFRAME, // EvLensCorrLensfunCamera
|
||||
DARKFRAME, // EvLensCorrLensfunLens
|
||||
LUMINANCECURVE, // EvlocallabEnabled
|
||||
LUMINANCECURVE, // EvlocallablocY
|
||||
LUMINANCECURVE, // EvlocallablocX
|
||||
@ -600,6 +603,5 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
|
||||
LUMINANCECURVE, //Evlocallabsensiex
|
||||
LUMINANCECURVE //Evlocallabshape
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
@ -49,6 +49,7 @@ class IImage8;
|
||||
class IImage16;
|
||||
class IImagefloat;
|
||||
|
||||
|
||||
/**
|
||||
* This class represents provides functions to obtain exif and IPTC metadata information
|
||||
* from the image file
|
||||
|
424
rtengine/rtlensfun.cc
Normal file
424
rtengine/rtlensfun.cc
Normal file
@ -0,0 +1,424 @@
|
||||
/* -*- C++ -*-
|
||||
*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2017 Alberto Griggio <alberto.griggio@gmail.com>
|
||||
*
|
||||
* 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 "rtlensfun.h"
|
||||
#include "settings.h"
|
||||
#include <iostream>
|
||||
|
||||
namespace rtengine {
|
||||
|
||||
extern const Settings *settings;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LFModifier
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
LFModifier::~LFModifier()
|
||||
{
|
||||
if (data_) {
|
||||
data_->Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LFModifier::operator bool() const
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
|
||||
void LFModifier::correctDistortion(double &x, double &y, int cx, int cy, double scale) const
|
||||
{
|
||||
if (!data_) {
|
||||
return;
|
||||
}
|
||||
|
||||
float pos[2];
|
||||
float xx = x + cx;
|
||||
float yy = y + cy;
|
||||
if (swap_xy_) {
|
||||
std::swap(xx, yy);
|
||||
}
|
||||
if (data_->ApplyGeometryDistortion(xx, yy, 1, 1, pos)) {
|
||||
x = pos[0];
|
||||
y = pos[1];
|
||||
if (swap_xy_) {
|
||||
std::swap(x, y);
|
||||
}
|
||||
x -= cx;
|
||||
y -= cy;
|
||||
}
|
||||
x *= scale;
|
||||
y *= scale;
|
||||
}
|
||||
|
||||
|
||||
bool LFModifier::isCACorrectionAvailable() const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void LFModifier::correctCA(double &x, double &y, int channel) const
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void LFModifier::processVignetteLine(int width, int y, float *line) const
|
||||
{
|
||||
data_->ApplyColorModification(line, 0, y, width, 1, LF_CR_1(INTENSITY), 0);
|
||||
}
|
||||
|
||||
|
||||
void LFModifier::processVignetteLine3Channels(int width, int y, float *line) const
|
||||
{
|
||||
data_->ApplyColorModification(line, 0, y, width, 1, LF_CR_3(RED, GREEN, BLUE), 0);
|
||||
}
|
||||
|
||||
|
||||
Glib::ustring LFModifier::getDisplayString() const
|
||||
{
|
||||
if (!data_) {
|
||||
return "NONE";
|
||||
} else {
|
||||
Glib::ustring ret;
|
||||
Glib::ustring sep = "";
|
||||
if (flags_ & LF_MODIFY_DISTORTION) {
|
||||
ret += "distortion";
|
||||
sep = ", ";
|
||||
}
|
||||
if (flags_ & LF_MODIFY_VIGNETTING) {
|
||||
ret += sep;
|
||||
ret += "vignetting";
|
||||
sep = ", ";
|
||||
}
|
||||
if (flags_ & LF_MODIFY_SCALE) {
|
||||
ret += sep;
|
||||
ret += "autoscaling";
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LFModifier::LFModifier(lfModifier *m, bool swap_xy, int flags):
|
||||
data_(m),
|
||||
swap_xy_(swap_xy),
|
||||
flags_(flags)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LFCamera
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
LFCamera::LFCamera():
|
||||
data_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
LFCamera::operator bool() const
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
|
||||
Glib::ustring LFCamera::getMake() const
|
||||
{
|
||||
if (data_) {
|
||||
return data_->Maker;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Glib::ustring LFCamera::getModel() const
|
||||
{
|
||||
if (data_) {
|
||||
return data_->Model;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float LFCamera::getCropFactor() const
|
||||
{
|
||||
if (data_) {
|
||||
return data_->CropFactor;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Glib::ustring LFCamera::getDisplayString() const
|
||||
{
|
||||
if (data_) {
|
||||
return Glib::ustring::compose("%1 %2", getMake(), getModel());
|
||||
} else {
|
||||
return "---";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LFLens
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
LFLens::LFLens():
|
||||
data_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
LFLens::operator bool() const
|
||||
{
|
||||
return data_;
|
||||
}
|
||||
|
||||
|
||||
Glib::ustring LFLens::getMake() const
|
||||
{
|
||||
if (data_) {
|
||||
return data_->Maker;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Glib::ustring LFLens::getLens() const
|
||||
{
|
||||
if (data_) {
|
||||
return Glib::ustring::compose("%1 %2", data_->Maker, data_->Model);
|
||||
} else {
|
||||
return "---";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
float LFLens::getCropFactor() const
|
||||
{
|
||||
if (data_) {
|
||||
return data_->CropFactor;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool LFLens::hasVignettingCorrection() const
|
||||
{
|
||||
if (data_) {
|
||||
return data_->CalibVignetting;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool LFLens::hasDistortionCorrection() const
|
||||
{
|
||||
if (data_) {
|
||||
return data_->CalibDistortion;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LFDatabase
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
LFDatabase LFDatabase::instance_;
|
||||
|
||||
|
||||
bool LFDatabase::init()
|
||||
{
|
||||
instance_.data_ = lfDatabase::Create();
|
||||
return instance_.data_->Load() != LF_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
LFDatabase::LFDatabase():
|
||||
data_(nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
LFDatabase::~LFDatabase()
|
||||
{
|
||||
if (data_) {
|
||||
data_->Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const LFDatabase *LFDatabase::getInstance()
|
||||
{
|
||||
return &instance_;
|
||||
}
|
||||
|
||||
|
||||
std::vector<LFCamera> LFDatabase::getCameras() const
|
||||
{
|
||||
std::vector<LFCamera> ret;
|
||||
if (data_) {
|
||||
auto cams = data_->GetCameras();
|
||||
while (*cams) {
|
||||
ret.emplace_back();
|
||||
ret.back().data_ = *cams;
|
||||
++cams;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
std::vector<LFLens> LFDatabase::getLenses() const
|
||||
{
|
||||
std::vector<LFLens> ret;
|
||||
if (data_) {
|
||||
auto lenses = data_->GetLenses();
|
||||
while (*lenses) {
|
||||
ret.emplace_back();
|
||||
ret.back().data_ = *lenses;
|
||||
++lenses;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
LFCamera LFDatabase::findCamera(const Glib::ustring &make, const Glib::ustring &model) const
|
||||
{
|
||||
LFCamera ret;
|
||||
if (data_) {
|
||||
auto found = data_->FindCamerasExt(make.c_str(), model.c_str());
|
||||
if (found) {
|
||||
ret.data_ = found[0];
|
||||
lf_free(found);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
LFLens LFDatabase::findLens(const LFCamera &camera, const Glib::ustring &name) const
|
||||
{
|
||||
LFLens ret;
|
||||
if (data_) {
|
||||
Glib::ustring lname = name;
|
||||
bool stdlens = camera && (name.empty() || name.find("Unknown") == 0);
|
||||
if (stdlens) {
|
||||
lname = camera.getModel(); // "Standard"
|
||||
}
|
||||
auto found = data_->FindLenses(camera.data_, nullptr, lname.c_str());
|
||||
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());
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
ret.data_ = found[0];
|
||||
lf_free(found);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
std::unique_ptr<LFModifier> LFDatabase::getModifier(const LFCamera &camera, const LFLens &lens,
|
||||
float focalLen, float aperture, float focusDist,
|
||||
int width, int height, bool swap_xy) const
|
||||
{
|
||||
std::unique_ptr<LFModifier> ret;
|
||||
if (data_) {
|
||||
if (camera && lens) {
|
||||
lfModifier *mod = lfModifier::Create(lens.data_, camera.getCropFactor(), width, height);
|
||||
int flags = LF_MODIFY_DISTORTION | LF_MODIFY_SCALE;
|
||||
if (aperture > 0) {
|
||||
flags |= LF_MODIFY_VIGNETTING;
|
||||
}
|
||||
flags = mod->Initialize(lens.data_, LF_PF_F32, focalLen, aperture, focusDist > 0 ? focusDist : 1000, 0.0, LF_RECTILINEAR, flags, false);
|
||||
ret.reset(new LFModifier(mod, swap_xy, flags));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
std::unique_ptr<LFModifier> LFDatabase::findModifier(const LensProfParams &lensProf, const ImageMetaData *idata, int width, int height, const CoarseTransformParams &coarse, int rawRotationDeg)
|
||||
{
|
||||
const LFDatabase *db = getInstance();
|
||||
Glib::ustring make, model, lens;
|
||||
float focallen = idata->getFocalLen();
|
||||
if (lensProf.lfAutoMatch) {
|
||||
if (focallen <= 0) {
|
||||
return nullptr;
|
||||
}
|
||||
make = idata->getMake();
|
||||
model = idata->getModel();
|
||||
lens = idata->getLens();
|
||||
} else {
|
||||
make = lensProf.lfCameraMake;
|
||||
model = lensProf.lfCameraModel;
|
||||
lens = lensProf.lfLens;
|
||||
}
|
||||
LFCamera c = db->findCamera(make, model);
|
||||
LFLens l = db->findLens(lensProf.lfAutoMatch ? c : LFCamera(), lens);
|
||||
if (focallen <= 0 && l.data_ && l.data_->MinFocal == l.data_->MaxFocal) {
|
||||
focallen = l.data_->MinFocal;
|
||||
}
|
||||
if (focallen <= 0) {
|
||||
return nullptr;
|
||||
}
|
||||
bool swap_xy = false;
|
||||
if (rawRotationDeg >= 0) {
|
||||
int rot = (coarse.rotate + rawRotationDeg) % 360;
|
||||
swap_xy = (rot == 90 || rot == 270);
|
||||
if (swap_xy) {
|
||||
std::swap(width, height);
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<LFModifier> ret = db->getModifier(c, l, idata->getFocalLen(), idata->getFNumber(), idata->getFocusDist(), width, height, swap_xy);
|
||||
|
||||
if (settings->verbose) {
|
||||
std::cout << "LENSFUN:\n"
|
||||
<< " camera: " << c.getDisplayString() << "\n"
|
||||
<< " lens: " << l.getDisplayString() << "\n"
|
||||
<< " correction: "
|
||||
<< (ret ? ret->getDisplayString() : "NONE") << std::endl;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
} // namespace rtengine
|
124
rtengine/rtlensfun.h
Normal file
124
rtengine/rtlensfun.h
Normal file
@ -0,0 +1,124 @@
|
||||
/* -*- C++ -*-
|
||||
*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2017 Alberto Griggio <alberto.griggio@gmail.com>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include <glibmm.h>
|
||||
|
||||
#include <lensfun.h>
|
||||
|
||||
#include "lcp.h"
|
||||
#include "noncopyable.h"
|
||||
#include "procparams.h"
|
||||
|
||||
namespace rtengine {
|
||||
|
||||
class LFModifier final :
|
||||
public LensCorrection,
|
||||
public NonCopyable
|
||||
{
|
||||
public:
|
||||
~LFModifier();
|
||||
|
||||
explicit operator bool() const;
|
||||
|
||||
void correctDistortion(double &x, double &y, int cx, int cy, double scale) const override;
|
||||
bool isCACorrectionAvailable() const override;
|
||||
void correctCA(double &x, double &y, int channel) const override;
|
||||
void processVignetteLine(int width, int y, float *line) const override;
|
||||
void processVignetteLine3Channels(int width, int y, float *line) const;
|
||||
|
||||
Glib::ustring getDisplayString() const;
|
||||
|
||||
private:
|
||||
LFModifier(lfModifier *m, bool swap_xy, int flags);
|
||||
|
||||
friend class LFDatabase;
|
||||
lfModifier *data_;
|
||||
bool swap_xy_;
|
||||
int flags_;
|
||||
};
|
||||
|
||||
class LFCamera final
|
||||
{
|
||||
public:
|
||||
LFCamera();
|
||||
|
||||
explicit operator bool() const;
|
||||
|
||||
Glib::ustring getMake() const;
|
||||
Glib::ustring getModel() const;
|
||||
float getCropFactor() const;
|
||||
|
||||
Glib::ustring getDisplayString() const;
|
||||
|
||||
private:
|
||||
friend class LFDatabase;
|
||||
const lfCamera *data_;
|
||||
};
|
||||
|
||||
class LFLens final
|
||||
{
|
||||
public:
|
||||
LFLens();
|
||||
|
||||
explicit operator bool() const;
|
||||
|
||||
Glib::ustring getMake() const;
|
||||
Glib::ustring getLens() const;
|
||||
Glib::ustring getDisplayString() const { return getLens(); }
|
||||
float getCropFactor() const;
|
||||
bool hasVignettingCorrection() const;
|
||||
bool hasDistortionCorrection() const;
|
||||
|
||||
private:
|
||||
friend class LFDatabase;
|
||||
const lfLens *data_;
|
||||
};
|
||||
|
||||
class LFDatabase final :
|
||||
public NonCopyable
|
||||
{
|
||||
public:
|
||||
static bool init();
|
||||
static const LFDatabase *getInstance();
|
||||
|
||||
~LFDatabase();
|
||||
|
||||
std::vector<LFCamera> getCameras() const;
|
||||
std::vector<LFLens> getLenses() const;
|
||||
LFCamera findCamera(const Glib::ustring &make, const Glib::ustring &model) const;
|
||||
LFLens findLens(const LFCamera &camera, const Glib::ustring &name) const;
|
||||
|
||||
static std::unique_ptr<LFModifier> findModifier(const LensProfParams &lensProf, const ImageMetaData *idata, int width, int height, const CoarseTransformParams &coarse, int rawRotationDeg);
|
||||
|
||||
private:
|
||||
std::unique_ptr<LFModifier> getModifier(const LFCamera &camera, const LFLens &lens,
|
||||
float focalLen, float aperture, float focusDist,
|
||||
int width, int height, bool swap_xy) const;
|
||||
LFDatabase();
|
||||
static LFDatabase instance_;
|
||||
lfDatabase *data_;
|
||||
};
|
||||
|
||||
} // namespace rtengine
|
@ -954,9 +954,14 @@ IImage8* Thumbnail::quickProcessImage (const procparams::ProcParams& params, int
|
||||
}
|
||||
|
||||
// Full thumbnail processing, second stage if complete profile exists
|
||||
IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rheight, TypeInterpolation interp, std::string camName,
|
||||
double focalLen, double focalLen35mm, float focusDist, float shutter, float fnumber, float iso, std::string expcomp_, double& myscale)
|
||||
IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rheight, TypeInterpolation interp, const ImageMetaData *metadata, double& myscale)
|
||||
{
|
||||
std::string camName = metadata->getCamera();
|
||||
float shutter = metadata->getShutterSpeed();
|
||||
float fnumber = metadata->getFNumber();
|
||||
float iso = metadata->getISOSpeed();
|
||||
float fcomp = metadata->getExpComp();
|
||||
|
||||
// check if the WB's equalizer value has changed
|
||||
if (wbEqual < (params.wb.equal - 5e-4) || wbEqual > (params.wb.equal + 5e-4) || wbTempBias < (params.wb.tempBias - 5e-4) || wbTempBias > (params.wb.tempBias + 5e-4)) {
|
||||
wbEqual = params.wb.equal;
|
||||
@ -1079,7 +1084,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei
|
||||
int origFH;
|
||||
double tscale = 0.0;
|
||||
getDimensions (origFW, origFH, tscale);
|
||||
ipf.transform (baseImg, trImg, 0, 0, 0, 0, fw, fh, origFW * tscale + 0.5, origFH * tscale + 0.5, focalLen, focalLen35mm, focusDist, fnumber, 0, true); // Raw rotate degree not detectable here
|
||||
ipf.transform (baseImg, trImg, 0, 0, 0, 0, fw, fh, origFW * tscale + 0.5, origFH * tscale + 0.5, metadata, 0, true); // Raw rotate degree not detectable here
|
||||
delete baseImg;
|
||||
baseImg = trImg;
|
||||
}
|
||||
@ -1279,11 +1284,6 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, int rhei
|
||||
float fnum = fnumber;// F number
|
||||
float fiso = iso;// ISO
|
||||
float fspeed = shutter;//speed
|
||||
char * writ = new char[expcomp_.size() + 1];//convert expcomp_ to char
|
||||
std::copy (expcomp_.begin(), expcomp_.end(), writ);
|
||||
writ[expcomp_.size()] = '\0';
|
||||
float fcomp = atof (writ); //compensation + -
|
||||
delete[] writ;
|
||||
float adap;
|
||||
|
||||
if (fnum < 0.3f || fiso < 5.f || fspeed < 0.00001f)
|
||||
|
@ -71,8 +71,7 @@ public:
|
||||
|
||||
void init ();
|
||||
|
||||
IImage8* processImage (const procparams::ProcParams& pparams, int rheight, TypeInterpolation interp, std::string camName,
|
||||
double focalLen, double focalLen35mm, float focusDist, float shutter, float fnumber, float iso, std::string expcomp_, double& scale);
|
||||
IImage8* processImage (const procparams::ProcParams& pparams, int rheight, TypeInterpolation interp, const ImageMetaData *metadata, double& scale);
|
||||
IImage8* quickProcessImage (const procparams::ProcParams& pparams, int rheight, TypeInterpolation interp, double& scale);
|
||||
int getImageWidth (const procparams::ProcParams& pparams, int rheight, float &ratio);
|
||||
void getDimensions (int& w, int& h, double& scaleFac);
|
||||
|
@ -820,10 +820,8 @@ private:
|
||||
// perform transform (excepted resizing)
|
||||
if (ipf.needsTransform()) {
|
||||
Imagefloat* trImg = new Imagefloat (fw, fh);
|
||||
ipf.transform (baseImg, trImg, 0, 0, 0, 0, fw, fh, fw, fh, imgsrc->getMetaData()->getFocalLen(), imgsrc->getMetaData()->getFocalLen35mm(),
|
||||
imgsrc->getMetaData()->getFocusDist(),
|
||||
imgsrc->getMetaData()->getFNumber(),
|
||||
imgsrc->getRotateDegree(), true);
|
||||
ipf.transform (baseImg, trImg, 0, 0, 0, 0, fw, fh, fw, fh,
|
||||
imgsrc->getMetaData(), imgsrc->getRotateDegree(), true);
|
||||
delete baseImg;
|
||||
baseImg = trImg;
|
||||
}
|
||||
|
@ -170,6 +170,7 @@ if(WIN32)
|
||||
${GLIBMM_INCLUDE_DIRS}
|
||||
${GTKMM_INCLUDE_DIRS}
|
||||
${GTK_INCLUDE_DIRS}
|
||||
${LENSFUN_INCLUDE_DIRS}
|
||||
)
|
||||
link_directories(. "${PROJECT_SOURCE_DIR}/rtexif"
|
||||
${EXTRA_LIBDIR}
|
||||
@ -195,6 +196,7 @@ else()
|
||||
${GTK_INCLUDE_DIRS}
|
||||
${IPTCDATA_INCLUDE_DIRS}
|
||||
${LCMS_INCLUDE_DIRS}
|
||||
${LENSFUN_INCLUDE_DIRS}
|
||||
)
|
||||
link_directories(${EXTRA_LIBDIR}
|
||||
${CANBERRA-GTK_LIBRARY_DIRS}
|
||||
@ -252,6 +254,7 @@ target_link_libraries(rth rtengine
|
||||
${PNG_LIBRARIES}
|
||||
${TIFF_LIBRARIES}
|
||||
${ZLIB_LIBRARIES}
|
||||
${LENSFUN_LIBRARIES}
|
||||
)
|
||||
|
||||
target_link_libraries(rth-cli rtengine
|
||||
@ -271,6 +274,7 @@ target_link_libraries(rth-cli rtengine
|
||||
${PNG_LIBRARIES}
|
||||
${TIFF_LIBRARIES}
|
||||
${ZLIB_LIBRARIES}
|
||||
${LENSFUN_LIBRARIES}
|
||||
)
|
||||
|
||||
# Install executables
|
||||
|
@ -21,8 +21,9 @@
|
||||
|
||||
#include <glibmm.h>
|
||||
#include "options.h"
|
||||
#include "../rtengine/rtengine.h"
|
||||
|
||||
class CacheImageData
|
||||
class CacheImageData: public rtengine::ImageMetaData
|
||||
{
|
||||
|
||||
public:
|
||||
@ -76,9 +77,26 @@ public:
|
||||
int load (const Glib::ustring& fname);
|
||||
int save (const Glib::ustring& fname);
|
||||
|
||||
Glib::ustring getCamera() const
|
||||
{
|
||||
return Glib::ustring(camMake + " " + camModel);
|
||||
}
|
||||
//-------------------------------------------------------------------------
|
||||
// ImageMetaData interface
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
bool hasExif() const { return false; }
|
||||
const rtexif::TagDirectory *getExifData() const { return NULL; }
|
||||
bool hasIPTC() const { return false; }
|
||||
const rtengine::procparams::IPTCPairs getIPTCData () const { return rtengine::procparams::IPTCPairs(); }
|
||||
tm getDateTime () const { return tm{}; }
|
||||
time_t getDateTimeAsTS() const { return time_t(-1); }
|
||||
int getISOSpeed() const { return iso; }
|
||||
double getFNumber() const { return fnumber; }
|
||||
double getFocalLen() const { return focalLen; }
|
||||
double getFocalLen35mm() const { return focalLen35mm; }
|
||||
float getFocusDist() const { return focusDist; }
|
||||
double getShutterSpeed() const { return shutter; }
|
||||
double getExpComp() const { return atof(expcomp.c_str()); }
|
||||
std::string getMake() const { return camMake; }
|
||||
std::string getModel() const { return camModel; }
|
||||
std::string getLens() const { return lens; }
|
||||
std::string getOrientation() const { return ""; } // TODO
|
||||
};
|
||||
#endif
|
||||
|
@ -22,15 +22,82 @@
|
||||
#include "../rtengine/lcp.h"
|
||||
#include <sstream>
|
||||
#include "rtimage.h"
|
||||
#include "../rtengine/rtlensfun.h"
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
using namespace rtengine;
|
||||
using namespace rtengine::procparams;
|
||||
|
||||
LensProfilePanel::LensProfilePanel () : FoldableToolPanel(this, "lensprof", M("TP_LENSPROFILE_LABEL")), lcpFileChanged(false), useDistChanged(false), useVignChanged(false), useCAChanged(false), isRaw(true), lensgeomLcpFill(nullptr)
|
||||
{
|
||||
hbLCPFile = Gtk::manage(new Gtk::HBox());
|
||||
LensProfilePanel::LFDbHelper *LensProfilePanel::lf(nullptr);
|
||||
|
||||
lLCPFileHead = Gtk::manage(new Gtk::Label(M("GENERAL_FILE")));
|
||||
LensProfilePanel::LensProfilePanel () :
|
||||
FoldableToolPanel(this, "lensprof", M("TP_LENSPROFILE_LABEL")),
|
||||
lcpFileChanged(false),
|
||||
useDistChanged(false),
|
||||
useVignChanged(false),
|
||||
useCAChanged(false),
|
||||
isRaw(true),
|
||||
metadata(nullptr),
|
||||
useLensfunChanged(false),
|
||||
lensfunAutoChanged(false),
|
||||
lensfunCameraChanged(false),
|
||||
lensfunLensChanged(false)
|
||||
{
|
||||
if (!lf) {
|
||||
lf = new LFDbHelper();
|
||||
}
|
||||
|
||||
corrUnchanged = Gtk::manage(new Gtk::RadioButton(M("GENERAL_UNCHANGED")));
|
||||
pack_start(*corrUnchanged);
|
||||
|
||||
corrGroup = corrUnchanged->get_group();
|
||||
|
||||
corrOff = Gtk::manage(new Gtk::RadioButton(corrGroup, M("GENERAL_NONE")));
|
||||
pack_start(*corrOff);
|
||||
|
||||
corrLensfunAuto = Gtk::manage(new Gtk::RadioButton(corrGroup, M("LENSPROFILE_CORRECTION_AUTOMATCH")));
|
||||
pack_start(*corrLensfunAuto);
|
||||
|
||||
corrLensfunManual = Gtk::manage(new Gtk::RadioButton(corrGroup, M("LENSPROFILE_CORRECTION_MANUAL")));
|
||||
pack_start(*corrLensfunManual);
|
||||
|
||||
lensfunCameras = Gtk::manage(new MyComboBox());
|
||||
lensfunCameras->set_model(lf->lensfunCameraModel);
|
||||
lensfunCameras->pack_start(lf->lensfunModelCam.model);
|
||||
Gtk::CellRendererText* cellRenderer = dynamic_cast<Gtk::CellRendererText*>(lensfunCameras->get_first_cell());
|
||||
cellRenderer->property_ellipsize() = Pango::ELLIPSIZE_MIDDLE;
|
||||
cellRenderer->property_ellipsize_set() = true;
|
||||
lensfunCameras->setPreferredWidth(50, 120);
|
||||
|
||||
lensfunLenses = Gtk::manage(new MyComboBox());
|
||||
lensfunLenses->set_model(lf->lensfunLensModel);
|
||||
lensfunLenses->pack_start(lf->lensfunModelLens.prettylens);
|
||||
cellRenderer = dynamic_cast<Gtk::CellRendererText*>(lensfunLenses->get_first_cell());
|
||||
cellRenderer->property_ellipsize() = Pango::ELLIPSIZE_MIDDLE;
|
||||
cellRenderer->property_ellipsize_set() = true;
|
||||
lensfunLenses->setPreferredWidth(50, 120);
|
||||
|
||||
Gtk::HBox *hb = Gtk::manage(new Gtk::HBox());
|
||||
hb->pack_start(*Gtk::manage(new Gtk::Label(M("EXIFFILTER_CAMERA"))), Gtk::PACK_SHRINK, 4);
|
||||
hb->pack_start(*lensfunCameras);
|
||||
pack_start(*hb);
|
||||
|
||||
hb = Gtk::manage(new Gtk::HBox());
|
||||
hb->pack_start(*Gtk::manage(new Gtk::Label(M("EXIFFILTER_LENS"))), Gtk::PACK_SHRINK, 4);
|
||||
hb->pack_start(*lensfunLenses);
|
||||
warning = Gtk::manage(new Gtk::Image());
|
||||
warning->set_from_icon_name("dialog-warning", Gtk::ICON_SIZE_LARGE_TOOLBAR);
|
||||
warning->set_tooltip_text(M("LENSPROFILE_LENS_WARNING"));
|
||||
warning->hide();
|
||||
hb->pack_start(*warning, Gtk::PACK_SHRINK, 4);
|
||||
pack_start(*hb);
|
||||
|
||||
corrLcpFile = Gtk::manage(new Gtk::RadioButton(corrGroup));
|
||||
hbLCPFile = Gtk::manage(new Gtk::HBox());
|
||||
hbLCPFile->pack_start(*corrLcpFile, Gtk::PACK_SHRINK);
|
||||
|
||||
lLCPFileHead = Gtk::manage(new Gtk::Label(M("LENSPROFILE_CORRECTION_LCPFILE")));
|
||||
hbLCPFile->pack_start(*lLCPFileHead, Gtk::PACK_SHRINK, 4);
|
||||
|
||||
fcbLCPFile = Gtk::manage(new MyFileChooserButton(M("TP_LENSPROFILE_LABEL"), Gtk::FILE_CHOOSER_ACTION_OPEN));
|
||||
@ -41,7 +108,7 @@ LensProfilePanel::LensProfilePanel () : FoldableToolPanel(this, "lensprof", M("T
|
||||
filterLCP->add_pattern("*.LCP");
|
||||
fcbLCPFile->add_filter(filterLCP);
|
||||
|
||||
Glib::ustring defDir = lcpStore->getDefaultCommonDirectory();
|
||||
Glib::ustring defDir = LCPStore::getInstance()->getDefaultCommonDirectory();
|
||||
|
||||
if (!defDir.empty()) {
|
||||
#ifdef WIN32
|
||||
@ -74,6 +141,15 @@ LensProfilePanel::LensProfilePanel () : FoldableToolPanel(this, "lensprof", M("T
|
||||
ckbUseVign->signal_toggled().connect( sigc::mem_fun(*this, &LensProfilePanel::onUseVignChanged) );
|
||||
ckbUseCA->signal_toggled().connect( sigc::mem_fun(*this, &LensProfilePanel::onUseCAChanged) );
|
||||
|
||||
lensfunCameras->signal_changed().connect(sigc::mem_fun(*this, &LensProfilePanel::onLensfunCameraChanged));
|
||||
lensfunLenses->signal_changed().connect(sigc::mem_fun(*this, &LensProfilePanel::onLensfunLensChanged));
|
||||
corrOff->signal_toggled().connect(sigc::mem_fun(*this, &LensProfilePanel::onCorrModeChanged));
|
||||
corrLensfunAuto->signal_toggled().connect(sigc::mem_fun(*this, &LensProfilePanel::onCorrModeChanged));
|
||||
corrLensfunManual->signal_toggled().connect(sigc::mem_fun(*this, &LensProfilePanel::onCorrModeChanged));
|
||||
corrLcpFile->signal_toggled().connect(sigc::mem_fun(*this, &LensProfilePanel::onCorrModeChanged));
|
||||
|
||||
corrUnchanged->hide();
|
||||
|
||||
allowFocusDep = true;
|
||||
}
|
||||
|
||||
@ -82,7 +158,20 @@ void LensProfilePanel::read(const rtengine::procparams::ProcParams* pp, const Pa
|
||||
disableListener ();
|
||||
conUseDist.block(true);
|
||||
|
||||
if (!pp->lensProf.lcpFile.empty() && lcpStore->isValidLCPFileName(pp->lensProf.lcpFile)) {
|
||||
if (!batchMode) {
|
||||
corrUnchanged->hide();
|
||||
}
|
||||
|
||||
corrLensfunAuto->set_sensitive(true);
|
||||
|
||||
if (pp->lensProf.useLensfun) {
|
||||
if (pp->lensProf.lfAutoMatch) {
|
||||
corrLensfunAuto->set_active(true);
|
||||
} else {
|
||||
corrLensfunManual->set_active(true);
|
||||
}
|
||||
} else if (!pp->lensProf.lcpFile.empty() && LCPStore::getInstance()->isValidLCPFileName(pp->lensProf.lcpFile)) {
|
||||
corrLcpFile->set_active(true);
|
||||
fcbLCPFile->set_filename (pp->lensProf.lcpFile);
|
||||
updateDisabled(true);
|
||||
} else {
|
||||
@ -98,18 +187,76 @@ void LensProfilePanel::read(const rtengine::procparams::ProcParams* pp, const Pa
|
||||
}
|
||||
|
||||
updateDisabled(false);
|
||||
|
||||
corrOff->set_active(true);
|
||||
}
|
||||
|
||||
ckbUseDist->set_active (pp->lensProf.useDist);
|
||||
ckbUseVign->set_active (pp->lensProf.useVign && isRaw);
|
||||
ckbUseCA->set_active (pp->lensProf.useCA && isRaw);
|
||||
|
||||
const LFDatabase *db = LFDatabase::getInstance();
|
||||
LFCamera c;
|
||||
LFLens l;
|
||||
if (metadata) {
|
||||
c = db->findCamera(metadata->getMake(), metadata->getModel());
|
||||
l = db->findLens(c, metadata->getLens());
|
||||
}
|
||||
|
||||
if (!setLensfunCamera(pp->lensProf.lfCameraMake, pp->lensProf.lfCameraModel) && pp->lensProf.lfAutoMatch) {
|
||||
setLensfunCamera(c.getMake(), c.getModel());
|
||||
}
|
||||
if (!setLensfunLens(pp->lensProf.lfLens) && pp->lensProf.lfAutoMatch) {
|
||||
setLensfunLens(l.getLens());
|
||||
}
|
||||
|
||||
lcpFileChanged = useDistChanged = useVignChanged = useCAChanged = false;
|
||||
useLensfunChanged = lensfunAutoChanged = lensfunCameraChanged = lensfunLensChanged = false;
|
||||
|
||||
if (!batchMode && !checkLensfunCanCorrect(true)) {
|
||||
if (corrLensfunAuto->get_active()) {
|
||||
corrOff->set_active(true);
|
||||
}
|
||||
corrLensfunAuto->set_sensitive(false);
|
||||
}
|
||||
|
||||
if (corrLensfunManual->get_active() && !checkLensfunCanCorrect(false)) {
|
||||
corrOff->set_active(true);
|
||||
}
|
||||
|
||||
updateLensfunWarning();
|
||||
|
||||
enableListener ();
|
||||
conUseDist.block(false);
|
||||
}
|
||||
|
||||
|
||||
void LensProfilePanel::updateLensfunWarning()
|
||||
{
|
||||
warning->hide();
|
||||
if (corrLensfunManual->get_active()) {
|
||||
const LFDatabase *db = LFDatabase::getInstance();
|
||||
|
||||
auto itc = lensfunCameras->get_active();
|
||||
if (!itc) {
|
||||
return;
|
||||
}
|
||||
LFCamera c = db->findCamera((*itc)[lf->lensfunModelCam.make], (*itc)[lf->lensfunModelCam.model]);
|
||||
auto itl = lensfunLenses->get_active();
|
||||
if (!itl) {
|
||||
return;
|
||||
}
|
||||
LFLens l = db->findLens(LFCamera(), (*itl)[lf->lensfunModelLens.lens]);
|
||||
float lenscrop = l.getCropFactor();
|
||||
float camcrop = c.getCropFactor();
|
||||
if (lenscrop <= 0 || camcrop <= 0 || lenscrop / camcrop >= 1.01f) {
|
||||
warning->show();
|
||||
}
|
||||
ckbUseVign->set_sensitive(l.hasVignettingCorrection());
|
||||
ckbUseDist->set_sensitive(l.hasDistortionCorrection());
|
||||
}
|
||||
}
|
||||
|
||||
void LensProfilePanel::setRawMeta(bool raw, const rtengine::ImageMetaData* pMeta)
|
||||
{
|
||||
if (!raw || pMeta->getFocusDist() <= 0) {
|
||||
@ -124,11 +271,12 @@ void LensProfilePanel::setRawMeta(bool raw, const rtengine::ImageMetaData* pMeta
|
||||
}
|
||||
|
||||
isRaw = raw;
|
||||
metadata = pMeta;
|
||||
}
|
||||
|
||||
void LensProfilePanel::write( rtengine::procparams::ProcParams* pp, ParamsEdited* pedited)
|
||||
{
|
||||
if (lcpStore->isValidLCPFileName(fcbLCPFile->get_filename())) {
|
||||
if (corrLcpFile->get_active() && LCPStore::getInstance()->isValidLCPFileName(fcbLCPFile->get_filename())) {
|
||||
pp->lensProf.lcpFile = fcbLCPFile->get_filename();
|
||||
} else {
|
||||
pp->lensProf.lcpFile = "";
|
||||
@ -138,20 +286,48 @@ void LensProfilePanel::write( rtengine::procparams::ProcParams* pp, ParamsEdited
|
||||
pp->lensProf.useVign = ckbUseVign->get_active();
|
||||
pp->lensProf.useCA = ckbUseCA->get_active();
|
||||
|
||||
pp->lensProf.useLensfun = corrLensfunAuto->get_active() || corrLensfunManual->get_active();
|
||||
pp->lensProf.lfAutoMatch = corrLensfunAuto->get_active();
|
||||
auto itc = lensfunCameras->get_active();
|
||||
if (itc) {
|
||||
pp->lensProf.lfCameraMake = (*itc)[lf->lensfunModelCam.make];
|
||||
pp->lensProf.lfCameraModel = (*itc)[lf->lensfunModelCam.model];
|
||||
} else {
|
||||
pp->lensProf.lfCameraMake = "";
|
||||
pp->lensProf.lfCameraModel = "";
|
||||
}
|
||||
auto itl = lensfunLenses->get_active();
|
||||
if (itl) {
|
||||
pp->lensProf.lfLens = (*itl)[lf->lensfunModelLens.lens];
|
||||
} else {
|
||||
pp->lensProf.lfLens = "";
|
||||
}
|
||||
|
||||
if (pedited) {
|
||||
pedited->lensProf.lcpFile = lcpFileChanged;
|
||||
pedited->lensProf.useDist = useDistChanged;
|
||||
pedited->lensProf.useVign = useVignChanged;
|
||||
pedited->lensProf.useCA = useCAChanged;
|
||||
pedited->lensProf.useLensfun = useLensfunChanged;
|
||||
pedited->lensProf.lfAutoMatch = lensfunAutoChanged;
|
||||
pedited->lensProf.lfCameraMake = lensfunCameraChanged;
|
||||
pedited->lensProf.lfCameraModel = lensfunCameraChanged;
|
||||
pedited->lensProf.lfLens = lensfunLensChanged;
|
||||
}
|
||||
}
|
||||
|
||||
void LensProfilePanel::onLCPFileChanged()
|
||||
{
|
||||
lcpFileChanged = true;
|
||||
updateDisabled(lcpStore->isValidLCPFileName(fcbLCPFile->get_filename()));
|
||||
bool valid = LCPStore::getInstance()->isValidLCPFileName(fcbLCPFile->get_filename());
|
||||
updateDisabled(valid);
|
||||
|
||||
if (listener) {
|
||||
if (valid) {
|
||||
disableListener();
|
||||
corrLcpFile->set_active(true);
|
||||
enableListener();
|
||||
}
|
||||
listener->panelChanged (EvLCPFile, Glib::path_get_basename(fcbLCPFile->get_filename()));
|
||||
}
|
||||
}
|
||||
@ -163,7 +339,11 @@ void LensProfilePanel::onLCPFileReset()
|
||||
fcbLCPFile->unselect_filename(fcbLCPFile->get_filename());
|
||||
updateDisabled(false);
|
||||
|
||||
|
||||
if (listener) {
|
||||
disableListener();
|
||||
corrOff->set_active(true);
|
||||
enableListener();
|
||||
listener->panelChanged (EvLCPFile, M("GENERAL_NONE"));
|
||||
}
|
||||
}
|
||||
@ -199,3 +379,280 @@ void LensProfilePanel::updateDisabled(bool enable)
|
||||
ckbUseVign->set_sensitive(enable && isRaw);
|
||||
ckbUseCA->set_sensitive(enable && allowFocusDep);
|
||||
}
|
||||
|
||||
void LensProfilePanel::setBatchMode(bool yes)
|
||||
{
|
||||
FoldableToolPanel::setBatchMode(yes);
|
||||
if (yes) {
|
||||
corrUnchanged->show();
|
||||
corrUnchanged->set_active(true);
|
||||
} else {
|
||||
corrUnchanged->hide();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool LensProfilePanel::setLensfunCamera(const Glib::ustring &make, const Glib::ustring &model)
|
||||
{
|
||||
if (!make.empty() && !model.empty()) {
|
||||
auto it = lensfunCameras->get_active();
|
||||
if (it && (*it)[lf->lensfunModelCam.make] == make && (*it)[lf->lensfunModelCam.model] == model) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// search for the active row
|
||||
for (auto row : lf->lensfunCameraModel->children()) {
|
||||
if (row[lf->lensfunModelCam.make] == make) {
|
||||
auto &c = row.children();
|
||||
for (auto it = c.begin(), end = c.end(); it != end; ++it) {
|
||||
auto &childrow = *it;
|
||||
if (childrow[lf->lensfunModelCam.model] == model) {
|
||||
lensfunCameras->set_active(it);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
lensfunCameras->set_active(-1);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool LensProfilePanel::setLensfunLens(const Glib::ustring &lens)
|
||||
{
|
||||
if (!lens.empty()) {
|
||||
auto it = lensfunLenses->get_active();
|
||||
if (it && (*it)[lf->lensfunModelLens.lens] == lens) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (auto row : lf->lensfunLensModel->children()) {
|
||||
if (lens.find(row[lf->lensfunModelLens.lens]) == 0) {
|
||||
auto &c = row.children();
|
||||
for (auto it = c.begin(), end = c.end(); it != end; ++it) {
|
||||
auto &childrow = *it;
|
||||
if (childrow[lf->lensfunModelLens.lens] == lens) {
|
||||
lensfunLenses->set_active(it);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
lensfunLenses->set_active(-1);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LensProfilePanel::onLensfunCameraChanged()
|
||||
{
|
||||
auto iter = lensfunCameras->get_active();
|
||||
|
||||
if (iter) {
|
||||
lensfunCameraChanged = true;
|
||||
|
||||
if (listener) {
|
||||
disableListener();
|
||||
corrLensfunManual->set_active(true);
|
||||
enableListener();
|
||||
|
||||
Glib::ustring name = (*iter)[lf->lensfunModelCam.model];
|
||||
listener->panelChanged(EvLensCorrLensfunCamera, name);
|
||||
}
|
||||
}
|
||||
|
||||
updateLensfunWarning();
|
||||
}
|
||||
|
||||
|
||||
void LensProfilePanel::onLensfunLensChanged()
|
||||
{
|
||||
auto iter = lensfunLenses->get_active();
|
||||
|
||||
if (iter) {
|
||||
lensfunLensChanged = true;
|
||||
|
||||
if (listener) {
|
||||
disableListener();
|
||||
corrLensfunManual->set_active(true);
|
||||
enableListener();
|
||||
|
||||
Glib::ustring name = (*iter)[lf->lensfunModelLens.prettylens];
|
||||
listener->panelChanged(EvLensCorrLensfunLens, name);
|
||||
}
|
||||
}
|
||||
|
||||
updateLensfunWarning();
|
||||
}
|
||||
|
||||
|
||||
void LensProfilePanel::onCorrModeChanged()
|
||||
{
|
||||
Glib::ustring mode;
|
||||
|
||||
if (corrOff->get_active()) {
|
||||
useLensfunChanged = true;
|
||||
lensfunAutoChanged = true;
|
||||
lcpFileChanged = true;
|
||||
|
||||
ckbUseDist->set_sensitive(false);
|
||||
ckbUseVign->set_sensitive(false);
|
||||
ckbUseCA->set_sensitive(false);
|
||||
|
||||
mode = M("GENERAL_NONE");
|
||||
} else if (corrLensfunAuto->get_active()) {
|
||||
useLensfunChanged = true;
|
||||
lensfunAutoChanged = true;
|
||||
lcpFileChanged = true;
|
||||
useDistChanged = true;
|
||||
useVignChanged = true;
|
||||
|
||||
ckbUseDist->set_sensitive(true);
|
||||
ckbUseVign->set_sensitive(true);
|
||||
ckbUseCA->set_sensitive(false);
|
||||
|
||||
if (metadata) {
|
||||
bool b = disableListener();
|
||||
const LFDatabase *db = LFDatabase::getInstance();
|
||||
LFCamera c = db->findCamera(metadata->getMake(), metadata->getModel());
|
||||
LFLens l = db->findLens(c, metadata->getLens());
|
||||
setLensfunCamera(c.getMake(), c.getModel());
|
||||
setLensfunLens(l.getLens());
|
||||
if (b) {
|
||||
enableListener();
|
||||
}
|
||||
}
|
||||
|
||||
mode = M("LENSPROFILE_CORRECTION_AUTOMATCH");
|
||||
} else if (corrLensfunManual->get_active()) {
|
||||
useLensfunChanged = true;
|
||||
lensfunAutoChanged = true;
|
||||
lcpFileChanged = true;
|
||||
useDistChanged = true;
|
||||
useVignChanged = true;
|
||||
|
||||
ckbUseDist->set_sensitive(true);
|
||||
ckbUseVign->set_sensitive(true);
|
||||
ckbUseCA->set_sensitive(false);
|
||||
|
||||
mode = M("LENSPROFILE_CORRECTION_MANUAL");
|
||||
} else if (corrLcpFile->get_active()) {
|
||||
useLensfunChanged = true;
|
||||
lensfunAutoChanged = true;
|
||||
lcpFileChanged = true;
|
||||
useDistChanged = true;
|
||||
useVignChanged = true;
|
||||
|
||||
updateDisabled(true);
|
||||
|
||||
mode = M("LENSPROFILE_CORRECTION_LCPFILE");
|
||||
} else if (corrUnchanged->get_active()) {
|
||||
useLensfunChanged = false;
|
||||
lensfunAutoChanged = false;
|
||||
lcpFileChanged = false;
|
||||
lensfunCameraChanged = false;
|
||||
lensfunLensChanged = false;
|
||||
|
||||
ckbUseDist->set_sensitive(true);
|
||||
ckbUseVign->set_sensitive(true);
|
||||
ckbUseCA->set_sensitive(true);
|
||||
|
||||
mode = M("GENERAL_UNCHANGED");
|
||||
}
|
||||
|
||||
updateLensfunWarning();
|
||||
|
||||
if (listener) {
|
||||
listener->panelChanged(EvLensCorrMode, mode);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool LensProfilePanel::checkLensfunCanCorrect(bool automatch)
|
||||
{
|
||||
if (!metadata) {
|
||||
return false;
|
||||
}
|
||||
rtengine::procparams::ProcParams lpp;
|
||||
write(&lpp);
|
||||
lpp.lensProf.lfAutoMatch = automatch;
|
||||
std::unique_ptr<LFModifier> mod(LFDatabase::findModifier(lpp.lensProf, metadata, 100, 100, lpp.coarse, -1));
|
||||
return mod.get() != nullptr;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// LFDbHelper
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
LensProfilePanel::LFDbHelper::LFDbHelper()
|
||||
{
|
||||
lensfunCameraModel = Gtk::TreeStore::create(lensfunModelCam);
|
||||
lensfunLensModel = Gtk::TreeStore::create(lensfunModelLens);
|
||||
|
||||
fillLensfunCameras();
|
||||
fillLensfunLenses();
|
||||
}
|
||||
|
||||
void LensProfilePanel::LFDbHelper::fillLensfunCameras()
|
||||
{
|
||||
if (options.rtSettings.verbose) {
|
||||
std::cout << "LENSFUN, scanning cameras:" << std::endl;
|
||||
}
|
||||
std::map<Glib::ustring, std::set<Glib::ustring>> camnames;
|
||||
auto camlist = LFDatabase::getInstance()->getCameras();
|
||||
for (auto &c : camlist) {
|
||||
camnames[c.getMake()].insert(c.getModel());
|
||||
|
||||
if (options.rtSettings.verbose) {
|
||||
std::cout << " found: " << c.getDisplayString() << std::endl;
|
||||
}
|
||||
}
|
||||
for (auto &p : camnames) {
|
||||
Gtk::TreeModel::Row row = *(lensfunCameraModel->append());
|
||||
row[lensfunModelCam.make] = p.first;
|
||||
row[lensfunModelCam.model] = p.first;
|
||||
for (auto &c : p.second) {
|
||||
Gtk::TreeModel::Row child = *(lensfunCameraModel->append(row.children()));
|
||||
child[lensfunModelCam.make] = p.first;
|
||||
child[lensfunModelCam.model] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LensProfilePanel::LFDbHelper::fillLensfunLenses()
|
||||
{
|
||||
if (options.rtSettings.verbose) {
|
||||
std::cout << "LENSFUN, scanning lenses:" << std::endl;
|
||||
}
|
||||
std::map<Glib::ustring, std::set<Glib::ustring>> lenses;
|
||||
auto lenslist = LFDatabase::getInstance()->getLenses();
|
||||
for (auto &l : lenslist) {
|
||||
auto name = l.getLens();
|
||||
auto make = l.getMake();
|
||||
lenses[make].insert(name);
|
||||
|
||||
if (options.rtSettings.verbose) {
|
||||
std::cout << " found: " << l.getDisplayString() << std::endl;
|
||||
}
|
||||
}
|
||||
for (auto &p : lenses) {
|
||||
Gtk::TreeModel::Row row = *(lensfunLensModel->append());
|
||||
row[lensfunModelLens.lens] = p.first;
|
||||
row[lensfunModelLens.prettylens] = p.first;
|
||||
for (auto &c : p.second) {
|
||||
Gtk::TreeModel::Row child = *(lensfunLensModel->append(row.children()));
|
||||
child[lensfunModelLens.lens] = c;
|
||||
if (c.find(p.first, p.first.size()+1) == p.first.size()+1) {
|
||||
child[lensfunModelLens.prettylens] = c.substr(p.first.size()+1);
|
||||
} else {
|
||||
child[lensfunModelLens.prettylens] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -39,7 +39,55 @@ protected:
|
||||
void updateDisabled(bool enable);
|
||||
bool allowFocusDep;
|
||||
bool isRaw;
|
||||
LensGeometry *lensgeomLcpFill;
|
||||
const rtengine::ImageMetaData* metadata;
|
||||
|
||||
Gtk::RadioButton::Group corrGroup;
|
||||
Gtk::RadioButton *corrOff;
|
||||
Gtk::RadioButton *corrLensfunAuto;
|
||||
Gtk::RadioButton *corrLensfunManual;
|
||||
Gtk::RadioButton *corrLcpFile;
|
||||
Gtk::RadioButton *corrUnchanged;
|
||||
MyComboBox *lensfunCameras;
|
||||
MyComboBox *lensfunLenses;
|
||||
Gtk::Image *warning;
|
||||
|
||||
class LFDbHelper {
|
||||
public:
|
||||
class LFModelCam: public Gtk::TreeModel::ColumnRecord {
|
||||
public:
|
||||
LFModelCam() { add(make); add(model); }
|
||||
Gtk::TreeModelColumn<Glib::ustring> make;
|
||||
Gtk::TreeModelColumn<Glib::ustring> model;
|
||||
};
|
||||
|
||||
class LFModelLens: public Gtk::TreeModel::ColumnRecord {
|
||||
public:
|
||||
LFModelLens() { add(lens); add(prettylens); }
|
||||
Gtk::TreeModelColumn<Glib::ustring> lens;
|
||||
Gtk::TreeModelColumn<Glib::ustring> prettylens;
|
||||
};
|
||||
|
||||
LFModelCam lensfunModelCam;
|
||||
LFModelLens lensfunModelLens;
|
||||
|
||||
Glib::RefPtr<Gtk::TreeStore> lensfunCameraModel;
|
||||
Glib::RefPtr<Gtk::TreeStore> lensfunLensModel;
|
||||
|
||||
LFDbHelper();
|
||||
void fillLensfunCameras();
|
||||
void fillLensfunLenses();
|
||||
};
|
||||
static LFDbHelper *lf;
|
||||
|
||||
bool useLensfunChanged;
|
||||
bool lensfunAutoChanged;
|
||||
bool lensfunCameraChanged;
|
||||
bool lensfunLensChanged;
|
||||
|
||||
bool setLensfunCamera(const Glib::ustring &make, const Glib::ustring &model);
|
||||
bool setLensfunLens(const Glib::ustring &lens);
|
||||
bool checkLensfunCanCorrect(bool automatch);
|
||||
void updateLensfunWarning();
|
||||
|
||||
public:
|
||||
|
||||
@ -54,10 +102,12 @@ public:
|
||||
void onUseDistChanged();
|
||||
void onUseVignChanged();
|
||||
void onUseCAChanged();
|
||||
void setLensGeomRef( LensGeometry *foo)
|
||||
{
|
||||
lensgeomLcpFill = foo ;
|
||||
};
|
||||
|
||||
void setBatchMode(bool yes);
|
||||
|
||||
void onLensfunCameraChanged();
|
||||
void onLensfunLensChanged();
|
||||
void onCorrModeChanged();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <locale.h>
|
||||
#include <lensfun.h>
|
||||
#include "options.h"
|
||||
#include "soundman.h"
|
||||
#include "rtimage.h"
|
||||
@ -139,6 +140,7 @@ int processLineParams ( int argc, char **argv )
|
||||
#endif
|
||||
|
||||
case 'v':
|
||||
std::cout << "Using lensfun " << LF_VERSION_MAJOR << "." << LF_VERSION_MINOR << "." << LF_VERSION_MICRO << "." << LF_VERSION_BUGFIX << std::endl;
|
||||
return 0;
|
||||
|
||||
#ifndef __APPLE__ // TODO agriggio - there seems to be already some "single instance app" support for OSX in rtwindow. Disabling it here until I understand how to merge the two
|
||||
|
@ -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;
|
||||
@ -921,6 +926,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;
|
||||
@ -2259,6 +2269,26 @@ void ParamsEdited::combine (rtengine::procparams::ProcParams& toEdit, const rten
|
||||
toEdit.lensProf.useCA = mods.lensProf.useCA;
|
||||
}
|
||||
|
||||
if (lensProf.useLensfun) {
|
||||
toEdit.lensProf.useLensfun = mods.lensProf.useLensfun;
|
||||
}
|
||||
|
||||
if (lensProf.lfAutoMatch) {
|
||||
toEdit.lensProf.lfAutoMatch = mods.lensProf.lfAutoMatch;
|
||||
}
|
||||
|
||||
if (lensProf.lfCameraMake) {
|
||||
toEdit.lensProf.lfCameraMake = mods.lensProf.lfCameraMake;
|
||||
}
|
||||
|
||||
if (lensProf.lfCameraModel) {
|
||||
toEdit.lensProf.lfCameraModel = mods.lensProf.lfCameraModel;
|
||||
}
|
||||
|
||||
if (lensProf.lfLens) {
|
||||
toEdit.lensProf.lfLens = mods.lensProf.lfLens;
|
||||
}
|
||||
|
||||
if (perspective.horizontal) {
|
||||
toEdit.perspective.horizontal = dontforceSet && options.baBehav[ADDSET_PERSPECTIVE] ? toEdit.perspective.horizontal + mods.perspective.horizontal : mods.perspective.horizontal;
|
||||
}
|
||||
|
@ -525,6 +525,7 @@ class LensProfParamsEdited
|
||||
{
|
||||
public:
|
||||
bool lcpFile, useDist, useVign, useCA;
|
||||
bool useLensfun, lfAutoMatch, lfCameraMake, lfCameraModel, lfLens;
|
||||
|
||||
bool isUnchanged() const;
|
||||
};
|
||||
|
@ -18,7 +18,6 @@
|
||||
*/
|
||||
|
||||
#include <gtkmm.h>
|
||||
#include <regex>
|
||||
#include "rtwindow.h"
|
||||
#include "options.h"
|
||||
#include "preferences.h"
|
||||
@ -315,23 +314,14 @@ void RTWindow::on_realize ()
|
||||
|
||||
// Display release notes only if new major version.
|
||||
// Pattern matches "5.1" from "5.1-23-g12345678"
|
||||
std::string vs[] = {versionString, options.version};
|
||||
std::regex pat ("(^[0-9.]+).*");
|
||||
std::smatch sm;
|
||||
const std::string vs[] = {versionString, options.version};
|
||||
std::vector<std::string> vMajor;
|
||||
|
||||
for (const auto& v : vs) {
|
||||
if (std::regex_match (v, sm, pat)) {
|
||||
if (sm.size() == 2) {
|
||||
std::ssub_match smsub = sm[1];
|
||||
vMajor.push_back (smsub.str());
|
||||
}
|
||||
}
|
||||
vMajor.emplace_back(v, 0, v.find_first_not_of("0123456789."));
|
||||
}
|
||||
|
||||
if (vMajor.size() == 2) {
|
||||
if (vMajor[0] != vMajor[1]) {
|
||||
|
||||
if (vMajor.size() == 2 && vMajor[0] != vMajor[1]) {
|
||||
// Update the version parameter with the right value
|
||||
options.version = versionString;
|
||||
|
||||
@ -348,7 +338,6 @@ void RTWindow::on_realize ()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool RTWindow::on_configure_event (GdkEventConfigure* event)
|
||||
{
|
||||
|
@ -603,7 +603,8 @@ rtengine::IImage8* Thumbnail::processThumbImage (const rtengine::procparams::Pro
|
||||
image = tpp->quickProcessImage (pparams, h, rtengine::TI_Nearest, scale);
|
||||
} else {
|
||||
// Full thumbnail: apply profile
|
||||
image = tpp->processImage (pparams, h, rtengine::TI_Bilinear, cfs.getCamera(), cfs.focalLen, cfs.focalLen35mm, cfs.focusDist, cfs.shutter, cfs.fnumber, cfs.iso, cfs.expcomp, scale );
|
||||
// image = tpp->processImage (pparams, h, rtengine::TI_Bilinear, cfs.getCamera(), cfs.focalLen, cfs.focalLen35mm, cfs.focusDist, cfs.shutter, cfs.fnumber, cfs.iso, cfs.expcomp, scale );
|
||||
image = tpp->processImage (pparams, h, rtengine::TI_Bilinear, &cfs, scale );
|
||||
}
|
||||
|
||||
tpp->getDimensions(lastW, lastH, lastScale);
|
||||
@ -628,7 +629,8 @@ rtengine::IImage8* Thumbnail::upgradeThumbImage (const rtengine::procparams::Pro
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
rtengine::IImage8* image = tpp->processImage (pparams, h, rtengine::TI_Bilinear, cfs.getCamera(), cfs.focalLen, cfs.focalLen35mm, cfs.focusDist, cfs.shutter, cfs.fnumber, cfs.iso, cfs.expcomp, scale );
|
||||
// rtengine::IImage8* image = tpp->processImage (pparams, h, rtengine::TI_Bilinear, cfs.getCamera(), cfs.focalLen, cfs.focalLen35mm, cfs.focusDist, cfs.shutter, cfs.fnumber, cfs.iso, cfs.expcomp, scale );
|
||||
rtengine::IImage8* image = tpp->processImage (pparams, h, rtengine::TI_Bilinear, &cfs, scale );
|
||||
tpp->getDimensions(lastW, lastH, lastScale);
|
||||
|
||||
delete tpp;
|
||||
|
@ -54,7 +54,6 @@ ToolPanelCoordinator::ToolPanelCoordinator () : ipc (nullptr), hasChanged (false
|
||||
colortoning = Gtk::manage (new ColorToning ());
|
||||
lensgeom = Gtk::manage (new LensGeometry ());
|
||||
lensProf = Gtk::manage (new LensProfilePanel ());
|
||||
lensProf->setLensGeomRef (lensgeom);
|
||||
distortion = Gtk::manage (new Distortion ());
|
||||
rotate = Gtk::manage (new Rotate ());
|
||||
vibrance = Gtk::manage (new Vibrance ());
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include "xtransprocess.h"
|
||||
#include "options.h"
|
||||
#include "guiutils.h"
|
||||
#include <regex>
|
||||
|
||||
using namespace rtengine;
|
||||
using namespace rtengine::procparams;
|
||||
|
||||
@ -30,8 +30,30 @@ XTransProcess::XTransProcess () : FoldableToolPanel(this, "xtransprocess", M("TP
|
||||
method = Gtk::manage (new MyComboBoxText ());
|
||||
|
||||
for( size_t i = 0; i < procparams::RAWParams::XTransSensor::numMethods; i++) {
|
||||
static const std::regex what ("[() -]");
|
||||
const std::string langKey = std::regex_replace (procparams::RAWParams::XTransSensor::methodstring[i], what, "");
|
||||
const std::string langKey =
|
||||
[i]() -> std::string
|
||||
{
|
||||
const std::string str(procparams::RAWParams::XTransSensor::methodstring[i]);
|
||||
|
||||
std::string res;
|
||||
for (const auto& c : str) {
|
||||
switch (c) {
|
||||
case '(':
|
||||
case ')':
|
||||
case ' ':
|
||||
case '-': {
|
||||
continue;
|
||||
}
|
||||
|
||||
default: {
|
||||
res += c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}();
|
||||
method->append(M("TP_RAW_" + Glib::ustring(langKey).uppercase()));
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user