From 45bde1c9996346d67cee1d37173b1d57fa833dce Mon Sep 17 00:00:00 2001 From: Daniel Gao Date: Mon, 18 Nov 2024 15:24:15 -0500 Subject: [PATCH] Add uniform relative sizing method to framing tool --- rtdata/languages/default | 1 + rtengine/ipresize.cc | 57 +++++++++++++++++++++++++++++++++++++++- rtengine/procparams.cc | 3 +++ rtengine/procparams.h | 5 ++-- rtgui/framing.cc | 48 ++++++++++++++++++++++++++++----- 5 files changed, 104 insertions(+), 10 deletions(-) diff --git a/rtdata/languages/default b/rtdata/languages/default index 6adf5601f..03e08be06 100644 --- a/rtdata/languages/default +++ b/rtdata/languages/default @@ -2744,6 +2744,7 @@ TP_FRAMING_BORDER_SIZE;Size TP_FRAMING_BORDER_SIZE_ABSOLUTE;Absolute TP_FRAMING_BORDER_SIZE_METHOD;Sizing: TP_FRAMING_BORDER_SIZE_RELATIVE;Relative +TP_FRAMING_BORDER_SIZE_UNIFORM_RELATIVE;Uniform Relative TP_FRAMING_FRAMED_HEIGHT;Framed Height TP_FRAMING_FRAMED_WIDTH;Framed Width TP_FRAMING_GREEN;Green diff --git a/rtengine/ipresize.cc b/rtengine/ipresize.cc index 26d906ed7..37fa6f32a 100644 --- a/rtengine/ipresize.cc +++ b/rtengine/ipresize.cc @@ -108,6 +108,8 @@ private: ResizeArgs adjustResize(const ResizeArgs& resize, const Dimensions& newSize) const; Dimensions computeRelativeImageBBoxInFrame(const Dimensions& imgSize, const Dimensions& framedSize) const; + Dimensions computeUniformRelativeImageBBox(const Dimensions& imgSize, + const Dimensions& framedSize) const; ResizeArgs resizeForFixedFrame(const ResizeArgs& resize) const; ResizeArgs resizeForBBox(const ResizeArgs& resize) const; Dimensions computeSizeWithBorders(const Dimensions& imgSize) const; @@ -456,6 +458,37 @@ Dimensions Framing::computeRelativeImageBBoxInFrame(const Dimensions& imgSize, } } +Dimensions Framing::computeUniformRelativeImageBBox(const Dimensions& imgSize, + const Dimensions& framedSize) const +{ + auto length = [](double frame, double border) { + return std::max(0.0, frame - 2.0 * border); + }; + + Side side = pickReferenceSide(framing, imgSize); + double scale = framing.relativeBorderSize; + + double minBorderWidth = 0; + double minBorderHeight = 0; + if (side == Side::WIDTH) { + minBorderWidth = scale * framedSize.width; + if (framing.minSizeEnabled && minBorderWidth < framing.minWidth) { + minBorderWidth = framing.minWidth; + } + } else { + minBorderHeight = scale * framedSize.height; + if (framing.minSizeEnabled && minBorderHeight < framing.minHeight) { + minBorderHeight = framing.minHeight; + } + } + + Dimensions bbox = { + length(framedSize.width, minBorderWidth), + length(framedSize.height, minBorderHeight) + }; + return bbox; +} + ResizeArgs Framing::adjustResizeForFraming(const ResizeArgs& resize) const { if (!framing.enabled) return resize; @@ -488,6 +521,8 @@ ResizeArgs Framing::resizeForFixedFrame(const ResizeArgs& args) const length(framedWidth, framing.absWidth), length(framedHeight, framing.absHeight) }; + } else if (framing.borderSizingMethod == BorderSizing::UNIFORM_PERCENTAGE) { + bbox = computeUniformRelativeImageBBox(args.size, frameSize); } else { bbox = computeRelativeImageBBoxInFrame(args.size, frameSize); } @@ -509,6 +544,8 @@ ResizeArgs Framing::resizeForBBox(const ResizeArgs& args) const length(boundary.width, framing.absWidth), length(boundary.height, framing.absHeight) }; + } else if (framing.borderSizingMethod == BorderSizing::UNIFORM_PERCENTAGE) { + bbox = computeUniformRelativeImageBBox(args.size, boundary); } else { // For the requested aspect ratio, it must fit inside the requested // bounding box @@ -567,9 +604,27 @@ Dimensions Framing::computeSizeWithBorders(const Dimensions& imgSize) const } Side side = pickReferenceSide(framing, imgSize); - double aspectRatio = orientAspectRatio(framing, imgSize); double scale = framing.relativeBorderSize; + if (framing.borderSizingMethod == BorderSizing::UNIFORM_PERCENTAGE) { + double borderSize = 0; + if (side == Side::WIDTH) { + borderSize = scale * imgSize.width; + if (framing.minSizeEnabled && borderSize < framing.minWidth) { + borderSize = framing.minWidth; + } + } else { + borderSize = scale * imgSize.width; + if (framing.minSizeEnabled && borderSize < framing.minHeight) { + borderSize = framing.minHeight; + } + } + + return Dimensions(imgSize.width + 2.0 * borderSize, + imgSize.height + 2.0 * borderSize); + } + + double aspectRatio = orientAspectRatio(framing, imgSize); Dimensions framedSize; if (side == Side::WIDTH) { framedSize.width = (1.0 + 2.0 * scale) * imgSize.width; diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index 88a94a830..677418816 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -467,6 +467,7 @@ namespace Framing DEFINE_KEY(ORIENT_LANDSCAPE, "Landscape"); DEFINE_KEY(ORIENT_PORTRAIT, "Portait"); DEFINE_KEY(BORDER_SIZING_PERCENTAGE, "Percentage"); + DEFINE_KEY(BORDER_SIZING_UNIFORM_PERCENTAGE, "UniformPercentage"); DEFINE_KEY(BORDER_SIZING_FIXED_SIZE, "FixedSize"); DEFINE_KEY(BASIS_AUTO, "Auto"); DEFINE_KEY(BASIS_WIDTH, "Width"); @@ -514,6 +515,7 @@ void loadFramingParams( using BorderSizing = FramingParams::BorderSizing; const std::map borderSizingMapping = { {BORDER_SIZING_PERCENTAGE, BorderSizing::PERCENTAGE}, + {BORDER_SIZING_UNIFORM_PERCENTAGE, BorderSizing::UNIFORM_PERCENTAGE}, {BORDER_SIZING_FIXED_SIZE, BorderSizing::FIXED_SIZE} }; assignFromKeyfile(keyFile, group, BORDER_SIZING_METHOD, borderSizingMapping, params.borderSizingMethod, edited.borderSizingMethod); @@ -576,6 +578,7 @@ void saveFramingParams( using BorderSizing = FramingParams::BorderSizing; const std::map borderSizingMapping = { {BorderSizing::PERCENTAGE, BORDER_SIZING_PERCENTAGE}, + {BorderSizing::UNIFORM_PERCENTAGE, BORDER_SIZING_UNIFORM_PERCENTAGE}, {BorderSizing::FIXED_SIZE, BORDER_SIZING_FIXED_SIZE} }; saveToKeyfile(!pedited || edited.borderSizingMethod, group, BORDER_SIZING_METHOD, borderSizingMapping, params.borderSizingMethod, keyFile); diff --git a/rtengine/procparams.h b/rtengine/procparams.h index f61ca6505..94108e5fd 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -2001,8 +2001,9 @@ struct FramingParams { // How to size border? enum class BorderSizing { - PERCENTAGE, // Percentage of image size - FIXED_SIZE // Fixed pixel dimensions + PERCENTAGE, // Percentage of image size + UNIFORM_PERCENTAGE, // Percentage of image size (ignore aspect ratio) + FIXED_SIZE // Fixed pixel dimensions }; // Which dimension to use for percentage based border sizing? diff --git a/rtgui/framing.cc b/rtgui/framing.cc index 62587a518..3d04b265e 100644 --- a/rtgui/framing.cc +++ b/rtgui/framing.cc @@ -125,10 +125,12 @@ FramingParams::Orientation mapOrientation(int comboIndex) // Border sizing method combo box data constexpr int INDEX_SIZE_RELATIVE = 0; -constexpr int INDEX_SIZE_ABSOLUTE = 1; -constexpr int INDEX_SIZE_UNCHANGED = 2; -constexpr std::array BORDER_SIZE_METHODS = { +constexpr int INDEX_SIZE_UNIFORM_RELATIVE = 1; +constexpr int INDEX_SIZE_ABSOLUTE = 2; +constexpr int INDEX_SIZE_UNCHANGED = 3; +constexpr std::array BORDER_SIZE_METHODS = { "TP_FRAMING_BORDER_SIZE_RELATIVE", + "TP_FRAMING_BORDER_SIZE_UNIFORM_RELATIVE", "TP_FRAMING_BORDER_SIZE_ABSOLUTE" }; @@ -138,6 +140,8 @@ int mapBorderSizeMethod(FramingParams::BorderSizing sizing) switch (sizing) { case BorderSizing::PERCENTAGE: return INDEX_SIZE_RELATIVE; + case BorderSizing::UNIFORM_PERCENTAGE: + return INDEX_SIZE_UNIFORM_RELATIVE; case BorderSizing::FIXED_SIZE: return INDEX_SIZE_ABSOLUTE; default: @@ -151,6 +155,8 @@ FramingParams::BorderSizing mapBorderSizeMethod(int comboIndex) switch (comboIndex) { case INDEX_SIZE_RELATIVE: return BorderSizing::PERCENTAGE; + case INDEX_SIZE_UNIFORM_RELATIVE: + return BorderSizing::UNIFORM_PERCENTAGE; case INDEX_SIZE_ABSOLUTE: return BorderSizing::FIXED_SIZE; default: @@ -823,6 +829,16 @@ void Framing::updateBorderSizeGui() aspectRatio->set_sensitive(true); orientation->set_sensitive(true); + } else if (activeRow == INDEX_SIZE_UNIFORM_RELATIVE) { + basisLabel->show(); + basis->show(); + relativeBorderSize->show(); + minSizeFrame->show(); + absWidth.hide(); + absHeight.hide(); + + aspectRatio->set_sensitive(false); + orientation->set_sensitive(false); } else if (activeRow == INDEX_SIZE_ABSOLUTE) { basisLabel->hide(); basis->hide(); @@ -949,6 +965,12 @@ void Framing::onAllowUpscalingToggled() void Framing::onBorderSizeMethodChanged() { + if (borderSizeMethod->get_active_row_number() == INDEX_SIZE_UNIFORM_RELATIVE) { + ConnectionBlocker block(minHeight.connection); + minHeight.isDirty = true; + minHeight.value->set_value(minWidth.value->get_value_as_int()); + } + updateBorderSizeGui(); if (listener && (getEnabled() || batchMode)) { @@ -993,20 +1015,32 @@ void Framing::onMinSizeToggled() void Framing::onMinWidthChanged() { minWidth.isDirty = true; + int value = minWidth.value->get_value_as_int(); + + if (borderSizeMethod->get_active_row_number() == INDEX_SIZE_UNIFORM_RELATIVE) { + ConnectionBlocker block(minHeight.connection); + minHeight.isDirty = true; + minHeight.value->set_value(value); + } if (listener && (getEnabled() || batchMode)) { - listener->panelChanged(EvFramingMinWidth, - Glib::ustring::format(minWidth.value->get_value_as_int())); + listener->panelChanged(EvFramingMinWidth, Glib::ustring::format(value)); } } void Framing::onMinHeightChanged() { minHeight.isDirty = true; + int value = minHeight.value->get_value_as_int(); + + if (borderSizeMethod->get_active_row_number() == INDEX_SIZE_UNIFORM_RELATIVE) { + ConnectionBlocker block(minWidth.connection); + minWidth.isDirty = true; + minWidth.value->set_value(value); + } if (listener && (getEnabled() || batchMode)) { - listener->panelChanged(EvFramingMinHeight, - Glib::ustring::format(minHeight.value->get_value_as_int())); + listener->panelChanged(EvFramingMinHeight, Glib::ustring::format(value)); } }