From f9a8875bb5a15465aaf48c57fd74d70dd13c2f8b Mon Sep 17 00:00:00 2001 From: Lawrence Date: Fri, 27 Dec 2019 16:40:41 -0800 Subject: [PATCH] Add more perspective correction adjusters Add camera lens/sensor shift support with horizontal/vertical shift adjusters. Add shifting and rotation of corrected image. This allows post-correction adjustments to be made more easily given the fixed image canvas size. Add scaling of final result. This also helps reduce frustrations with the fixed image canvas size. Replace field of view with focal length and crop factor. Use of focal length and crop factor is more common than diagonal angular field of view. The new adjusters should be more intuitive for most photographers. The implementation of perspective correction uses a focal length relative to the image dimensions. The existing code calculates that focal length with trigonometry. The new code does it by multiplying by a ratio. Replace vertical bias with horizontal and vertical perspective distortion recovery. Vertical bias is not intuitive as it causes vertical lines to converge off-center if horizontal correction is applied. The new adjusters perform perspective distortion on the projection of the corrected image, allowing vertical/horizontal lines to converge towards the center lines of the image. Refactor perspective transformation math to use dynamically computed homogeneous coordinate matrices instead of pre-calculated formulas. This should add some overhead, but results in more maintainable code and possible improved performance due to the reduced number of arithmetic and assignments needed for each pixel. Integrate new adjusters in the GUI. This includes fine granularity for batch processing add/set modes and history. --- rtdata/languages/default | 18 ++- rtengine/iptransform.cc | 205 +++++++++++++++++++++----------- rtengine/procevents.h | 6 + rtengine/procparams.cc | 48 ++++++-- rtengine/procparams.h | 12 +- rtengine/refreshmap.cc | 8 +- rtgui/addsetids.h | 6 + rtgui/batchtoolpanelcoord.cc | 10 +- rtgui/paramsedited.cc | 64 ++++++++-- rtgui/paramsedited.h | 12 +- rtgui/perspective.cc | 223 ++++++++++++++++++++++++++++++----- rtgui/perspective.h | 14 ++- rtgui/preferences.cc | 8 +- 13 files changed, 502 insertions(+), 132 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index 376eb6072..776074d5e 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -727,6 +727,12 @@ HISTORY_MSG_491;White Balance HISTORY_MSG_492;RGB Curves HISTORY_MSG_493;L*a*b* Adjustments HISTORY_MSG_494;Capture Sharpening +HISTORY_MSG_496;Perspective - Camera +HISTORY_MSG_497;Perspective - Camera +HISTORY_MSG_498;Perspective - Recovery +HISTORY_MSG_499;Perspective - PCA - Rotation +HISTORY_MSG_500;Perspective - PCA - Scale +HISTORY_MSG_501;Perspective - PCA - Shift HISTORY_MSG_CLAMPOOG;Clip out-of-gamut colors HISTORY_MSG_COLORTONING_LABGRID_VALUE;CT - Color correction HISTORY_MSG_COLORTONING_LABREGION_AB;CT - Color correction @@ -1803,11 +1809,19 @@ TP_PCVIGNETTE_ROUNDNESS_TOOLTIP;Roundness:\n0 = rectangle,\n50 = fitted ellipse, TP_PCVIGNETTE_STRENGTH;Strength TP_PCVIGNETTE_STRENGTH_TOOLTIP;Filter strength in stops (reached in corners). TP_PDSHARPENING_LABEL;Capture Sharpening -TP_PERSPECTIVE_FOV;Field of view +TP_PERSPECTIVE_CAMERA_CROP_FACTOR;Crop factor +TP_PERSPECTIVE_CAMERA_FOCAL_LENGTH;Focal length +TP_PERSPECTIVE_CAMERA_SHIFT_HORIZONTAL;Horizontal shift +TP_PERSPECTIVE_CAMERA_SHIFT_VERTICAL;Vertical shift TP_PERSPECTIVE_HORIZONTAL;Horizontal TP_PERSPECTIVE_LABEL;Perspective +TP_PERSPECTIVE_PROJECTION_PITCH;Vertical +TP_PERSPECTIVE_PROJECTION_ROTATE;Rotation +TP_PERSPECTIVE_PROJECTION_SCALE;Scale +TP_PERSPECTIVE_PROJECTION_SHIFT_HORIZONTAL;Horizontal shift +TP_PERSPECTIVE_PROJECTION_SHIFT_VERTICAL;Vertical shift +TP_PERSPECTIVE_PROJECTION_YAW;Horizontal TP_PERSPECTIVE_VERTICAL;Vertical -TP_PERSPECTIVE_VERTICAL_BIAS;Vertical bias TP_PFCURVE_CURVEEDITOR_CH;Hue TP_PFCURVE_CURVEEDITOR_CH_TOOLTIP;Controls defringe strength by color.\nHigher = more,\nLower = less. TP_PREPROCESS_DEADPIXFILT;Dead pixel filter diff --git a/rtengine/iptransform.cc b/rtengine/iptransform.cc index 7e509d584..46c0601e0 100644 --- a/rtengine/iptransform.cc +++ b/rtengine/iptransform.cc @@ -21,6 +21,7 @@ #include "imagefloat.h" #include "improcfun.h" +#include "homogeneouscoordinates.h" #include "procparams.h" #include "rt_math.h" #include "rtengine.h" @@ -203,6 +204,84 @@ namespace rtengine #define CLIPTOC(a,b,c,d) ((a)>=(b)?((a)<=(c)?(a):(d=true,(c))):(d=true,(b))) +/** + * Creates an inverse transformation matrix for camera-geometry-based + * perspective correction. Unless otherwise specified, units are the same as the + * units of the vectors which the matrix will transform. The projection_* + * parameters are applied in the order they appear. + * @param camera_focal_length Camera's focal length. + * @param camera_shift_horiz Camera lens's shift to the right. + * @param camera_shift_vert Camera lens's shift upwards. + * @param camera_pitch Camera's pitch in radians. Up is positive. + * @param camera_yaw Camera's yaw in radians. Right is positive. + * Up is positive. + * @param projection_shift_horiz Shift of perspective-corrected image to the + * right. + * @param projection_shift_vert Shift of perspective-corrected image upwards. + * @param projection_rotate Rotation of perspective-corrected image + * counter-clockwise in radians. + * @param projection_yaw Yaw in radians of simulated perspective distortion. + * Right is positive. + * @param projection_pitch Pitch in radians of simulated perspective distortion. + * Up is positive. + * @param projection_scale Scale factor of perspective-corrected image. + */ +homogeneous::Matrix perspectiveMatrix(double camera_focal_length, double + camera_shift_horiz, double camera_shift_vert, double camera_pitch, + double camera_yaw, double projection_yaw, double projection_pitch, + double projection_rotate, double projection_shift_horiz, double + projection_shift_vert, double projection_scale) +{ + const double projection_scale_inverse = 1.0 / projection_scale; + homogeneous::Vector center; + center[0] = 0; + center[1] = 0; + center[2] = camera_focal_length; + center[3] = 1; + + // Locations of image center after rotations. + const homogeneous::Vector camera_center_yaw_pitch = + homogeneous::rotationMatrix(camera_yaw, homogeneous::Axis::Y) * + homogeneous::rotationMatrix(camera_pitch, homogeneous::Axis::X) * + center; + const homogeneous::Vector projection_center_yaw_pitch = + homogeneous::rotationMatrix(-projection_yaw, homogeneous::Axis::Y) * + homogeneous::rotationMatrix(-projection_pitch, homogeneous::Axis::X) * + center; + + // The following comments refer to the forward transformation. + const homogeneous::Matrix matrix = + // Lens/sensor shift and move to z == camera_focal_length. + homogeneous::translationMatrix(-camera_shift_horiz, + -camera_shift_vert, -camera_focal_length) * + // Perspective correction. + homogeneous::projectionMatrix(camera_focal_length, homogeneous::Axis::Z) * + homogeneous::rotationMatrix(-camera_pitch, homogeneous::Axis::X) * + homogeneous::rotationMatrix(-camera_yaw, homogeneous::Axis::Y) * + // Re-center after perspective rotation. + homogeneous::translationMatrix(camera_center_yaw_pitch[0], + camera_center_yaw_pitch[1], camera_center_yaw_pitch[2] - camera_focal_length) * + // Translate corrected image. + homogeneous::translationMatrix(-projection_shift_horiz, + -projection_shift_vert, 0) * + // Rotate corrected image. + homogeneous::rotationMatrix(projection_rotate, homogeneous::Axis::Z) * + // Un-center for perspective rotation. + homogeneous::translationMatrix(projection_center_yaw_pitch[0], + projection_center_yaw_pitch[1], camera_focal_length - projection_center_yaw_pitch[2]) * + // Simulate perspective transformation. + homogeneous::projectionMatrix(projection_center_yaw_pitch[2], homogeneous::Axis::Z) * + homogeneous::rotationMatrix(projection_yaw, homogeneous::Axis::Y) * + homogeneous::rotationMatrix(projection_pitch, homogeneous::Axis::X) * + // Move to z == 0. + homogeneous::translationMatrix(0, 0, camera_focal_length) * + // Scale corrected image. + homogeneous::scaleMatrix(projection_scale_inverse, + projection_scale_inverse, 1); + + return matrix; +} + bool ImProcFunctions::transCoord (int W, int H, const std::vector &src, std::vector &red, std::vector &green, std::vector &blue, double ascaleDef, const LensCorrection *pLCPMap) const { @@ -239,34 +318,24 @@ bool ImProcFunctions::transCoord (int W, int H, const std::vector &src, double ascale = ascaleDef > 0 ? ascaleDef : (params->commonTrans.autofill ? getTransformAutoFill (oW, oH, pLCPMap) : 1.0); // auxiliary variables for perspective correction - const double f = maxRadius / tan(params->perspective.fov / 360.0 * rtengine::RT_PI); - const double phtheta = params->perspective.horizontal / -180.0 * rtengine::RT_PI; - const double pvtheta = params->perspective.vertical / -180.0 * rtengine::RT_PI; - const double pbtheta = params->perspective.vBias / -180.0 * rtengine::RT_PI; - const double phcos = cos(phtheta); - const double pvcos = cos(pvtheta); - const double pbcos = cos(pbtheta); - const double phsin = sin(phtheta); - const double pvsin = sin(pvtheta); - const double pbsin = sin(pbtheta); - // Coordinates of distorted image center. - const double pxoffset = f * phsin * pvcos; - const double pyoffset = -f * (phcos * pvcos * pbsin + pvsin * pbcos); - const double pz = f * (phcos * pvcos * pbcos - pvsin * pbsin); - // Inverse transformation matrix. - const double p_xx = f * phcos; - const double p_xy = f * phsin * pbsin; - const double p_xz = f * phsin * pbcos; - const double p_yx = f * phsin * pvsin; - const double p_yy = f * (pvcos * pbcos - phcos * pvsin * pbsin); - const double p_yz = f * (-pvcos * pbsin - phcos * pvsin * pbcos); - const double p_zx = -phsin * pvcos; - const double p_zy = phcos * pvcos * pbsin + pvsin * pbcos; - const double p_zz = phcos * pvcos * pbcos - pvsin * pbsin; - // z is known, can calculate these in advance. - const double pz_xz = pz * p_xz; - const double pz_yz = pz * p_yz; - const double pz_zz = pz * p_zz; + const double f = params->perspective.camera_focal_length * + params->perspective.camera_crop_factor * (maxRadius / sqrt(18.0*18.0 + + 12.0*12.0)); + const double p_camera_yaw = params->perspective.horizontal / 180.0 * rtengine::RT_PI; + const double p_camera_pitch = params->perspective.vertical / 180.0 * rtengine::RT_PI; + const double p_camera_shift_horiz = oW / 100.0 * params->perspective.camera_shift_horiz; + const double p_camera_shift_vert = oH / -100.0 * params->perspective.camera_shift_vert; + const double p_projection_shift_horiz = oW / 100.0 * params->perspective.projection_shift_horiz; + const double p_projection_shift_vert = oH / -100.0 * params->perspective.projection_shift_vert; + const double p_projection_rotate = params->perspective.projection_rotate * rtengine::RT_PI_180; + const double p_projection_yaw = -params->perspective.projection_yaw * rtengine::RT_PI_180; + const double p_projection_pitch = -params->perspective.projection_pitch * rtengine::RT_PI_180; + const double p_projection_scale = params->perspective.projection_scale; + const homogeneous::Matrix p_matrix = perspectiveMatrix(f, + p_camera_shift_horiz, p_camera_shift_vert, p_camera_pitch, + p_camera_yaw, p_projection_yaw, p_projection_pitch, + p_projection_rotate, p_projection_shift_horiz, + p_projection_shift_vert, p_projection_scale); for (size_t i = 0; i < src.size(); i++) { double x_d = src[i].x, y_d = src[i].y; @@ -282,13 +351,11 @@ bool ImProcFunctions::transCoord (int W, int H, const std::vector &src, y_d += ascale * (0 - h2); // centering y coord & scale if (needsPerspective()) { - x_d -= pxoffset; - y_d -= pyoffset; - const double normalizer = p_zx * x_d + p_zy * y_d + pz_zz; - const double x_d_new = p_xx * x_d + p_xy * y_d + pz_xz; - y_d = p_yx * x_d + p_yy * y_d + pz_yz; - x_d = x_d_new / normalizer; - y_d /= normalizer; + const double w = p_matrix[3][0] * x_d + p_matrix[3][1] * y_d + p_matrix[3][3]; + const double xw = p_matrix[0][0] * x_d + p_matrix[0][1] * y_d + p_matrix[0][3]; + const double yw = p_matrix[1][0] * x_d + p_matrix[1][1] * y_d + p_matrix[1][3]; + x_d = xw / w; + y_d = yw / w; } // rotate @@ -928,34 +995,24 @@ void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, I const double centerFactory = cy - h2; // auxiliary variables for perspective correction - const double f = maxRadius / tan(params->perspective.fov / 360.0 * rtengine::RT_PI); - const double phtheta = params->perspective.horizontal / -180.0 * rtengine::RT_PI; - const double pvtheta = params->perspective.vertical / -180.0 * rtengine::RT_PI; - const double pbtheta = params->perspective.vBias / -180.0 * rtengine::RT_PI; - const double phcos = cos(phtheta); - const double pvcos = cos(pvtheta); - const double pbcos = cos(pbtheta); - const double phsin = sin(phtheta); - const double pvsin = sin(pvtheta); - const double pbsin = sin(pbtheta); - // Coordinates of distorted image center. - const double pxoffset = f * phsin * pvcos; - const double pyoffset = -f * (phcos * pvcos * pbsin + pvsin * pbcos); - const double pz = f * (phcos * pvcos * pbcos - pvsin * pbsin); - // Inverse transformation matrix. - const double p_xx = f * phcos; - const double p_xy = f * phsin * pbsin; - const double p_xz = f * phsin * pbcos; - const double p_yx = f * phsin * pvsin; - const double p_yy = f * (pvcos * pbcos - phcos * pvsin * pbsin); - const double p_yz = f * (-pvcos * pbsin - phcos * pvsin * pbcos); - const double p_zx = -phsin * pvcos; - const double p_zy = phcos * pvcos * pbsin + pvsin * pbcos; - const double p_zz = phcos * pvcos * pbcos - pvsin * pbsin; - // z is known, can calculate these in advance. - const double pz_xz = pz * p_xz; - const double pz_yz = pz * p_yz; - const double pz_zz = pz * p_zz; + const double f = params->perspective.camera_focal_length * + params->perspective.camera_crop_factor * (maxRadius / sqrt(18.0*18.0 + + 12.0*12.0)); + const double p_camera_yaw = params->perspective.horizontal / 180.0 * rtengine::RT_PI; + const double p_camera_pitch = params->perspective.vertical / 180.0 * rtengine::RT_PI; + const double p_camera_shift_horiz = oW / 100.0 * params->perspective.camera_shift_horiz; + const double p_camera_shift_vert = oH / -100.0 * params->perspective.camera_shift_vert; + const double p_projection_shift_horiz = oW / 100.0 * params->perspective.projection_shift_horiz; + const double p_projection_shift_vert = oH / -100.0 * params->perspective.projection_shift_vert; + const double p_projection_rotate = params->perspective.projection_rotate * rtengine::RT_PI_180; + const double p_projection_yaw = -params->perspective.projection_yaw * rtengine::RT_PI_180; + const double p_projection_pitch = -params->perspective.projection_pitch * rtengine::RT_PI_180; + const double p_projection_scale = params->perspective.projection_scale; + const homogeneous::Matrix p_matrix = perspectiveMatrix(f, + p_camera_shift_horiz, p_camera_shift_vert, p_camera_pitch, + p_camera_yaw, p_projection_yaw, p_projection_pitch, + p_projection_rotate, p_projection_shift_horiz, + p_projection_shift_vert, p_projection_scale); // main cycle #ifdef _OPENMP @@ -978,13 +1035,11 @@ void ImProcFunctions::transformGeneral(bool highQuality, Imagefloat *original, I y_d += ascale * centerFactory; // centering y coord & scale if (enablePerspective) { - x_d -= pxoffset; - y_d -= pyoffset; - const double normalizer = p_zx * x_d + p_zy * y_d + pz_zz; - const double x_d_new = p_xx * x_d + p_xy * y_d + pz_xz; - y_d = p_yx * x_d + p_yy * y_d + pz_yz; - x_d = x_d_new / normalizer; - y_d /= normalizer; + const double w = p_matrix[3][0] * x_d + p_matrix[3][1] * y_d + p_matrix[3][3]; + const double xw = p_matrix[0][0] * x_d + p_matrix[0][1] * y_d + p_matrix[0][3]; + const double yw = p_matrix[1][0] * x_d + p_matrix[1][1] * y_d + p_matrix[1][3]; + x_d = xw / w; + y_d = yw / w; } // rotate @@ -1182,7 +1237,15 @@ bool ImProcFunctions::needsRotation () const bool ImProcFunctions::needsPerspective () const { - return params->perspective.horizontal || params->perspective.vertical || params->perspective.vBias; + return params->perspective.horizontal || params->perspective.vertical || + params->perspective.camera_shift_horiz || + params->perspective.camera_shift_vert || + params->perspective.projection_pitch || + params->perspective.projection_rotate || + params->perspective.projection_scale != 1.0 || + params->perspective.projection_shift_horiz || + params->perspective.projection_shift_vert || + params->perspective.projection_yaw; } bool ImProcFunctions::needsGradient () const diff --git a/rtengine/procevents.h b/rtengine/procevents.h index 1b00d4218..dddfdea30 100644 --- a/rtengine/procevents.h +++ b/rtengine/procevents.h @@ -518,6 +518,12 @@ enum ProcEventCode { EvLEnabled = 492, EvPdShrEnabled = 493, EvPdShrMaskToggled = 494, + EvPerspCamFocalLength = 495, + EvPerspCamShift = 496, + EvPerspProjAngle = 497, + EvPerspProjRotate = 498, + EvPerspProjScale = 499, + EvPerspProjShift = 500, NUMOFEVENTS diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 16f06b71f..dbabc9165 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -1852,8 +1852,16 @@ LensProfParams::LcMode LensProfParams::getMethodNumber(const Glib::ustring& mode PerspectiveParams::PerspectiveParams() : horizontal(0.0), vertical(0.0), - vBias(0.0), - fov(65.0) + camera_crop_factor(1.0), + camera_focal_length(24.0), + camera_shift_horiz(0.0), + camera_shift_vert(0.0), + projection_pitch(0.0), + projection_rotate(0.0), + projection_scale(1.0), + projection_shift_horiz(0.0), + projection_shift_vert(0.0), + projection_yaw(0.0) { } @@ -1862,8 +1870,16 @@ bool PerspectiveParams::operator ==(const PerspectiveParams& other) const return horizontal == other.horizontal && vertical == other.vertical - && vBias == other.vBias - && fov == other.fov; + && camera_focal_length == other.camera_focal_length + && camera_crop_factor == other.camera_crop_factor + && camera_shift_horiz == other.camera_shift_horiz + && camera_shift_vert == other.camera_shift_vert + && projection_shift_horiz == other.projection_shift_horiz + && projection_shift_vert == other.projection_shift_vert + && projection_scale == other.projection_scale + && projection_rotate == other.projection_rotate + && projection_pitch == other.projection_pitch + && projection_yaw == other.projection_yaw; } bool PerspectiveParams::operator !=(const PerspectiveParams& other) const @@ -3347,8 +3363,16 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo // Perspective correction saveToKeyfile(!pedited || pedited->perspective.horizontal, "Perspective", "Horizontal", perspective.horizontal, keyFile); saveToKeyfile(!pedited || pedited->perspective.vertical, "Perspective", "Vertical", perspective.vertical, keyFile); - saveToKeyfile(!pedited || pedited->perspective.vBias, "Perspective", "VerticalBias", perspective.vBias, keyFile); - saveToKeyfile(!pedited || pedited->perspective.fov, "Perspective", "FOV", perspective.fov, keyFile); + saveToKeyfile(!pedited || pedited->perspective.camera_crop_factor, "Perspective", "CameraCropFactor", perspective.camera_crop_factor, keyFile); + saveToKeyfile(!pedited || pedited->perspective.camera_focal_length, "Perspective", "CameraFocalLength", perspective.camera_focal_length, keyFile); + saveToKeyfile(!pedited || pedited->perspective.camera_shift_horiz, "Perspective", "CameraShiftHorizontal", perspective.camera_shift_horiz, keyFile); + saveToKeyfile(!pedited || pedited->perspective.camera_shift_vert, "Perspective", "CameraShiftVertical", perspective.camera_shift_vert, keyFile); + saveToKeyfile(!pedited || pedited->perspective.projection_pitch, "Perspective", "ProjectionPitch", perspective.projection_pitch, keyFile); + saveToKeyfile(!pedited || pedited->perspective.projection_rotate, "Perspective", "ProjectionRotate", perspective.projection_rotate, keyFile); + saveToKeyfile(!pedited || pedited->perspective.projection_scale, "Perspective", "ProjectionScale", perspective.projection_scale, keyFile); + saveToKeyfile(!pedited || pedited->perspective.projection_shift_horiz, "Perspective", "ProjectionShiftHorizontal", perspective.projection_shift_horiz, keyFile); + saveToKeyfile(!pedited || pedited->perspective.projection_shift_vert, "Perspective", "ProjectionShiftVertical", perspective.projection_shift_vert, keyFile); + saveToKeyfile(!pedited || pedited->perspective.projection_yaw, "Perspective", "ProjectionYaw", perspective.projection_yaw, keyFile); // Gradient saveToKeyfile(!pedited || pedited->gradient.enabled, "Gradient", "Enabled", gradient.enabled, keyFile); @@ -4426,8 +4450,16 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) if (keyFile.has_group("Perspective")) { assignFromKeyfile(keyFile, "Perspective", "Horizontal", pedited, perspective.horizontal, pedited->perspective.horizontal); assignFromKeyfile(keyFile, "Perspective", "Vertical", pedited, perspective.vertical, pedited->perspective.vertical); - assignFromKeyfile(keyFile, "Perspective", "VerticalBias", pedited, perspective.vBias, pedited->perspective.vBias); - assignFromKeyfile(keyFile, "Perspective", "FOV", pedited, perspective.fov, pedited->perspective.fov); + assignFromKeyfile(keyFile, "Perspective", "CameraShiftHorizontal", pedited, perspective.camera_shift_horiz, pedited->perspective.camera_shift_horiz); + assignFromKeyfile(keyFile, "Perspective", "CameraShiftVertical", pedited, perspective.camera_shift_vert, pedited->perspective.camera_shift_vert); + assignFromKeyfile(keyFile, "Perspective", "CameraCropFactor", pedited, perspective.camera_crop_factor, pedited->perspective.camera_crop_factor); + assignFromKeyfile(keyFile, "Perspective", "CameraFocalLength", pedited, perspective.camera_focal_length, pedited->perspective.camera_focal_length); + assignFromKeyfile(keyFile, "Perspective", "ProjectionPitch", pedited, perspective.projection_pitch, pedited->perspective.projection_pitch); + assignFromKeyfile(keyFile, "Perspective", "ProjectionRotate", pedited, perspective.projection_rotate, pedited->perspective.projection_rotate); + assignFromKeyfile(keyFile, "Perspective", "ProjectionScale", pedited, perspective.projection_scale, pedited->perspective.projection_scale); + assignFromKeyfile(keyFile, "Perspective", "ProjectionShiftHorizontal", pedited, perspective.projection_shift_horiz, pedited->perspective.projection_shift_horiz); + assignFromKeyfile(keyFile, "Perspective", "ProjectionShiftVertical", pedited, perspective.projection_shift_vert, pedited->perspective.projection_shift_vert); + assignFromKeyfile(keyFile, "Perspective", "ProjectionYaw", pedited, perspective.projection_yaw, pedited->perspective.projection_yaw); } if (keyFile.has_group("Gradient")) { diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 956a0ac0c..eb251a9d0 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -907,8 +907,16 @@ struct LensProfParams { struct PerspectiveParams { double horizontal; double vertical; - double vBias; - double fov; + double camera_crop_factor; + double camera_focal_length; + double camera_shift_horiz; + double camera_shift_vert; + double projection_pitch; + double projection_rotate; + double projection_scale; + double projection_shift_horiz; + double projection_shift_vert; + double projection_yaw; PerspectiveParams(); diff --git a/rtengine/refreshmap.cc b/rtengine/refreshmap.cc index b77eac29c..aeb783ae5 100644 --- a/rtengine/refreshmap.cc +++ b/rtengine/refreshmap.cc @@ -521,7 +521,13 @@ int refreshmap[rtengine::NUMOFEVENTS] = { RGBCURVE, // EvRGBEnabled LUMINANCECURVE, // EvLEnabled DEMOSAIC, // EvPdShrEnabled - CAPTURESHARPEN // EvPdShrMaskToggled + CAPTURESHARPEN, // EvPdShrMaskToggled + TRANSFORM, // EvPerspCamFocalLength + TRANSFORM, // EvPerspCamShift + TRANSFORM, // EvPerspProjAngle + TRANSFORM, // EvPerspProjRotate + TRANSFORM, // EvPerspProjScale + TRANSFORM // EvPerspProjShift }; diff --git a/rtgui/addsetids.h b/rtgui/addsetids.h index 05150517f..dd21f9a89 100644 --- a/rtgui/addsetids.h +++ b/rtgui/addsetids.h @@ -18,6 +18,12 @@ enum { ADDSET_ROTATE_DEGREE, ADDSET_DIST_AMOUNT, ADDSET_PERSPECTIVE, + ADDSET_PERSP_CAM_FOCAL_LENGTH, + ADDSET_PERSP_CAM_SHIFT, + ADDSET_PERSP_PROJ_ANGLE, + ADDSET_PERSP_PROJ_ROTATE, + ADDSET_PERSP_PROJ_SCALE, + ADDSET_PERSP_PROJ_SHIFT, ADDSET_CA, ADDSET_VIGN_AMOUNT, ADDSET_VIGN_RADIUS, diff --git a/rtgui/batchtoolpanelcoord.cc b/rtgui/batchtoolpanelcoord.cc index 2824a285c..da7073b71 100644 --- a/rtgui/batchtoolpanelcoord.cc +++ b/rtgui/batchtoolpanelcoord.cc @@ -151,7 +151,7 @@ void BatchToolPanelCoordinator::initSession () rotate->setAdjusterBehavior (false); resize->setAdjusterBehavior (false); distortion->setAdjusterBehavior (false); - perspective->setAdjusterBehavior (false); + perspective->setAdjusterBehavior (false, false, false, false, false, false, false); gradient->setAdjusterBehavior (false, false, false, false); pcvignette->setAdjusterBehavior (false, false, false); cacorrection->setAdjusterBehavior (false); @@ -196,7 +196,7 @@ void BatchToolPanelCoordinator::initSession () rotate->setAdjusterBehavior (options.baBehav[ADDSET_ROTATE_DEGREE]); resize->setAdjusterBehavior (options.baBehav[ADDSET_RESIZE_SCALE]); distortion->setAdjusterBehavior (options.baBehav[ADDSET_DIST_AMOUNT]); - perspective->setAdjusterBehavior (options.baBehav[ADDSET_PERSPECTIVE]); + perspective->setAdjusterBehavior (options.baBehav[ADDSET_PERSPECTIVE], options.baBehav[ADDSET_PERSP_CAM_FOCAL_LENGTH], options.baBehav[ADDSET_PERSP_CAM_SHIFT], options.baBehav[ADDSET_PERSP_PROJ_ANGLE], options.baBehav[ADDSET_PERSP_PROJ_SHIFT], options.baBehav[ADDSET_PERSP_PROJ_ROTATE], options.baBehav[ADDSET_PERSP_PROJ_SCALE]); gradient->setAdjusterBehavior (options.baBehav[ADDSET_GRADIENT_DEGREE], options.baBehav[ADDSET_GRADIENT_FEATHER], options.baBehav[ADDSET_GRADIENT_STRENGTH], options.baBehav[ADDSET_GRADIENT_CENTER]); pcvignette->setAdjusterBehavior (options.baBehav[ADDSET_PCVIGNETTE_STRENGTH], options.baBehav[ADDSET_PCVIGNETTE_FEATHER], options.baBehav[ADDSET_PCVIGNETTE_ROUNDNESS]); cacorrection->setAdjusterBehavior (options.baBehav[ADDSET_CA]); @@ -308,6 +308,12 @@ void BatchToolPanelCoordinator::initSession () if (options.baBehav[ADDSET_RESIZE_SCALE]) { pparams.resize.scale = 0; } if (options.baBehav[ADDSET_DIST_AMOUNT]) { pparams.distortion.amount = 0; } if (options.baBehav[ADDSET_PERSPECTIVE]) { pparams.perspective.horizontal = pparams.perspective.vertical = 0; } + if (options.baBehav[ADDSET_PERSP_CAM_FOCAL_LENGTH]) { pparams.perspective.camera_focal_length = pparams.perspective.camera_crop_factor = 0; } + if (options.baBehav[ADDSET_PERSP_CAM_SHIFT]) { pparams.perspective.camera_shift_horiz = pparams.perspective.camera_shift_vert = 0; } + if (options.baBehav[ADDSET_PERSP_PROJ_ANGLE]) { pparams.perspective.projection_yaw = pparams.perspective.projection_pitch = 0; } + if (options.baBehav[ADDSET_PERSP_PROJ_SHIFT]) { pparams.perspective.projection_shift_horiz = pparams.perspective.projection_shift_vert = 0; } + if (options.baBehav[ADDSET_PERSP_PROJ_ROTATE]) { pparams.perspective.projection_rotate = 0; } + if (options.baBehav[ADDSET_PERSP_PROJ_SCALE]) { pparams.perspective.projection_scale = 0; } if (options.baBehav[ADDSET_GRADIENT_DEGREE]) { pparams.gradient.degree = 0; } if (options.baBehav[ADDSET_GRADIENT_FEATHER]) { pparams.gradient.feather = 0; } if (options.baBehav[ADDSET_GRADIENT_STRENGTH]) { pparams.gradient.strength = 0; } diff --git a/rtgui/paramsedited.cc b/rtgui/paramsedited.cc index ce7f3400c..ddd6146a3 100644 --- a/rtgui/paramsedited.cc +++ b/rtgui/paramsedited.cc @@ -336,8 +336,16 @@ void ParamsEdited::set(bool v) lensProf.lfLens = v; perspective.horizontal = v; perspective.vertical = v; - perspective.vBias = v; - perspective.fov = v; + perspective.camera_crop_factor = v; + perspective.camera_focal_length = v; + perspective.camera_shift_horiz = v; + perspective.camera_shift_vert = v; + perspective.projection_pitch = v; + perspective.projection_rotate = v; + perspective.projection_scale = v; + perspective.projection_shift_horiz = v; + perspective.projection_shift_vert = v; + perspective.projection_yaw = v; gradient.enabled = v; gradient.degree = v; gradient.feather = v; @@ -921,8 +929,16 @@ void ParamsEdited::initFrom(const std::vector& 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; - perspective.vBias = perspective.vBias && p.perspective.vBias == other.perspective.vBias; - perspective.fov = perspective.fov && p.perspective.fov == other.perspective.fov; + perspective.camera_crop_factor = perspective.camera_crop_factor && p.perspective.camera_crop_factor == other.perspective.camera_crop_factor; + perspective.camera_focal_length = perspective.camera_focal_length && p.perspective.camera_focal_length == other.perspective.camera_focal_length; + perspective.camera_shift_horiz = perspective.camera_shift_horiz && p.perspective.camera_shift_horiz == other.perspective.camera_shift_horiz; + perspective.camera_shift_vert = perspective.camera_shift_vert && p.perspective.camera_shift_vert == other.perspective.camera_shift_vert; + perspective.projection_pitch = perspective.projection_pitch && p.perspective.projection_pitch == other.perspective.projection_pitch; + perspective.projection_rotate = perspective.projection_rotate && p.perspective.projection_rotate == other.perspective.projection_rotate; + perspective.projection_scale = perspective.projection_scale && p.perspective.projection_scale == other.perspective.projection_scale; + perspective.projection_shift_horiz = perspective.projection_shift_horiz && p.perspective.projection_shift_horiz == other.perspective.projection_shift_horiz; + perspective.projection_shift_vert = perspective.projection_shift_vert && p.perspective.projection_shift_vert == other.perspective.projection_shift_vert; + perspective.projection_yaw = perspective.projection_yaw && p.perspective.projection_yaw == other.perspective.projection_yaw; gradient.enabled = gradient.enabled && p.gradient.enabled == other.gradient.enabled; gradient.degree = gradient.degree && p.gradient.degree == other.gradient.degree; gradient.feather = gradient.feather && p.gradient.feather == other.gradient.feather; @@ -2321,12 +2337,44 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng toEdit.perspective.vertical = dontforceSet && options.baBehav[ADDSET_PERSPECTIVE] ? toEdit.perspective.vertical + mods.perspective.vertical : mods.perspective.vertical; } - if (perspective.vBias) { - toEdit.perspective.vBias = dontforceSet && options.baBehav[ADDSET_PERSPECTIVE] ? toEdit.perspective.vBias + mods.perspective.vBias : mods.perspective.vBias; + if (perspective.camera_crop_factor) { + toEdit.perspective.camera_crop_factor = dontforceSet && options.baBehav[ADDSET_PERSP_CAM_FOCAL_LENGTH] ? toEdit.perspective.camera_crop_factor + mods.perspective.camera_crop_factor : mods.perspective.camera_crop_factor; } - if (perspective.fov) { - toEdit.perspective.fov = dontforceSet && options.baBehav[ADDSET_PERSPECTIVE] ? toEdit.perspective.fov + mods.perspective.fov : mods.perspective.fov; + if (perspective.camera_focal_length) { + toEdit.perspective.camera_focal_length = dontforceSet && options.baBehav[ADDSET_PERSP_CAM_FOCAL_LENGTH] ? toEdit.perspective.camera_focal_length + mods.perspective.camera_focal_length : mods.perspective.camera_focal_length; + } + + if (perspective.camera_shift_horiz) { + toEdit.perspective.camera_shift_horiz = dontforceSet && options.baBehav[ADDSET_PERSP_CAM_SHIFT] ? toEdit.perspective.camera_shift_horiz + mods.perspective.camera_shift_horiz : mods.perspective.camera_shift_horiz; + } + + if (perspective.camera_shift_vert) { + toEdit.perspective.camera_shift_vert = dontforceSet && options.baBehav[ADDSET_PERSP_CAM_SHIFT] ? toEdit.perspective.camera_shift_vert + mods.perspective.camera_shift_vert : mods.perspective.camera_shift_vert; + } + + if (perspective.projection_pitch) { + toEdit.perspective.projection_pitch = dontforceSet && options.baBehav[ADDSET_PERSP_PROJ_ANGLE] ? toEdit.perspective.projection_pitch + mods.perspective.projection_pitch : mods.perspective.projection_pitch; + } + + if (perspective.projection_rotate) { + toEdit.perspective.projection_rotate = dontforceSet && options.baBehav[ADDSET_PERSP_PROJ_ROTATE] ? toEdit.perspective.projection_rotate + mods.perspective.projection_rotate : mods.perspective.projection_rotate; + } + + if (perspective.projection_scale) { + toEdit.perspective.projection_scale = dontforceSet && options.baBehav[ADDSET_PERSP_PROJ_SCALE] ? toEdit.perspective.projection_scale + mods.perspective.projection_scale : mods.perspective.projection_scale; + } + + if (perspective.projection_shift_horiz) { + toEdit.perspective.projection_shift_horiz = dontforceSet && options.baBehav[ADDSET_PERSP_PROJ_SHIFT] ? toEdit.perspective.projection_shift_horiz + mods.perspective.projection_shift_horiz : mods.perspective.projection_shift_horiz; + } + + if (perspective.projection_shift_vert) { + toEdit.perspective.projection_shift_vert = dontforceSet && options.baBehav[ADDSET_PERSP_PROJ_SHIFT] ? toEdit.perspective.projection_shift_vert + mods.perspective.projection_shift_vert : mods.perspective.projection_shift_vert; + } + + if (perspective.projection_yaw) { + toEdit.perspective.projection_yaw = dontforceSet && options.baBehav[ADDSET_PERSP_PROJ_ANGLE] ? toEdit.perspective.projection_yaw + mods.perspective.projection_yaw : mods.perspective.projection_yaw; } if (gradient.enabled) { diff --git a/rtgui/paramsedited.h b/rtgui/paramsedited.h index aa1e10698..6403eba3b 100644 --- a/rtgui/paramsedited.h +++ b/rtgui/paramsedited.h @@ -396,8 +396,16 @@ struct LensProfParamsEdited { struct PerspectiveParamsEdited { bool horizontal; bool vertical; - bool vBias; - bool fov; + bool camera_crop_factor; + bool camera_focal_length; + bool camera_shift_horiz; + bool camera_shift_vert; + bool projection_pitch; + bool projection_rotate; + bool projection_scale; + bool projection_shift_horiz; + bool projection_shift_vert; + bool projection_yaw; }; struct GradientParamsEdited { diff --git a/rtgui/perspective.cc b/rtgui/perspective.cc index 19bef6de6..a7c3900ad 100644 --- a/rtgui/perspective.cc +++ b/rtgui/perspective.cc @@ -32,8 +32,13 @@ PerspCorrection::PerspCorrection () : FoldableToolPanel(this, "perspective", M(" Gtk::Image* ipersHR = Gtk::manage (new RTImage ("perspective-horizontal-right-small.png")); Gtk::Image* ipersVL = Gtk::manage (new RTImage ("perspective-vertical-bottom-small.png")); Gtk::Image* ipersVR = Gtk::manage (new RTImage ("perspective-vertical-top-small.png")); - Gtk::Image* ipersBL = Gtk::manage (new RTImage ("perspective-vertical-bottom-small.png")); - Gtk::Image* ipersBR = Gtk::manage (new RTImage ("perspective-vertical-top-small.png")); + + Gtk::Image* ipers_proj_yaw_left = Gtk::manage (new RTImage ("perspective-horizontal-left-small.png")); + Gtk::Image* ipers_proj_yaw_right = Gtk::manage (new RTImage ("perspective-horizontal-right-small.png")); + Gtk::Image* ipers_proj_pitch_left = Gtk::manage (new RTImage ("perspective-vertical-bottom-small.png")); + Gtk::Image* ipers_proj_pitch_right = Gtk::manage (new RTImage ("perspective-vertical-top-small.png")); + Gtk::Image* ipers_rotate_left = Gtk::manage(new RTImage("rotate-right-small.png")); + Gtk::Image* ipers_rotate_right = Gtk::manage(new RTImage("rotate-left-small.png")); vert = Gtk::manage (new Adjuster (M("TP_PERSPECTIVE_VERTICAL"), -85, 85, 0.1, 0, ipersVL, ipersVR)); vert->setAdjusterListener (this); @@ -41,21 +46,54 @@ PerspCorrection::PerspCorrection () : FoldableToolPanel(this, "perspective", M(" horiz = Gtk::manage (new Adjuster (M("TP_PERSPECTIVE_HORIZONTAL"), -85, 85, 0.1, 0, ipersHL, ipersHR)); horiz->setAdjusterListener (this); - vBias = Gtk::manage (new Adjuster (M("TP_PERSPECTIVE_VERTICAL_BIAS"), -85, 85, 0.1, 0, ipersBL, ipersBR)); - vBias->setAdjusterListener (this); + camera_focal_length = Gtk::manage (new Adjuster (M("TP_PERSPECTIVE_CAMERA_FOCAL_LENGTH"), 0.5, 2000, 0.01, 24)); + camera_focal_length->setAdjusterListener (this); - fov = Gtk::manage (new Adjuster (M("TP_PERSPECTIVE_FOV"), 0.1, 150, 0.1, 65)); - fov->setAdjusterListener (this); + camera_crop_factor = Gtk::manage (new Adjuster (M("TP_PERSPECTIVE_CAMERA_CROP_FACTOR"), 0.1, 30, 0.01, 1)); + camera_crop_factor->setAdjusterListener (this); + + camera_shift_horiz = Gtk::manage (new Adjuster (M("TP_PERSPECTIVE_CAMERA_SHIFT_HORIZONTAL"), -100, 100, 0.01, 0)); + camera_shift_horiz->setAdjusterListener (this); + + camera_shift_vert = Gtk::manage (new Adjuster (M("TP_PERSPECTIVE_CAMERA_SHIFT_VERTICAL"), -100, 100, 0.01, 0)); + camera_shift_vert->setAdjusterListener (this); + + projection_shift_horiz = Gtk::manage (new Adjuster (M("TP_PERSPECTIVE_PROJECTION_SHIFT_HORIZONTAL"), -100, 100, 0.01, 0)); + projection_shift_horiz->setAdjusterListener (this); + + projection_shift_vert = Gtk::manage (new Adjuster (M("TP_PERSPECTIVE_PROJECTION_SHIFT_VERTICAL"), -100, 100, 0.01, 0)); + projection_shift_vert->setAdjusterListener (this); + + projection_rotate = Gtk::manage (new Adjuster (M("TP_PERSPECTIVE_PROJECTION_ROTATE"), -180, 180, 0.01, 0, ipers_rotate_left, ipers_rotate_right)); + projection_rotate->setAdjusterListener (this); + + projection_scale = Gtk::manage (new Adjuster (M("TP_PERSPECTIVE_PROJECTION_SCALE"), 0.5, 2, 0.01, 1)); + projection_scale->setAdjusterListener (this); + + projection_pitch = Gtk::manage (new Adjuster (M("TP_PERSPECTIVE_PROJECTION_PITCH"), -85, 85, 0.1, 0, ipers_proj_pitch_left, ipers_proj_pitch_right)); + projection_pitch->setAdjusterListener (this); + + projection_yaw = Gtk::manage (new Adjuster (M("TP_PERSPECTIVE_PROJECTION_YAW"), -85, 85, 0.1, 0, ipers_proj_yaw_left, ipers_proj_yaw_right)); + projection_yaw->setAdjusterListener (this); pack_start (*vert); pack_start (*horiz); - pack_start (*vBias); - pack_start (*fov); + pack_start (*camera_focal_length); + pack_start (*camera_crop_factor); + pack_start (*camera_shift_horiz); + pack_start (*camera_shift_vert); + pack_start (*projection_shift_horiz); + pack_start (*projection_shift_vert); + pack_start (*projection_rotate); + pack_start (*projection_scale); + pack_start (*projection_yaw); + pack_start (*projection_pitch); horiz->setLogScale(2, 0); vert->setLogScale(2, 0); - vBias->setLogScale(2, 0); - fov->setLogScale(2, 0); + camera_focal_length->setLogScale(4000, 0.5); + camera_crop_factor->setLogScale(300, 0.1); + projection_scale->setLogScale(4, 0.5); show_all(); } @@ -68,14 +106,30 @@ void PerspCorrection::read (const ProcParams* pp, const ParamsEdited* pedited) if (pedited) { horiz->setEditedState (pedited->perspective.horizontal ? Edited : UnEdited); vert->setEditedState (pedited->perspective.vertical ? Edited : UnEdited); - vBias->setEditedState (pedited->perspective.vBias ? Edited : UnEdited); - fov->setEditedState (pedited->perspective.fov ? Edited : UnEdited); + camera_crop_factor->setEditedState (pedited->perspective.camera_crop_factor ? Edited : UnEdited); + camera_focal_length->setEditedState (pedited->perspective.camera_focal_length ? Edited : UnEdited); + camera_shift_horiz->setEditedState (pedited->perspective.camera_shift_horiz ? Edited : UnEdited); + camera_shift_vert->setEditedState (pedited->perspective.camera_shift_vert ? Edited : UnEdited); + projection_pitch->setEditedState (pedited->perspective.projection_pitch ? Edited : UnEdited); + projection_rotate->setEditedState (pedited->perspective.projection_rotate ? Edited : UnEdited); + projection_scale->setEditedState (pedited->perspective.projection_scale ? Edited : UnEdited); + projection_shift_horiz->setEditedState (pedited->perspective.projection_shift_horiz ? Edited : UnEdited); + projection_shift_vert->setEditedState (pedited->perspective.projection_shift_vert ? Edited : UnEdited); + projection_yaw->setEditedState (pedited->perspective.projection_yaw ? Edited : UnEdited); } horiz->setValue (pp->perspective.horizontal); vert->setValue (pp->perspective.vertical); - vBias->setValue (pp->perspective.vBias); - fov->setValue (pp->perspective.fov); + camera_crop_factor->setValue (pp->perspective.camera_crop_factor); + camera_focal_length->setValue (pp->perspective.camera_focal_length); + camera_shift_horiz->setValue (pp->perspective.camera_shift_horiz); + camera_shift_vert->setValue (pp->perspective.camera_shift_vert); + projection_pitch->setValue (pp->perspective.projection_pitch); + projection_rotate->setValue (pp->perspective.projection_rotate); + projection_scale->setValue (pp->perspective.projection_scale); + projection_shift_horiz->setValue (pp->perspective.projection_shift_horiz); + projection_shift_vert->setValue (pp->perspective.projection_shift_vert); + projection_yaw->setValue (pp->perspective.projection_yaw); enableListener (); } @@ -85,14 +139,30 @@ void PerspCorrection::write (ProcParams* pp, ParamsEdited* pedited) pp->perspective.horizontal = horiz->getValue (); pp->perspective.vertical = vert->getValue (); - pp->perspective.vBias = vBias->getValue (); - pp->perspective.fov = fov->getValue (); + pp->perspective.camera_crop_factor= camera_crop_factor->getValue (); + pp->perspective.camera_focal_length = camera_focal_length->getValue (); + pp->perspective.camera_shift_horiz = camera_shift_horiz->getValue (); + pp->perspective.camera_shift_vert = camera_shift_vert->getValue (); + pp->perspective.projection_pitch = projection_pitch->getValue (); + pp->perspective.projection_rotate = projection_rotate->getValue (); + pp->perspective.projection_scale = projection_scale->getValue (); + pp->perspective.projection_shift_horiz = projection_shift_horiz->getValue (); + pp->perspective.projection_shift_vert = projection_shift_vert->getValue (); + pp->perspective.projection_yaw = projection_yaw->getValue (); if (pedited) { pedited->perspective.horizontal = horiz->getEditedState (); pedited->perspective.vertical = vert->getEditedState (); - pedited->perspective.vBias = vBias->getEditedState (); - pedited->perspective.fov = fov->getEditedState (); + pedited->perspective.camera_crop_factor= camera_crop_factor->getEditedState (); + pedited->perspective.camera_focal_length = camera_focal_length->getEditedState (); + pedited->perspective.camera_shift_horiz = camera_shift_horiz->getEditedState(); + pedited->perspective.camera_shift_vert = camera_shift_vert->getEditedState(); + pedited->perspective.projection_pitch = projection_pitch->getEditedState(); + pedited->perspective.projection_rotate = projection_rotate->getEditedState(); + pedited->perspective.projection_scale = projection_scale->getEditedState(); + pedited->perspective.projection_shift_horiz = projection_shift_horiz->getEditedState(); + pedited->perspective.projection_shift_vert = projection_shift_vert->getEditedState(); + pedited->perspective.projection_yaw = projection_yaw->getEditedState(); } } @@ -101,36 +171,109 @@ void PerspCorrection::setDefaults (const ProcParams* defParams, const ParamsEdit horiz->setDefault (defParams->perspective.horizontal); vert->setDefault (defParams->perspective.vertical); - vBias->setDefault (defParams->perspective.vBias); - fov->setDefault (defParams->perspective.fov); + camera_crop_factor->setDefault (defParams->perspective.camera_crop_factor); + camera_focal_length->setDefault (defParams->perspective.camera_focal_length); + camera_shift_horiz->setDefault (defParams->perspective.camera_shift_horiz); + camera_shift_vert->setDefault (defParams->perspective.camera_shift_vert); + projection_pitch->setDefault (defParams->perspective.projection_pitch); + projection_rotate->setDefault (defParams->perspective.projection_rotate); + projection_scale->setDefault (defParams->perspective.projection_scale); + projection_shift_horiz->setDefault (defParams->perspective.projection_shift_horiz); + projection_shift_vert->setDefault (defParams->perspective.projection_shift_vert); + projection_yaw->setDefault (defParams->perspective.projection_yaw); if (pedited) { horiz->setDefaultEditedState (pedited->perspective.horizontal ? Edited : UnEdited); vert->setDefaultEditedState (pedited->perspective.vertical ? Edited : UnEdited); - vBias->setDefaultEditedState (pedited->perspective.vBias ? Edited : UnEdited); - fov->setDefaultEditedState (pedited->perspective.fov ? Edited : UnEdited); + camera_crop_factor->setDefaultEditedState (pedited->perspective.camera_crop_factor ? Edited : UnEdited); + camera_focal_length->setDefaultEditedState (pedited->perspective.camera_focal_length ? Edited : UnEdited); + camera_shift_horiz->setDefaultEditedState (pedited->perspective.camera_shift_horiz ? Edited : UnEdited); + camera_shift_vert->setDefaultEditedState (pedited->perspective.camera_shift_vert ? Edited : UnEdited); + projection_pitch->setDefaultEditedState (pedited->perspective.projection_pitch ? Edited : UnEdited); + projection_rotate->setDefaultEditedState (pedited->perspective.projection_rotate ? Edited : UnEdited); + projection_scale->setDefaultEditedState (pedited->perspective.projection_scale ? Edited : UnEdited); + projection_shift_horiz->setDefaultEditedState (pedited->perspective.projection_shift_horiz ? Edited : UnEdited); + projection_shift_vert->setDefaultEditedState (pedited->perspective.projection_shift_vert ? Edited : UnEdited); + projection_yaw->setDefaultEditedState (pedited->perspective.projection_yaw ? Edited : UnEdited); } else { horiz->setDefaultEditedState (Irrelevant); vert->setDefaultEditedState (Irrelevant); - vBias->setDefaultEditedState (Irrelevant); - fov->setDefaultEditedState (Irrelevant); + camera_crop_factor->setDefaultEditedState (Irrelevant); + camera_focal_length->setDefaultEditedState (Irrelevant); + camera_shift_horiz->setDefaultEditedState (Irrelevant); + camera_shift_vert->setDefaultEditedState (Irrelevant); + projection_pitch->setDefaultEditedState (Irrelevant); + projection_rotate->setDefaultEditedState (Irrelevant); + projection_scale->setDefaultEditedState (Irrelevant); + projection_shift_horiz->setDefaultEditedState (Irrelevant); + projection_shift_vert->setDefaultEditedState (Irrelevant); + projection_yaw->setDefaultEditedState (Irrelevant); } } void PerspCorrection::adjusterChanged(Adjuster* a, double newval) { if (listener) { - listener->panelChanged (EvPerspCorr, Glib::ustring::compose ("%1=%5\n%2=%6\n%3=%7\n%4=%8", M("TP_PERSPECTIVE_HORIZONTAL"), M("TP_PERSPECTIVE_VERTICAL"), M("TP_PERSPECTIVE_VERTICAL_BIAS"), M("TP_PERSPECTIVE_FOV"), horiz->getValue(), vert->getValue(), vBias->getValue(), fov->getValue())); + if (a == horiz || a == vert) { + listener->panelChanged (EvPerspCorr, + Glib::ustring::compose("%1=%2\n%3=%4", + M("TP_PERSPECTIVE_HORIZONTAL"), + horiz->getValue(), + M("TP_PERSPECTIVE_VERTICAL"), + vert->getValue())); + } else if (a == camera_focal_length || a == camera_crop_factor) { + listener->panelChanged (EvPerspCamFocalLength, + Glib::ustring::compose("%1=%2\n%3=%4", + M("TP_PERSPECTIVE_CAMERA_FOCAL_LENGTH"), + camera_focal_length->getValue(), + M("TP_PERSPECTIVE_CAMERA_CROP_FACTOR"), + camera_crop_factor->getValue())); + } else if (a == camera_shift_horiz || a == camera_shift_vert) { + listener->panelChanged (EvPerspCamShift, + Glib::ustring::compose("%1=%2\n%3=%4", + M("TP_PERSPECTIVE_CAMERA_SHIFT_HORIZONTAL"), + camera_shift_horiz->getValue(), + M("TP_PERSPECTIVE_CAMERA_SHIFT_VERTICAL"), + camera_shift_vert->getValue())); + } else if (a == projection_shift_horiz || a == projection_shift_vert) { + listener->panelChanged (EvPerspProjShift, + Glib::ustring::compose("%1=%2\n%3=%4", + M("TP_PERSPECTIVE_PROJECTION_SHIFT_HORIZONTAL"), + projection_shift_horiz->getValue(), + M("TP_PERSPECTIVE_PROJECTION_SHIFT_VERTICAL"), + projection_shift_vert->getValue())); + } else if (a == projection_rotate) { + listener->panelChanged (EvPerspProjRotate, + Glib::ustring::format(projection_rotate->getValue())); + } else if (a == projection_scale) { + listener->panelChanged (EvPerspProjScale, + Glib::ustring::format(projection_scale->getValue())); + } else if (a == projection_pitch || a == projection_yaw) { + listener->panelChanged (EvPerspProjAngle, + Glib::ustring::compose("%1=%2\n%3=%4", + M("TP_PERSPECTIVE_PROJECTION_PITCH"), + projection_pitch->getValue(), + M("TP_PERSPECTIVE_PROJECTION_YAW"), + projection_yaw->getValue())); + } } } -void PerspCorrection::setAdjusterBehavior (bool badd) +void PerspCorrection::setAdjusterBehavior (bool badd, bool camera_focal_length_add, bool camera_shift_add, bool projection_angle_add, bool projection_shift_add, bool projection_rotate_add, bool projection_scale_add) { horiz->setAddMode(badd); vert->setAddMode(badd); - vBias->setAddMode(badd); - fov->setAddMode(badd); + camera_crop_factor->setAddMode(camera_focal_length_add); + camera_focal_length->setAddMode(camera_focal_length_add); + camera_shift_horiz->setAddMode(camera_shift_add); + camera_shift_vert->setAddMode(camera_shift_add); + projection_pitch->setAddMode(projection_angle_add); + projection_rotate->setAddMode(projection_rotate_add); + projection_scale->setAddMode(projection_scale_add); + projection_shift_horiz->setAddMode(projection_shift_add); + projection_shift_vert->setAddMode(projection_shift_add); + projection_yaw->setAddMode(projection_angle_add); } void PerspCorrection::trimValues (rtengine::procparams::ProcParams* pp) @@ -138,8 +281,16 @@ void PerspCorrection::trimValues (rtengine::procparams::ProcParams* pp) horiz->trimValue(pp->perspective.horizontal); vert->trimValue(pp->perspective.vertical); - vBias->trimValue(pp->perspective.vBias); - fov->trimValue(pp->perspective.fov); + camera_crop_factor->trimValue(pp->perspective.camera_crop_factor); + camera_focal_length->trimValue(pp->perspective.camera_focal_length); + camera_shift_horiz->trimValue(pp->perspective.camera_shift_horiz); + camera_shift_vert->trimValue(pp->perspective.camera_shift_vert); + projection_pitch->trimValue(pp->perspective.projection_pitch); + projection_rotate->trimValue(pp->perspective.projection_rotate); + projection_scale->trimValue(pp->perspective.projection_scale); + projection_shift_horiz->trimValue(pp->perspective.projection_shift_horiz); + projection_shift_vert->trimValue(pp->perspective.projection_shift_vert); + projection_yaw->trimValue(pp->perspective.projection_yaw); } void PerspCorrection::setBatchMode (bool batchMode) @@ -148,6 +299,14 @@ void PerspCorrection::setBatchMode (bool batchMode) ToolPanel::setBatchMode (batchMode); horiz->showEditedCB (); vert->showEditedCB (); - vBias->showEditedCB (); - fov->showEditedCB (); + camera_crop_factor->showEditedCB (); + camera_focal_length->showEditedCB (); + camera_shift_horiz->showEditedCB (); + camera_shift_vert->showEditedCB (); + projection_pitch->showEditedCB (); + projection_rotate->showEditedCB (); + projection_scale->showEditedCB (); + projection_shift_horiz->showEditedCB (); + projection_shift_vert->showEditedCB (); + projection_yaw->showEditedCB (); } diff --git a/rtgui/perspective.h b/rtgui/perspective.h index 2b56f2727..bf443f430 100644 --- a/rtgui/perspective.h +++ b/rtgui/perspective.h @@ -32,8 +32,16 @@ class PerspCorrection final : protected: Adjuster* horiz; Adjuster* vert; - Adjuster* vBias; - Adjuster* fov; + Adjuster* camera_crop_factor; + Adjuster* camera_focal_length; + Adjuster* camera_shift_horiz; + Adjuster* camera_shift_vert; + Adjuster* projection_pitch; + Adjuster* projection_rotate; + Adjuster* projection_scale; + Adjuster* projection_shift_horiz; + Adjuster* projection_shift_vert; + Adjuster* projection_yaw; public: @@ -45,6 +53,6 @@ public: void setBatchMode (bool batchMode) override; void adjusterChanged (Adjuster* a, double newval) override; - void setAdjusterBehavior (bool badd); + void setAdjusterBehavior (bool badd, bool camera_focal_length_add, bool camera_shift_add, bool projection_angle_add, bool projection_shift_add, bool projection_rotate_add, bool projection_scale_add); void trimValues (rtengine::procparams::ProcParams* pp) override; }; diff --git a/rtgui/preferences.cc b/rtgui/preferences.cc index 4bbeb345d..a66cfd7d7 100644 --- a/rtgui/preferences.cc +++ b/rtgui/preferences.cc @@ -343,7 +343,13 @@ Gtk::Widget* Preferences::getBatchProcPanel () mi = behModel->append (); mi->set_value (behavColumns.label, M ("TP_PERSPECTIVE_LABEL")); - appendBehavList (mi, M ("TP_PERSPECTIVE_HORIZONTAL") + ", " + M ("TP_PERSPECTIVE_VERTICAL") + ", " + M ("TP_PERSPECTIVE_VERTICAL_BIAS") + ", " + M ("TP_PERSPECTIVE_FOV"), ADDSET_PERSPECTIVE, false); + appendBehavList (mi, M ("TP_PERSPECTIVE_HORIZONTAL") + ", " + M ("TP_PERSPECTIVE_VERTICAL"), ADDSET_PERSPECTIVE, false); + appendBehavList (mi, M ("TP_PERSPECTIVE_CAMERA_FOCAL_LENGTH") + ", " + M ("TP_PERSPECTIVE_CAMERA_CROP_FACTOR"), ADDSET_PERSP_CAM_FOCAL_LENGTH, false); + appendBehavList (mi, M ("TP_PERSPECTIVE_CAMERA_SHIFT_HORIZONTAL") + ", " + M ("TP_PERSPECTIVE_CAMERA_SHIFT_VERTICAL"), ADDSET_PERSP_CAM_SHIFT, false); + appendBehavList (mi, M ("TP_PERSPECTIVE_PROJECTION_SHIFT_HORIZONTAL") + ", " + M ("TP_PERSPECTIVE_PROJECTION_SHIFT_VERTICAL"), ADDSET_PERSP_PROJ_SHIFT, false); + appendBehavList (mi, M ("TP_PERSPECTIVE_PROJECTION_ROTATE"), ADDSET_PERSP_PROJ_ROTATE, false); + appendBehavList (mi, M ("TP_PERSPECTIVE_PROJECTION_SCALE"), ADDSET_PERSP_PROJ_SCALE, false); + appendBehavList (mi, M ("TP_PERSPECTIVE_PROJECTION_YAW") + ", " + M ("TP_PERSPECTIVE_PROJECTION_PITCH"), ADDSET_PERSP_PROJ_ANGLE, false); mi = behModel->append (); mi->set_value (behavColumns.label, M ("TP_GRADIENT_LABEL"));