commit
3c21dca522
@ -1433,6 +1433,24 @@ HISTORY_MSG_FILMNEGATIVE_COLORSPACE;Film negative color space
|
||||
HISTORY_MSG_FILMNEGATIVE_ENABLED;Film Negative
|
||||
HISTORY_MSG_FILMNEGATIVE_REF_SPOT;FN - Reference input
|
||||
HISTORY_MSG_FILMNEGATIVE_VALUES;Film negative values
|
||||
HISTORY_MSG_FRAMING_ABSOLUTE_HEIGHT;Framing - Border Height
|
||||
HISTORY_MSG_FRAMING_ABSOLUTE_WIDTH;Framing - Border Width
|
||||
HISTORY_MSG_FRAMING_ALLOW_UPSCALING;Framing - Upscaling
|
||||
HISTORY_MSG_FRAMING_ASPECT_RATIO;Framing - Aspect Ratio
|
||||
HISTORY_MSG_FRAMING_BASIS;Framing - Basis
|
||||
HISTORY_MSG_FRAMING_BORDER_BLUE;Framing - Border (B)
|
||||
HISTORY_MSG_FRAMING_BORDER_GREEN;Framing - Border (G)
|
||||
HISTORY_MSG_FRAMING_BORDER_RED;Framing - Border (R)
|
||||
HISTORY_MSG_FRAMING_BORDER_SIZE;Framing - Relative Size
|
||||
HISTORY_MSG_FRAMING_BORDER_SIZE_METHOD;Framing - Border Sizing Method
|
||||
HISTORY_MSG_FRAMING_ENABLED;Framing
|
||||
HISTORY_MSG_FRAMING_FRAMED_HEIGHT;Framing - Framed Height
|
||||
HISTORY_MSG_FRAMING_FRAMED_WIDTH;Framing - Framed Width
|
||||
HISTORY_MSG_FRAMING_METHOD;Framing - Method
|
||||
HISTORY_MSG_FRAMING_MIN_HEIGHT;Framing - Min Height
|
||||
HISTORY_MSG_FRAMING_MIN_SIZE_ENABLED;Framing - Min Size
|
||||
HISTORY_MSG_FRAMING_MIN_WIDTH;Framing - Min Width
|
||||
HISTORY_MSG_FRAMING_ORIENTATION;Framing - Orientation
|
||||
HISTORY_MSG_GAMUTMUNSEL;Gamut-Munsell
|
||||
HISTORY_MSG_HISTMATCHING;Auto-matched tone curve
|
||||
HISTORY_MSG_HLBL;Color propagation - blur
|
||||
@ -1587,8 +1605,8 @@ HISTORY_MSG_TONE_EQUALIZER_ENABLED;Tone equalizer
|
||||
HISTORY_MSG_TONE_EQUALIZER_PIVOT;Tone equalizer - Pivot
|
||||
HISTORY_MSG_TONE_EQUALIZER_REGULARIZATION;Tone equalizer - Regularization
|
||||
HISTORY_MSG_TONE_EQUALIZER_SHOW_COLOR_MAP;Tone equalizer - Tonal map
|
||||
HISTORY_MSG_TRANS_SCALE;Geometry - Scale
|
||||
HISTORY_MSG_TRANS_METHOD;Geometry - Method
|
||||
HISTORY_MSG_TRANS_SCALE;Geometry - Scale
|
||||
HISTORY_MSG_WAVBALCHROM;Equalizer chrominance
|
||||
HISTORY_MSG_WAVBALLUM;Equalizer luminance
|
||||
HISTORY_MSG_WAVBL;Blur levels
|
||||
@ -1864,6 +1882,7 @@ PARTIALPASTE_FLATFIELDBLURTYPE;Flat-field blur type
|
||||
PARTIALPASTE_FLATFIELDCLIPCONTROL;Flat-field clip control
|
||||
PARTIALPASTE_FLATFIELDFILE;Flat-field file
|
||||
PARTIALPASTE_FLATFIELDFROMMETADATA;Flat-field from Metadata
|
||||
PARTIALPASTE_FRAMING;Framing
|
||||
PARTIALPASTE_GRADIENT;Graduated filter
|
||||
PARTIALPASTE_HSVEQUALIZER;HSV equalizer
|
||||
PARTIALPASTE_ICMSETTINGS;Color management settings
|
||||
@ -2709,6 +2728,36 @@ TP_FLATFIELD_CLIPCONTROL;Clip control
|
||||
TP_FLATFIELD_CLIPCONTROL_TOOLTIP;Clip control avoids clipped highlights caused by applying the flat field. If there are already clipped highlights before applying the flat field, value 0 is used.
|
||||
TP_FLATFIELD_FROMMETADATA;From Metadata
|
||||
TP_FLATFIELD_LABEL;Flat-Field
|
||||
TP_FRAMING_ABSOLUTE_HEIGHT;Border Height
|
||||
TP_FRAMING_ABSOLUTE_WIDTH;Border Width
|
||||
TP_FRAMING_ALLOW_UPSCALING;Allow upscaling to frame
|
||||
TP_FRAMING_ASPECT_RATIO;Aspect Ratio:
|
||||
TP_FRAMING_BASIS;Basis
|
||||
TP_FRAMING_BASIS_AUTO;Auto
|
||||
TP_FRAMING_BASIS_HEIGHT;Height
|
||||
TP_FRAMING_BASIS_LONG_SIDE;Long Edge
|
||||
TP_FRAMING_BASIS_SHORT_SIDE;Short Edge
|
||||
TP_FRAMING_BASIS_WIDTH;Width
|
||||
TP_FRAMING_BLUE;Blue
|
||||
TP_FRAMING_BORDER_COLOR;Border Color
|
||||
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
|
||||
TP_FRAMING_LABEL;Framing
|
||||
TP_FRAMING_LIMIT_MINIMUM;Limit minimum size
|
||||
TP_FRAMING_METHOD;Method:
|
||||
TP_FRAMING_METHOD_BBOX;Bounding Box
|
||||
TP_FRAMING_METHOD_FIXED;Fixed Frame
|
||||
TP_FRAMING_METHOD_STANDARD;Standard
|
||||
TP_FRAMING_MIN_HEIGHT;Minimum Height
|
||||
TP_FRAMING_MIN_WIDTH;Minimum Width
|
||||
TP_FRAMING_ORIENTATION;Orientation:
|
||||
TP_FRAMING_RED;Red
|
||||
TP_GENERAL_11SCALE_TOOLTIP;The effects of this tool are only visible or only accurate at a preview scale of 1:1.
|
||||
TP_GRADIENT_CENTER;Center
|
||||
TP_GRADIENT_CENTER_X;Center X
|
||||
@ -2876,11 +2925,11 @@ TP_LABCURVE_LCREDSK_TOOLTIP;If enabled, the LC Curve affects only red and skin-t
|
||||
TP_LABCURVE_RSTPROTECTION;Red and skin-tones protection
|
||||
TP_LABCURVE_RSTPRO_TOOLTIP;Works on the Chromaticity slider and the CC curve.
|
||||
TP_LENSGEOM_AUTOCROP;Auto-Crop
|
||||
TP_LENSGEOM_SCALE;Scale
|
||||
TP_LENSGEOM_FILL;Auto-fill
|
||||
TP_LENSGEOM_LABEL;Lens / Geometry
|
||||
TP_LENSGEOM_LIN;Linear
|
||||
TP_LENSGEOM_LOG;Logarithmic
|
||||
TP_LENSGEOM_SCALE;Scale
|
||||
TP_LENSPROFILE_CORRECTION_AUTOMATCH;Automatically selected
|
||||
TP_LENSPROFILE_CORRECTION_LCPFILE;LCP file
|
||||
TP_LENSPROFILE_CORRECTION_MANUAL;Manually selected
|
||||
@ -3908,7 +3957,7 @@ TP_RESIZE_FITBOX;Bounding Box
|
||||
TP_RESIZE_FULLIMAGE;Full Image
|
||||
TP_RESIZE_H;Height:
|
||||
TP_RESIZE_HEIGHT;Height
|
||||
TP_RESIZE_LABEL;Resize
|
||||
TP_RESIZE_LABEL;Resize & Framing
|
||||
TP_RESIZE_LANCZOS;Lanczos
|
||||
TP_RESIZE_LE;Long Edge:
|
||||
TP_RESIZE_LONG;Long Edge
|
||||
|
@ -213,12 +213,33 @@ enum class BlurType {
|
||||
void sharpening(LabImage* lab, const procparams::SharpeningParams &sharpenParam, bool showMask = false);
|
||||
void sharpeningcam(CieImage* ncie, float** buffer, bool showMask = false);
|
||||
void transform(Imagefloat* original, Imagefloat* transformed, int cx, int cy, int sx, int sy, int oW, int oH, int fW, int fH, const FramesMetaData *metadata, int rawRotationDeg, bool fullImage, bool useOriginalBuffer = false);
|
||||
float resizeScale(const procparams::ProcParams* params, int fw, int fh, int &imw, int &imh);
|
||||
void lab2monitorRgb(LabImage* lab, Image8* image);
|
||||
|
||||
double resizeScale(const procparams::ProcParams* params, int fw, int fh, int &imw, int &imh);
|
||||
void resize(Imagefloat* src, Imagefloat* dst, float dScale);
|
||||
void Lanczos(const LabImage* src, LabImage* dst, float scale);
|
||||
void Lanczos(const Imagefloat* src, Imagefloat* dst, float scale);
|
||||
|
||||
struct FramingArgs {
|
||||
const procparams::ProcParams* params = nullptr;
|
||||
int cropWidth = 0;
|
||||
int cropHeight = 0;
|
||||
int resizeWidth = 0;
|
||||
int resizeHeight = 0;
|
||||
double resizeScale = 1.0f;
|
||||
};
|
||||
struct FramingData {
|
||||
bool enabled = false;
|
||||
int imgWidth = 0;
|
||||
int imgHeight = 0;
|
||||
double scale = 1.0;
|
||||
int framedWidth = 0;
|
||||
int framedHeight = 0;
|
||||
};
|
||||
FramingData framing(const FramingArgs& args) const;
|
||||
Imagefloat* drawFrame(Imagefloat* rgb, const procparams::FramingParams& params,
|
||||
const FramingData& dims) const;
|
||||
|
||||
void deconvsharpening(float** luminance, float** buffer, const float* const * blend, int W, int H, const procparams::SharpeningParams &sharpenParam, double Scale);
|
||||
void deconvsharpeningloc(float** luminance, float** buffer, int W, int H, float** loctemp, int damp, double radi, int ite, int amo, int contrast, double blurrad, int sk);
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "improcfun.h"
|
||||
|
||||
#include "alignedbuffer.h"
|
||||
#include "color.h"
|
||||
#include "imagefloat.h"
|
||||
#include "labimage.h"
|
||||
#include "opthelper.h"
|
||||
@ -33,6 +34,678 @@
|
||||
# include <iostream>
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
using ProcParams = rtengine::procparams::ProcParams;
|
||||
using FramingParams = rtengine::procparams::FramingParams;
|
||||
|
||||
using Basis = FramingParams::Basis;
|
||||
using BorderSizing = FramingParams::BorderSizing;
|
||||
using FramingMethod = FramingParams::FramingMethod;
|
||||
|
||||
enum class Orientation { LANDSCAPE, PORTRAIT };
|
||||
enum class Side { WIDTH, HEIGHT };
|
||||
|
||||
struct Dimensions
|
||||
{
|
||||
double width;
|
||||
double height;
|
||||
|
||||
Dimensions() : width(0), height(0) {}
|
||||
Dimensions(double w, double h) : width(w), height(h) {}
|
||||
|
||||
bool isDegenerate() const { return width <= 0.0 || height <= 0.0; }
|
||||
|
||||
double aspectRatio() const {
|
||||
if (isDegenerate()) return 1.0;
|
||||
else return static_cast<double>(width) / static_cast<double>(height);
|
||||
}
|
||||
|
||||
Orientation orient() const {
|
||||
return width >= height ? Orientation::LANDSCAPE : Orientation::PORTRAIT;
|
||||
}
|
||||
|
||||
bool inside(const Dimensions& other) const {
|
||||
return width <= other.width && height <= other.height;
|
||||
}
|
||||
|
||||
void rotate(Orientation newOrient) {
|
||||
if (newOrient != orient()) {
|
||||
std::swap(width, height);
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(const Dimensions& other) const {
|
||||
return width == other.width && height == other.height;
|
||||
}
|
||||
bool operator!=(const Dimensions& other) const { return !(*this == other); }
|
||||
|
||||
Dimensions intersect(const Dimensions& other) const {
|
||||
return Dimensions(std::min(width, other.width), std::min(height, other.height));
|
||||
}
|
||||
|
||||
void debug(const char* prefix) const {
|
||||
printf("%s w=%f h=%f ar=%f\n", prefix, width, height, aspectRatio());
|
||||
}
|
||||
};
|
||||
|
||||
struct ResizeArgs
|
||||
{
|
||||
Dimensions size;
|
||||
double scale = 1.0;
|
||||
|
||||
ResizeArgs(const Dimensions& aSize, double aScale) : size(aSize), scale(aScale) {}
|
||||
};
|
||||
|
||||
class Framing
|
||||
{
|
||||
public:
|
||||
Framing(const ProcParams& params, int fullWidth, int fullHeight);
|
||||
|
||||
ResizeArgs adjustResizeForFraming(const ResizeArgs& resize) const;
|
||||
Dimensions computeFramedSize(const Dimensions& imgSize) const;
|
||||
|
||||
private:
|
||||
Dimensions clampResize(const Dimensions& imgSize, const Dimensions& bounds) const;
|
||||
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;
|
||||
|
||||
const ProcParams& allParams;
|
||||
const FramingParams framing; // Make a copy to sanitize inputs
|
||||
const Dimensions postCropImageSize;
|
||||
const Dimensions maxUpscalingBBox;
|
||||
};
|
||||
|
||||
// Downscaling limit is 32x32px
|
||||
constexpr double MIN_DOWNSCALE_PX = 32.0;
|
||||
// Upscaling limit is 16x image size
|
||||
constexpr double MAX_UPSCALE_FACTOR = 16.0;
|
||||
|
||||
int computeSize(int dim, double scale)
|
||||
{
|
||||
return static_cast<int>(static_cast<double>(dim) * scale + 0.5);
|
||||
}
|
||||
|
||||
std::pair<double, double> computeImgAndBorderSize(double frameSize, double scale)
|
||||
{
|
||||
// frame_len = img_len + 2 * scale * img_len = (1 + 2 * scale) * img_len
|
||||
double imgFrameScale = (1.0 + 2.0 * scale);
|
||||
double imgSize = frameSize / imgFrameScale;
|
||||
double borderSize = scale * imgSize;
|
||||
|
||||
return {imgSize, borderSize};
|
||||
}
|
||||
|
||||
Orientation orient(const FramingParams& params, const Dimensions& imgSize)
|
||||
{
|
||||
switch (params.orientation) {
|
||||
case FramingParams::Orientation::LANDSCAPE:
|
||||
return Orientation::LANDSCAPE;
|
||||
case FramingParams::Orientation::PORTRAIT:
|
||||
return Orientation::PORTRAIT;
|
||||
case FramingParams::Orientation::AS_IMAGE:
|
||||
default:
|
||||
return imgSize.orient();
|
||||
}
|
||||
}
|
||||
|
||||
double flipAspectRatioByOrientation(double aspectRatio, Orientation orient)
|
||||
{
|
||||
switch (orient) {
|
||||
case Orientation::LANDSCAPE:
|
||||
return aspectRatio >= 1.0 ? aspectRatio : 1.0 / aspectRatio;
|
||||
case Orientation::PORTRAIT:
|
||||
return aspectRatio <= 1.0 ? aspectRatio : 1.0 / aspectRatio;
|
||||
default:
|
||||
return aspectRatio;
|
||||
}
|
||||
}
|
||||
|
||||
Side autoPickBasis(const FramingParams& params, const Dimensions& imgSize)
|
||||
{
|
||||
if (imgSize.isDegenerate()) {
|
||||
if (imgSize.width <= 0) return Side::HEIGHT;
|
||||
else return Side::WIDTH;
|
||||
}
|
||||
|
||||
Orientation imgOrient = imgSize.orient();
|
||||
double imgAspectRatio = imgSize.aspectRatio();
|
||||
Orientation frameOrient = orient(params, imgSize);
|
||||
double frameAspectRatio = flipAspectRatioByOrientation(params.aspectRatio, frameOrient);
|
||||
|
||||
if (frameOrient == imgOrient) {
|
||||
// Pick the more constrained side (i.e. hits 0 border width first)
|
||||
return imgAspectRatio >= frameAspectRatio ? Side::WIDTH : Side::HEIGHT;
|
||||
} else if (imgOrient == Orientation::LANDSCAPE) {
|
||||
// Image in landscape, frame in portrait
|
||||
return Side::WIDTH;
|
||||
} else {
|
||||
// Image in portrait, frame in landscape
|
||||
return Side::HEIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
Side pickReferenceSide(const FramingParams& params, const Dimensions& imgSize)
|
||||
{
|
||||
switch (params.basis) {
|
||||
case Basis::WIDTH:
|
||||
return Side::WIDTH;
|
||||
case Basis::HEIGHT:
|
||||
return Side::HEIGHT;
|
||||
case Basis::LONG:
|
||||
return imgSize.width >= imgSize.height ? Side::WIDTH : Side::HEIGHT;
|
||||
case Basis::SHORT:
|
||||
return imgSize.width <= imgSize.height ? Side::WIDTH : Side::HEIGHT;
|
||||
case Basis::AUTO:
|
||||
default:
|
||||
return autoPickBasis(params, imgSize);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr bool INSIDE_BBOX = true;
|
||||
constexpr bool OUTSIDE_BBOX = false;
|
||||
|
||||
Dimensions clampToBBox(const Dimensions& img, const Dimensions& bbox, bool clampInside)
|
||||
{
|
||||
double widthScale = 1.0;
|
||||
double heightScale = 1.0;
|
||||
if (bbox.width > 0) {
|
||||
widthScale = img.width / bbox.width;
|
||||
}
|
||||
if (bbox.height > 0) {
|
||||
heightScale = img.height / bbox.height;
|
||||
}
|
||||
|
||||
Dimensions newSize = img;
|
||||
|
||||
if (clampInside) {
|
||||
// If a side exceeds the bbox, scale down to bbox
|
||||
double scale = std::max(widthScale, heightScale);
|
||||
if (scale > 1.0) {
|
||||
if (widthScale >= heightScale) {
|
||||
newSize.width = bbox.width;
|
||||
newSize.height = img.height / widthScale;
|
||||
} else {
|
||||
newSize.width = img.width / heightScale;
|
||||
newSize.height = bbox.height;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If a side is within the bbox, scale up to bbox
|
||||
double scale = std::min(widthScale, heightScale);
|
||||
if (scale < 1.0) {
|
||||
if (widthScale <= heightScale) {
|
||||
newSize.width = bbox.width;
|
||||
newSize.height = img.height / widthScale;
|
||||
} else {
|
||||
newSize.width = img.width / heightScale;
|
||||
newSize.height = bbox.height;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return newSize;
|
||||
}
|
||||
|
||||
Dimensions downscaleToTouchBBox(const Dimensions& img, const Dimensions& bbox)
|
||||
{
|
||||
if (bbox.isDegenerate()) return Dimensions(0, 0);
|
||||
if (!bbox.inside(img)) return img;
|
||||
|
||||
double widthScale = img.width / bbox.width;
|
||||
double heightScale = img.height / bbox.height;
|
||||
|
||||
Dimensions downscaled;
|
||||
if (widthScale <= heightScale) {
|
||||
downscaled.width = bbox.width;
|
||||
downscaled.height = img.height / widthScale;
|
||||
} else {
|
||||
downscaled.height = bbox.height;
|
||||
downscaled.width = img.width / heightScale;
|
||||
}
|
||||
return downscaled;
|
||||
}
|
||||
|
||||
Dimensions upscaleToBBox(const Dimensions& img, const Dimensions& bbox)
|
||||
{
|
||||
if (bbox.isDegenerate()) return Dimensions(0, 0);
|
||||
if (!img.inside(bbox)) return img;
|
||||
|
||||
double widthScale = img.width / bbox.width;
|
||||
double heightScale = img.height / bbox.height;
|
||||
|
||||
Dimensions upscaled;
|
||||
if (widthScale >= heightScale) {
|
||||
upscaled.width = bbox.width;
|
||||
upscaled.height = img.height / widthScale;
|
||||
} else {
|
||||
upscaled.height = bbox.height;
|
||||
upscaled.width = img.width / heightScale;
|
||||
}
|
||||
|
||||
return upscaled;
|
||||
}
|
||||
|
||||
double orientAspectRatio(const FramingParams& framing, const Dimensions& imgSize)
|
||||
{
|
||||
double aspectRatio = framing.aspectRatio;
|
||||
if (aspectRatio == FramingParams::AS_IMAGE_ASPECT_RATIO) {
|
||||
aspectRatio = imgSize.aspectRatio();
|
||||
}
|
||||
|
||||
Orientation borderOrient = orient(framing, imgSize);
|
||||
if ((borderOrient == Orientation::PORTRAIT && aspectRatio > 1.0) ||
|
||||
(borderOrient == Orientation::LANDSCAPE && aspectRatio < 1.0)) {
|
||||
aspectRatio = 1.0 / aspectRatio;
|
||||
}
|
||||
return aspectRatio;
|
||||
}
|
||||
|
||||
Dimensions fromAspectRatio(const Dimensions& size, double aspectRatio)
|
||||
{
|
||||
Dimensions result;
|
||||
if (aspectRatio >= 1.0) {
|
||||
result.height = size.height;
|
||||
result.width = result.height * aspectRatio;
|
||||
} else {
|
||||
result.width = size.width;
|
||||
result.height = result.width / aspectRatio;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
FramingParams sanitize(const FramingParams& dirty)
|
||||
{
|
||||
FramingParams framing = dirty;
|
||||
framing.framedWidth = std::max(static_cast<int>(MIN_DOWNSCALE_PX), framing.framedWidth);
|
||||
framing.framedHeight = std::max(static_cast<int>(MIN_DOWNSCALE_PX), framing.framedHeight);
|
||||
framing.relativeBorderSize = std::max(0.0, std::min(1.0, framing.relativeBorderSize));
|
||||
framing.minWidth = std::max(0, framing.minWidth);
|
||||
framing.minHeight = std::max(0, framing.minHeight);
|
||||
framing.absWidth = std::max(0, framing.absWidth);
|
||||
framing.absHeight = std::max(0, framing.absHeight);
|
||||
return framing;
|
||||
}
|
||||
|
||||
Framing::Framing(const ProcParams& params, int fullWidth, int fullHeight) :
|
||||
allParams(params),
|
||||
framing(sanitize(params.framing)),
|
||||
postCropImageSize(params.crop.enabled ?
|
||||
Dimensions(params.crop.w, params.crop.h) :
|
||||
Dimensions(fullWidth, fullHeight)),
|
||||
maxUpscalingBBox(Dimensions(
|
||||
computeSize(postCropImageSize.width, MAX_UPSCALE_FACTOR),
|
||||
computeSize(postCropImageSize.height, MAX_UPSCALE_FACTOR)))
|
||||
{
|
||||
}
|
||||
|
||||
Dimensions Framing::clampResize(const Dimensions& imgSize, const Dimensions& bounds) const
|
||||
{
|
||||
// Don't adjust above upscaling limit.
|
||||
//
|
||||
// If the upscaling limit is contained inside the target bounds, scale
|
||||
// down the bounds to outside the upscaling limit. This is needed since
|
||||
// scaling the bounds to fit inside the upscaling bbox may artificially
|
||||
// reduce the upscaling limit due to aspect ratio differences.
|
||||
Dimensions clampedBounds = maxUpscalingBBox.inside(bounds) ?
|
||||
downscaleToTouchBBox(bounds, maxUpscalingBBox) :
|
||||
clampToBBox(bounds, maxUpscalingBBox, INSIDE_BBOX);
|
||||
|
||||
if (!imgSize.inside(clampedBounds)) {
|
||||
// Downscale large images to fit inside bounds (only if above limit)
|
||||
|
||||
Dimensions minSize(MIN_DOWNSCALE_PX, MIN_DOWNSCALE_PX);
|
||||
if (!minSize.inside(imgSize)) {
|
||||
// Skip images below downscaling limit
|
||||
return imgSize;
|
||||
} else if (!minSize.inside(clampedBounds)) {
|
||||
// Go as small as possible without exceeding downscaling limit
|
||||
return downscaleToTouchBBox(imgSize, minSize);
|
||||
} else {
|
||||
// Downscale large images to fit inside bounds
|
||||
return clampToBBox(imgSize, clampedBounds, INSIDE_BBOX);
|
||||
}
|
||||
} else {
|
||||
// Consider upscaling...
|
||||
if (!framing.allowUpscaling ||
|
||||
imgSize.width == clampedBounds.width ||
|
||||
imgSize.height == clampedBounds.height) {
|
||||
return imgSize;
|
||||
} else {
|
||||
return upscaleToBBox(imgSize, clampedBounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ResizeArgs Framing::adjustResize(const ResizeArgs& resize, const Dimensions& bbox) const
|
||||
{
|
||||
Dimensions newSize = clampResize(resize.size, bbox);
|
||||
double newScale = newSize.width / postCropImageSize.width;
|
||||
return ResizeArgs(newSize, newScale);
|
||||
}
|
||||
|
||||
Dimensions Framing::computeRelativeImageBBoxInFrame(const Dimensions& imgSize,
|
||||
const Dimensions& framedSize) const
|
||||
{
|
||||
if (imgSize.isDegenerate() || framedSize.isDegenerate()) {
|
||||
return Dimensions(0, 0);
|
||||
}
|
||||
|
||||
double imgAspectRatio = imgSize.aspectRatio();
|
||||
// Compute the width:height ratio of the border size for the requested
|
||||
// image size and framed size.
|
||||
//
|
||||
// We do this by creating a dummy image. Then, scale the framed size to be
|
||||
// larger than the dummy image such that there is a non-zero difference for
|
||||
// widths and heights.
|
||||
double borderAspectRatio = [&]()
|
||||
{
|
||||
Dimensions fakeImage = fromAspectRatio(framedSize, imgAspectRatio);
|
||||
Dimensions bigFrame = clampToBBox(framedSize, fakeImage, OUTSIDE_BBOX);
|
||||
bigFrame.width *= 2.0;
|
||||
bigFrame.height *= 2.0;
|
||||
|
||||
Dimensions diff(bigFrame.width - fakeImage.width, bigFrame.height - fakeImage.height);
|
||||
return diff.aspectRatio();
|
||||
}();
|
||||
|
||||
Side side = pickReferenceSide(framing, imgSize);
|
||||
double scale = framing.relativeBorderSize;
|
||||
|
||||
// Compute image and border lengths on basis side
|
||||
double frameBasis = side == Side::WIDTH ? framedSize.width : framedSize.height;
|
||||
double frameOther = side == Side::WIDTH ? framedSize.height : framedSize.width;
|
||||
|
||||
auto computedSizes = computeImgAndBorderSize(frameBasis, scale);
|
||||
double imgBasis = computedSizes.first;
|
||||
double borderBasis = computedSizes.second;
|
||||
|
||||
// Compute image and border lengths for the non-basis side
|
||||
double imgBasisToOther = side == Side::WIDTH ? 1.0 / imgAspectRatio : imgAspectRatio;
|
||||
double borderBasisToOther = side == Side::WIDTH ? 1.0 / borderAspectRatio : borderAspectRatio;
|
||||
double imgOther = imgBasis * imgBasisToOther;
|
||||
double borderOther = borderBasis * borderBasisToOther;
|
||||
|
||||
// Find the maximum allowed image size considering min size limits
|
||||
double maxImageBasis = frameBasis;
|
||||
double maxImageOther = frameOther;
|
||||
if (framing.minSizeEnabled) {
|
||||
double minBorderBasis = static_cast<double>(
|
||||
side == Side::WIDTH ? framing.minWidth : framing.minHeight);
|
||||
double minBorderOther = static_cast<double>(
|
||||
side == Side::WIDTH ? framing.minHeight : framing.minWidth);
|
||||
|
||||
maxImageOther = std::floor(frameOther - 2.0 * minBorderOther);
|
||||
maxImageBasis = std::floor(frameBasis - 2.0 * minBorderBasis);
|
||||
}
|
||||
|
||||
// Image is too large to satisfy requirements:
|
||||
// a. Min border size limit not satisfied
|
||||
// b. Basis size is too small for the requested aspect ratio
|
||||
// (i.e. original image clipped)
|
||||
//
|
||||
// Resize the image so that it fits in bounds
|
||||
if (imgOther > maxImageOther) {
|
||||
imgOther = maxImageOther;
|
||||
imgBasis = imgOther / imgBasisToOther;
|
||||
}
|
||||
if (imgBasis > maxImageBasis) {
|
||||
imgBasis = maxImageBasis;
|
||||
imgOther = imgBasis * imgBasisToOther;
|
||||
}
|
||||
|
||||
if (side == Side::WIDTH) {
|
||||
return Dimensions(imgBasis, imgOther);
|
||||
} else {
|
||||
return Dimensions(imgOther, imgBasis);
|
||||
}
|
||||
}
|
||||
|
||||
Dimensions Framing::computeUniformRelativeImageBBox(const Dimensions& imgSize,
|
||||
const Dimensions& framedSize) const
|
||||
{
|
||||
if (imgSize.isDegenerate() || framedSize.isDegenerate()) {
|
||||
return Dimensions(0, 0);
|
||||
}
|
||||
|
||||
Side side = pickReferenceSide(framing, imgSize);
|
||||
double scale = framing.relativeBorderSize;
|
||||
|
||||
// Compute image and border lengths on basis side
|
||||
double frameBasis = side == Side::WIDTH ? framedSize.width : framedSize.height;
|
||||
double frameOther = side == Side::WIDTH ? framedSize.height : framedSize.width;
|
||||
|
||||
auto computedSizes = computeImgAndBorderSize(frameBasis, scale);
|
||||
double imgBasis = computedSizes.first;
|
||||
double border = computedSizes.second;
|
||||
|
||||
// Compute image and border lengths for the non-basis side
|
||||
double imgAspectRatio = imgSize.aspectRatio();
|
||||
double imgBasisToOther = side == Side::WIDTH ? 1.0 / imgAspectRatio : imgAspectRatio;
|
||||
double imgOther = imgBasis * imgBasisToOther;
|
||||
|
||||
// If the frame doesn't constrain the non-basis side length, we just need
|
||||
// to check the border minimum size. However, if the non-basis side is
|
||||
// constrained, we need to adjust the image size to fit while still
|
||||
// maintaining the border scale w.r.t. the basis side.
|
||||
double totalOther = imgOther + 2.0 * border;
|
||||
if (totalOther > frameOther) {
|
||||
// Let:
|
||||
// imgOther = imgBasis * imgBasisToOther
|
||||
// border = imgBasis * scale
|
||||
//
|
||||
// Want:
|
||||
// frameOther = imgOther + 2 * border
|
||||
// = imgBasis * imgBasisToOther + 2 * scale * imgBasis
|
||||
// = imgBasis * (imgBasisToOther + 2 * scale)
|
||||
//
|
||||
// Rearrange:
|
||||
// imgBasis = frameOther / (imgBasisToOther + 2 * scale)
|
||||
imgBasis = frameOther / (imgBasisToOther + 2.0 * scale);
|
||||
imgOther = imgBasis * imgBasisToOther;
|
||||
border = imgBasis * scale;
|
||||
}
|
||||
|
||||
// Find the maximum allowed image size considering min size limits
|
||||
double maxImageBasis = frameBasis;
|
||||
double maxImageOther = frameOther;
|
||||
if (framing.minSizeEnabled) {
|
||||
double minBorder = static_cast<double>(
|
||||
side == Side::WIDTH ? framing.minWidth : framing.minHeight);
|
||||
|
||||
maxImageBasis = std::floor(frameBasis - 2.0 * minBorder);
|
||||
maxImageOther = std::floor(frameOther - 2.0 * minBorder);
|
||||
}
|
||||
|
||||
if (imgOther > maxImageOther) {
|
||||
imgOther = maxImageOther;
|
||||
imgBasis = imgOther / imgBasisToOther;
|
||||
}
|
||||
if (imgBasis > maxImageBasis) {
|
||||
imgBasis = maxImageBasis;
|
||||
imgOther = imgBasis * imgBasisToOther;
|
||||
}
|
||||
|
||||
if (side == Side::WIDTH) {
|
||||
return Dimensions(imgBasis, imgOther);
|
||||
} else {
|
||||
return Dimensions(imgOther, imgBasis);
|
||||
}
|
||||
}
|
||||
|
||||
ResizeArgs Framing::adjustResizeForFraming(const ResizeArgs& resize) const
|
||||
{
|
||||
if (!framing.enabled) return resize;
|
||||
|
||||
switch (framing.framingMethod) {
|
||||
case FramingMethod::BBOX:
|
||||
return resizeForBBox(resize);
|
||||
case FramingMethod::FIXED_SIZE:
|
||||
return resizeForFixedFrame(resize);
|
||||
case FramingMethod::STANDARD:
|
||||
default:
|
||||
// No limits on framed size so do nothing
|
||||
return resize;
|
||||
}
|
||||
}
|
||||
|
||||
ResizeArgs Framing::resizeForFixedFrame(const ResizeArgs& args) const
|
||||
{
|
||||
double framedWidth = framing.framedWidth;
|
||||
double framedHeight = framing.framedHeight;
|
||||
Dimensions frameSize(framedWidth, framedHeight);
|
||||
|
||||
Dimensions bbox;
|
||||
if (framing.borderSizingMethod == BorderSizing::FIXED_SIZE) {
|
||||
auto length = [](double frame, double border) {
|
||||
return std::max(0.0, frame - 2.0 * border);
|
||||
};
|
||||
|
||||
bbox = {
|
||||
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);
|
||||
}
|
||||
|
||||
return adjustResize(args, bbox);
|
||||
}
|
||||
|
||||
ResizeArgs Framing::resizeForBBox(const ResizeArgs& args) const
|
||||
{
|
||||
Dimensions boundary(framing.framedWidth, framing.framedHeight);
|
||||
|
||||
Dimensions bbox;
|
||||
if (framing.borderSizingMethod == BorderSizing::FIXED_SIZE) {
|
||||
auto length = [](double frame, double border) {
|
||||
return std::max(0.0, frame - 2.0 * border);
|
||||
};
|
||||
|
||||
bbox = {
|
||||
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
|
||||
double aspectRatio = orientAspectRatio(framing, args.size);
|
||||
Dimensions ratioBBox = fromAspectRatio(boundary, aspectRatio);
|
||||
ratioBBox = clampToBBox(ratioBBox, boundary, INSIDE_BBOX);
|
||||
|
||||
// Now we have the true max bounds for the framed image. Determine how the
|
||||
// original image fits inside these bounds. This process is the same as
|
||||
// in the fixed frame mode.
|
||||
bbox = computeRelativeImageBBoxInFrame(args.size, ratioBBox);
|
||||
}
|
||||
|
||||
return adjustResize(args, bbox);
|
||||
}
|
||||
|
||||
Dimensions Framing::computeFramedSize(const Dimensions& imgSize) const
|
||||
{
|
||||
if (!framing.enabled) return imgSize;
|
||||
|
||||
// For constrained frame sizes, check if the image size (without frame)
|
||||
// exceeds the constrained size. This indicates that a combination of
|
||||
// parameters caused the downscaling limit to be hit. In which case,
|
||||
// just return the original image size (i.e. don't insert border).
|
||||
//
|
||||
// If the image fits the constrained size, assume that previous resize
|
||||
// calculations were correct and trim off any excess borders. The excess
|
||||
// may be from rounding errors or hitting some downscaling limit.
|
||||
switch (framing.framingMethod) {
|
||||
case FramingMethod::BBOX:
|
||||
{
|
||||
Dimensions fixed(framing.framedWidth, framing.framedHeight);
|
||||
if (imgSize.inside(fixed)) {
|
||||
Dimensions framedSize = computeSizeWithBorders(imgSize);
|
||||
return clampToBBox(framedSize, fixed, INSIDE_BBOX);
|
||||
} else {
|
||||
return imgSize;
|
||||
}
|
||||
}
|
||||
case FramingMethod::FIXED_SIZE:
|
||||
{
|
||||
Dimensions fixed(framing.framedWidth, framing.framedHeight);
|
||||
return imgSize.inside(fixed) ? fixed : imgSize;
|
||||
}
|
||||
case FramingMethod::STANDARD:
|
||||
default:
|
||||
return computeSizeWithBorders(imgSize);
|
||||
}
|
||||
}
|
||||
|
||||
Dimensions Framing::computeSizeWithBorders(const Dimensions& imgSize) const
|
||||
{
|
||||
if (framing.borderSizingMethod == BorderSizing::FIXED_SIZE) {
|
||||
return Dimensions(imgSize.width + 2.0 * framing.absWidth,
|
||||
imgSize.height + 2.0 * framing.absHeight);
|
||||
}
|
||||
|
||||
Side side = pickReferenceSide(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.height;
|
||||
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;
|
||||
framedSize.height = framedSize.width / aspectRatio;
|
||||
} else {
|
||||
framedSize.height = (1.0 + 2.0 * scale) * imgSize.height;
|
||||
framedSize.width = framedSize.height * aspectRatio;
|
||||
}
|
||||
|
||||
// Check if the computed frame size satsifies the requested aspect ratio
|
||||
// without cutting off the original image. If the image is cut off, use
|
||||
// the smallest frame that preserves the original image and still
|
||||
// satisfies the requested aspect ratio.
|
||||
Dimensions minFramedSize = fromAspectRatio(imgSize, aspectRatio);
|
||||
Dimensions limit = imgSize;
|
||||
if (framing.minSizeEnabled) {
|
||||
limit.width += 2.0 * framing.minWidth;
|
||||
limit.height += 2.0 * framing.minHeight;
|
||||
}
|
||||
minFramedSize = clampToBBox(minFramedSize, limit, OUTSIDE_BBOX);
|
||||
|
||||
if (minFramedSize.inside(framedSize)) {
|
||||
return framedSize;
|
||||
} else {
|
||||
return minFramedSize;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace rtengine
|
||||
{
|
||||
@ -333,7 +1006,7 @@ void ImProcFunctions::Lanczos (const LabImage* src, LabImage* dst, float scale)
|
||||
delete[] wwh;
|
||||
}
|
||||
|
||||
float ImProcFunctions::resizeScale (const ProcParams* params, int fw, int fh, int &imw, int &imh)
|
||||
double ImProcFunctions::resizeScale (const ProcParams* params, int fw, int fh, int &imw, int &imh)
|
||||
{
|
||||
imw = fw;
|
||||
imh = fh;
|
||||
@ -406,10 +1079,6 @@ float ImProcFunctions::resizeScale (const ProcParams* params, int fw, int fh, in
|
||||
break;
|
||||
}
|
||||
|
||||
if (fabs (dScale - 1.0) <= 1e-5) {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
if (params->crop.enabled && params->resize.appliesTo == "Full image") {
|
||||
imw = params->crop.w;
|
||||
imh = params->crop.h;
|
||||
@ -418,9 +1087,13 @@ float ImProcFunctions::resizeScale (const ProcParams* params, int fw, int fh, in
|
||||
imh = refh;
|
||||
}
|
||||
|
||||
imw = (int) ( (double)imw * dScale + 0.5 );
|
||||
imh = (int) ( (double)imh * dScale + 0.5 );
|
||||
return (float)dScale;
|
||||
if (fabs (dScale - 1.0) <= 1e-5) {
|
||||
return 1.0;
|
||||
} else {
|
||||
imw = computeSize(imw, dScale);
|
||||
imh = computeSize(imh, dScale);
|
||||
return dScale;
|
||||
}
|
||||
}
|
||||
|
||||
void ImProcFunctions::resize (Imagefloat* src, Imagefloat* dst, float dScale)
|
||||
@ -458,4 +1131,99 @@ void ImProcFunctions::resize (Imagefloat* src, Imagefloat* dst, float dScale)
|
||||
#endif
|
||||
}
|
||||
|
||||
ImProcFunctions::FramingData ImProcFunctions::framing(const FramingArgs& args) const
|
||||
{
|
||||
FramingData result;
|
||||
result.enabled = false;
|
||||
result.imgWidth = args.resizeWidth;
|
||||
result.imgHeight = args.resizeHeight;
|
||||
result.scale = args.resizeScale;
|
||||
result.framedWidth = args.resizeWidth;
|
||||
result.framedHeight = args.resizeHeight;
|
||||
|
||||
if (!args.params || !args.params->resize.enabled) return result;
|
||||
if (!args.params->framing.enabled) return result;
|
||||
|
||||
// For these calculations, try to keep everything as doubles to minimize
|
||||
// rounding errors from intermediate steps!
|
||||
|
||||
Framing util(*params, args.cropWidth, args.cropHeight);
|
||||
ResizeArgs resize(Dimensions(args.resizeWidth, args.resizeHeight), args.resizeScale);
|
||||
ResizeArgs adjusted = util.adjustResizeForFraming(resize);
|
||||
Dimensions framedSize = util.computeFramedSize(adjusted.size);
|
||||
|
||||
result.enabled = true;
|
||||
result.imgWidth = std::round(adjusted.size.width);
|
||||
result.imgHeight = std::round(adjusted.size.height);
|
||||
result.scale = adjusted.scale;
|
||||
result.framedWidth = std::round(framedSize.width);
|
||||
result.framedHeight = std::round(framedSize.height);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Draws the border around the input image.
|
||||
// It should be called after gamma correction.
|
||||
Imagefloat* ImProcFunctions::drawFrame(Imagefloat* rgb, const FramingParams& params,
|
||||
const FramingData& dims) const
|
||||
{
|
||||
if (rgb->getWidth() > dims.framedWidth || rgb->getHeight() > dims.framedHeight) {
|
||||
return rgb;
|
||||
}
|
||||
if (rgb->getWidth() == dims.framedWidth && rgb->getHeight() == dims.framedHeight) {
|
||||
return rgb;
|
||||
}
|
||||
|
||||
Imagefloat* framed = new Imagefloat(dims.framedWidth, dims.framedHeight);
|
||||
|
||||
// Color::gamma2curve expects a 16-bit value, but the GUI sliders are
|
||||
// using 8-bit values. Step up the user value to 16-bits.
|
||||
auto clip = [](int v) -> int {
|
||||
int sanitized = std::max(0, std::min(v, 255));
|
||||
|
||||
double normalized = static_cast<double>(sanitized) / 255.0;
|
||||
return normalized * 65535.0;
|
||||
};
|
||||
|
||||
float r = Color::gamma2curve[clip(params.borderRed)];
|
||||
float g = Color::gamma2curve[clip(params.borderGreen)];
|
||||
float b = Color::gamma2curve[clip(params.borderBlue)];
|
||||
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for if (multiThread)
|
||||
#endif
|
||||
for (int i = 0; i < framed->getHeight(); i++) {
|
||||
for (int j = 0; j < framed->getWidth(); j++) {
|
||||
framed->r(i, j) = r;
|
||||
framed->g(i, j) = g;
|
||||
framed->b(i, j) = b;
|
||||
}
|
||||
}
|
||||
|
||||
auto offset = [](int inner, int outer) {
|
||||
double u = inner;
|
||||
double v = outer;
|
||||
return static_cast<int>(std::round((v - u) / 2.0));
|
||||
};
|
||||
int rowOffset = offset(rgb->getHeight(), framed->getHeight());
|
||||
int colOffset = offset(rgb->getWidth(), framed->getWidth());
|
||||
|
||||
#ifdef _OPENMP
|
||||
#pragma omp parallel for if (multiThread)
|
||||
#endif
|
||||
for (int i = 0; i < rgb->getHeight(); i++) {
|
||||
for (int j = 0; j < rgb->getWidth(); j++) {
|
||||
int row = i + rowOffset;
|
||||
int col = j + colOffset;
|
||||
|
||||
framed->r(row, col) = rgb->r(i, j);
|
||||
framed->g(row, col) = rgb->g(i, j);
|
||||
framed->b(row, col) = rgb->b(i, j);
|
||||
}
|
||||
}
|
||||
|
||||
delete rgb;
|
||||
return framed;
|
||||
}
|
||||
|
||||
} // namespace rtengine
|
||||
|
@ -1177,7 +1177,6 @@ enum ProcEventCode {
|
||||
Evlocallabsigjz = 1147,
|
||||
Evlocallabsigq = 1148,
|
||||
Evlocallablogcie = 1149,
|
||||
|
||||
NUMOFEVENTS
|
||||
};
|
||||
|
||||
|
@ -427,6 +427,181 @@ bool saveToKeyfile(
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace ProfileKeys {
|
||||
|
||||
#define DEFINE_KEY(VAR, NAME) \
|
||||
constexpr const char* VAR = NAME;
|
||||
|
||||
DEFINE_KEY(TOOL_ENABLED, "Enabled");
|
||||
|
||||
namespace Framing
|
||||
{
|
||||
DEFINE_KEY(TOOL_NAME, "Framing");
|
||||
|
||||
// Fields
|
||||
DEFINE_KEY(FRAMING_METHOD, "FramingMethod");
|
||||
DEFINE_KEY(ASPECT_RATIO, "AspectRatio");
|
||||
DEFINE_KEY(ORIENTATION, "Orientation");
|
||||
DEFINE_KEY(FRAMED_WIDTH, "FramedWidth");
|
||||
DEFINE_KEY(FRAMED_HEIGHT, "FramedHeight");
|
||||
DEFINE_KEY(ALLOW_UPSCALING, "AllowUpscaling");
|
||||
|
||||
DEFINE_KEY(BORDER_SIZING_METHOD, "BorderSizingMethod");
|
||||
DEFINE_KEY(BASIS, "Basis");
|
||||
DEFINE_KEY(RELATIVE_BORDER_SIZE, "RelativeBorderSize");
|
||||
DEFINE_KEY(MIN_SIZE_ENABLED, "MinSizeEnabled");
|
||||
DEFINE_KEY(MIN_WIDTH, "MinWidth");
|
||||
DEFINE_KEY(MIN_HEIGHT, "MinHeight");
|
||||
DEFINE_KEY(ABS_WIDTH, "AbsWidth");
|
||||
DEFINE_KEY(ABS_HEIGHT, "AbsHeight");
|
||||
|
||||
DEFINE_KEY(BORDER_RED, "BorderRed");
|
||||
DEFINE_KEY(BORDER_GREEN, "BorderGreen");
|
||||
DEFINE_KEY(BORDER_BLUE, "BorderBlue");
|
||||
|
||||
// Enum mappings
|
||||
DEFINE_KEY(FRAMING_METHOD_STANDARD, "Standard");
|
||||
DEFINE_KEY(FRAMING_METHOD_BBOX, "BoundingBox");
|
||||
DEFINE_KEY(FRAMING_METHOD_FIXED_SIZE, "FixedSize");
|
||||
DEFINE_KEY(ORIENT_AS_IMAGE, "AsImage");
|
||||
DEFINE_KEY(ORIENT_LANDSCAPE, "Landscape");
|
||||
DEFINE_KEY(ORIENT_PORTRAIT, "Portrait");
|
||||
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");
|
||||
DEFINE_KEY(BASIS_HEIGHT, "Height");
|
||||
DEFINE_KEY(BASIS_LONG, "Long");
|
||||
DEFINE_KEY(BASIS_SHORT, "Short");
|
||||
} // namespace Framing
|
||||
|
||||
} // namespace ProfileKeys
|
||||
|
||||
void loadFramingParams(
|
||||
const Glib::KeyFile& keyFile,
|
||||
rtengine::procparams::FramingParams& params,
|
||||
FramingParamsEdited& edited
|
||||
)
|
||||
{
|
||||
using namespace ProfileKeys;
|
||||
using namespace ProfileKeys::Framing;
|
||||
using FramingParams = rtengine::procparams::FramingParams;
|
||||
|
||||
const Glib::ustring group{TOOL_NAME};
|
||||
if (!keyFile.has_group(group)) return;
|
||||
|
||||
assignFromKeyfile(keyFile, group, TOOL_ENABLED, params.enabled, edited.enabled);
|
||||
|
||||
using FramingMethod = FramingParams::FramingMethod;
|
||||
const std::map<std::string, FramingMethod> framingMethodMapping = {
|
||||
{FRAMING_METHOD_STANDARD, FramingMethod::STANDARD},
|
||||
{FRAMING_METHOD_BBOX, FramingMethod::BBOX},
|
||||
{FRAMING_METHOD_FIXED_SIZE, FramingMethod::FIXED_SIZE}
|
||||
};
|
||||
assignFromKeyfile(keyFile, group, FRAMING_METHOD, framingMethodMapping, params.framingMethod, edited.framingMethod);
|
||||
assignFromKeyfile(keyFile, group, ASPECT_RATIO, params.aspectRatio, edited.aspectRatio);
|
||||
using Orientation = FramingParams::Orientation;
|
||||
const std::map<std::string, Orientation> orientationMapping = {
|
||||
{ORIENT_AS_IMAGE, Orientation::AS_IMAGE},
|
||||
{ORIENT_LANDSCAPE, Orientation::LANDSCAPE},
|
||||
{ORIENT_PORTRAIT, Orientation::PORTRAIT},
|
||||
};
|
||||
assignFromKeyfile(keyFile, group, ORIENTATION, orientationMapping, params.orientation, edited.orientation);
|
||||
assignFromKeyfile(keyFile, group, FRAMED_WIDTH, params.framedWidth, edited.framedWidth);
|
||||
assignFromKeyfile(keyFile, group, FRAMED_HEIGHT, params.framedHeight, edited.framedHeight);
|
||||
assignFromKeyfile(keyFile, group, ALLOW_UPSCALING, params.allowUpscaling, edited.allowUpscaling);
|
||||
|
||||
using BorderSizing = FramingParams::BorderSizing;
|
||||
const std::map<std::string, BorderSizing> 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);
|
||||
using Basis = FramingParams::Basis;
|
||||
const std::map<std::string, Basis> basisMapping = {
|
||||
{BASIS_AUTO, Basis::AUTO},
|
||||
{BASIS_WIDTH, Basis::WIDTH},
|
||||
{BASIS_HEIGHT, Basis::HEIGHT},
|
||||
{BASIS_LONG, Basis::LONG},
|
||||
{BASIS_SHORT, Basis::SHORT}
|
||||
};
|
||||
assignFromKeyfile(keyFile, group, BASIS, basisMapping, params.basis, edited.basis);
|
||||
assignFromKeyfile(keyFile, group, RELATIVE_BORDER_SIZE, params.relativeBorderSize, edited.relativeBorderSize);
|
||||
assignFromKeyfile(keyFile, group, MIN_SIZE_ENABLED, params.minSizeEnabled, edited.minSizeEnabled);
|
||||
assignFromKeyfile(keyFile, group, MIN_WIDTH, params.minWidth, edited.minWidth);
|
||||
assignFromKeyfile(keyFile, group, MIN_HEIGHT, params.minHeight, edited.minHeight);
|
||||
assignFromKeyfile(keyFile, group, ABS_WIDTH, params.absWidth, edited.absWidth);
|
||||
assignFromKeyfile(keyFile, group, ABS_HEIGHT, params.absHeight, edited.absHeight);
|
||||
|
||||
assignFromKeyfile(keyFile, group, BORDER_RED, params.borderRed, edited.borderRed);
|
||||
assignFromKeyfile(keyFile, group, BORDER_GREEN, params.borderGreen, edited.borderGreen);
|
||||
assignFromKeyfile(keyFile, group, BORDER_BLUE, params.borderBlue, edited.borderBlue);
|
||||
}
|
||||
|
||||
void saveFramingParams(
|
||||
Glib::KeyFile& keyFile,
|
||||
const rtengine::procparams::FramingParams& params,
|
||||
const ParamsEdited* pedited
|
||||
)
|
||||
{
|
||||
using namespace ProfileKeys;
|
||||
using namespace ProfileKeys::Framing;
|
||||
using FramingParams = rtengine::procparams::FramingParams;
|
||||
|
||||
const Glib::ustring group{TOOL_NAME};
|
||||
|
||||
const FramingParamsEdited& edited = pedited->framing;
|
||||
|
||||
saveToKeyfile(!pedited || edited.enabled, group, TOOL_ENABLED, params.enabled, keyFile);
|
||||
|
||||
using FramingMethod = FramingParams::FramingMethod;
|
||||
const std::map<FramingMethod, const char*> framingMethodMapping = {
|
||||
{FramingMethod::STANDARD, FRAMING_METHOD_STANDARD},
|
||||
{FramingMethod::BBOX, FRAMING_METHOD_BBOX},
|
||||
{FramingMethod::FIXED_SIZE, FRAMING_METHOD_FIXED_SIZE}
|
||||
};
|
||||
saveToKeyfile(!pedited || edited.framingMethod, group, FRAMING_METHOD, framingMethodMapping, params.framingMethod, keyFile);
|
||||
saveToKeyfile(!pedited || edited.aspectRatio, group, ASPECT_RATIO, params.aspectRatio, keyFile);
|
||||
using Orientation = FramingParams::Orientation;
|
||||
const std::map<Orientation, const char*> orientationMapping = {
|
||||
{Orientation::AS_IMAGE, ORIENT_AS_IMAGE},
|
||||
{Orientation::LANDSCAPE, ORIENT_LANDSCAPE},
|
||||
{Orientation::PORTRAIT, ORIENT_PORTRAIT},
|
||||
};
|
||||
saveToKeyfile(!pedited || edited.orientation, group, ORIENTATION, orientationMapping, params.orientation, keyFile);
|
||||
saveToKeyfile(!pedited || edited.framedWidth, group, FRAMED_WIDTH, params.framedWidth, keyFile);
|
||||
saveToKeyfile(!pedited || edited.framedHeight, group, FRAMED_HEIGHT, params.framedHeight, keyFile);
|
||||
saveToKeyfile(!pedited || edited.allowUpscaling, group, ALLOW_UPSCALING, params.allowUpscaling, keyFile);
|
||||
|
||||
using BorderSizing = FramingParams::BorderSizing;
|
||||
const std::map<BorderSizing, const char*> 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);
|
||||
using Basis = FramingParams::Basis;
|
||||
const std::map<Basis, const char*> basisMapping = {
|
||||
{Basis::AUTO, BASIS_AUTO},
|
||||
{Basis::WIDTH, BASIS_WIDTH},
|
||||
{Basis::HEIGHT, BASIS_HEIGHT},
|
||||
{Basis::LONG, BASIS_LONG},
|
||||
{Basis::SHORT, BASIS_SHORT}
|
||||
};
|
||||
saveToKeyfile(!pedited || edited.basis, group, BASIS, basisMapping, params.basis, keyFile);
|
||||
saveToKeyfile(!pedited || edited.relativeBorderSize, group, RELATIVE_BORDER_SIZE, params.relativeBorderSize, keyFile);
|
||||
saveToKeyfile(!pedited || edited.minSizeEnabled, group, MIN_SIZE_ENABLED, params.minSizeEnabled, keyFile);
|
||||
saveToKeyfile(!pedited || edited.minWidth, group, MIN_WIDTH, params.minWidth, keyFile);
|
||||
saveToKeyfile(!pedited || edited.minHeight, group, MIN_HEIGHT, params.minHeight, keyFile);
|
||||
saveToKeyfile(!pedited || edited.absWidth, group, ABS_WIDTH, params.absWidth, keyFile);
|
||||
saveToKeyfile(!pedited || edited.absHeight, group, ABS_HEIGHT, params.absHeight, keyFile);
|
||||
|
||||
saveToKeyfile(!pedited || edited.borderRed, group, BORDER_RED, params.borderRed, keyFile);
|
||||
saveToKeyfile(!pedited || edited.borderGreen, group, BORDER_GREEN, params.borderGreen, keyFile);
|
||||
saveToKeyfile(!pedited || edited.borderBlue, group, BORDER_BLUE, params.borderBlue, keyFile);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
@ -2425,6 +2600,56 @@ bool ResizeParams::operator !=(const ResizeParams& other) const
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
FramingParams::FramingParams() :
|
||||
enabled(false),
|
||||
framingMethod(FramingMethod::STANDARD),
|
||||
aspectRatio(0),
|
||||
orientation(Orientation::AS_IMAGE),
|
||||
framedWidth(800),
|
||||
framedHeight(600),
|
||||
allowUpscaling(false),
|
||||
borderSizingMethod(BorderSizing::PERCENTAGE),
|
||||
basis(Basis::AUTO),
|
||||
relativeBorderSize(0.1),
|
||||
minSizeEnabled(false),
|
||||
minWidth(0),
|
||||
minHeight(0),
|
||||
absWidth(0),
|
||||
absHeight(0),
|
||||
borderRed(255),
|
||||
borderGreen(255),
|
||||
borderBlue(255)
|
||||
{
|
||||
}
|
||||
|
||||
bool FramingParams::operator ==(const FramingParams& other) const
|
||||
{
|
||||
return
|
||||
enabled == other.enabled
|
||||
&& framingMethod == other.framingMethod
|
||||
&& aspectRatio == other.aspectRatio
|
||||
&& orientation == other.orientation
|
||||
&& framedWidth == other.framedWidth
|
||||
&& framedHeight == other.framedHeight
|
||||
&& allowUpscaling == other.allowUpscaling
|
||||
&& borderSizingMethod == other.borderSizingMethod
|
||||
&& basis == other.basis
|
||||
&& relativeBorderSize == other.relativeBorderSize
|
||||
&& minSizeEnabled == other.minSizeEnabled
|
||||
&& minWidth == other.minWidth
|
||||
&& minHeight == other.minHeight
|
||||
&& absWidth == other.absWidth
|
||||
&& absHeight == other.absHeight
|
||||
&& borderRed == other.borderRed
|
||||
&& borderGreen == other.borderGreen
|
||||
&& borderBlue == other.borderBlue;
|
||||
}
|
||||
|
||||
bool FramingParams::operator !=(const FramingParams& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
const Glib::ustring ColorManagementParams::NoICMString = Glib::ustring("No ICM: sRGB output");
|
||||
const Glib::ustring ColorManagementParams::NoProfileString = Glib::ustring("(none)");
|
||||
|
||||
@ -6358,6 +6583,8 @@ void ProcParams::setDefaults()
|
||||
|
||||
resize = {};
|
||||
|
||||
framing = {};
|
||||
|
||||
icm = {};
|
||||
|
||||
wavelet = {};
|
||||
@ -7697,6 +7924,8 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
|
||||
saveToKeyfile(!pedited || pedited->resize.shortedge, "Resize", "ShortEdge", resize.shortedge, keyFile);
|
||||
saveToKeyfile(!pedited || pedited->resize.allowUpscaling, "Resize", "AllowUpscaling", resize.allowUpscaling, keyFile);
|
||||
|
||||
saveFramingParams(keyFile, framing, pedited);
|
||||
|
||||
// Post demosaic sharpening
|
||||
saveToKeyfile(!pedited || pedited->pdsharpening.enabled, "PostDemosaicSharpening", "Enabled", pdsharpening.enabled, keyFile);
|
||||
saveToKeyfile(!pedited || pedited->pdsharpening.contrast, "PostDemosaicSharpening", "Contrast", pdsharpening.contrast, keyFile);
|
||||
@ -10252,6 +10481,8 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
|
||||
}
|
||||
}
|
||||
|
||||
loadFramingParams(keyFile, framing, pedited->framing);
|
||||
|
||||
if (keyFile.has_group ("Spot removal")) {
|
||||
assignFromKeyfile(keyFile, "Spot removal", "Enabled", spot.enabled, pedited->spot.enabled);
|
||||
int i = 0;
|
||||
@ -11498,6 +11729,7 @@ bool ProcParams::operator ==(const ProcParams& other) const
|
||||
&& chmixer == other.chmixer
|
||||
&& blackwhite == other.blackwhite
|
||||
&& resize == other.resize
|
||||
&& framing == other.framing
|
||||
&& spot == other.spot
|
||||
&& raw == other.raw
|
||||
&& icm == other.icm
|
||||
|
@ -1984,6 +1984,68 @@ struct ResizeParams {
|
||||
bool operator !=(const ResizeParams& other) const;
|
||||
};
|
||||
|
||||
struct FramingParams {
|
||||
// How is framed size determined?
|
||||
enum class FramingMethod {
|
||||
STANDARD, // Unconstrained framed size
|
||||
BBOX, // Framed size within bounding box
|
||||
FIXED_SIZE // Fixed framed size
|
||||
};
|
||||
|
||||
// Orientation of framed image
|
||||
enum class Orientation {
|
||||
AS_IMAGE,
|
||||
LANDSCAPE,
|
||||
PORTRAIT
|
||||
};
|
||||
|
||||
// How to size border?
|
||||
enum class BorderSizing {
|
||||
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?
|
||||
enum class Basis {
|
||||
AUTO, // Determine by aspect ratio of image and frame
|
||||
WIDTH,
|
||||
HEIGHT,
|
||||
LONG, // Use long side of image
|
||||
SHORT // Use short side of image
|
||||
};
|
||||
|
||||
// Indicates to use the image aspect ratio for border
|
||||
static constexpr double AS_IMAGE_ASPECT_RATIO = 0.0;
|
||||
|
||||
FramingParams();
|
||||
|
||||
bool enabled;
|
||||
|
||||
FramingMethod framingMethod;
|
||||
double aspectRatio;
|
||||
Orientation orientation;
|
||||
int framedWidth;
|
||||
int framedHeight;
|
||||
bool allowUpscaling;
|
||||
|
||||
BorderSizing borderSizingMethod;
|
||||
Basis basis;
|
||||
double relativeBorderSize;
|
||||
bool minSizeEnabled;
|
||||
int minWidth;
|
||||
int minHeight;
|
||||
int absWidth;
|
||||
int absHeight;
|
||||
|
||||
int borderRed;
|
||||
int borderGreen;
|
||||
int borderBlue;
|
||||
|
||||
bool operator ==(const FramingParams& other) const;
|
||||
bool operator !=(const FramingParams& other) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parameters entry
|
||||
*/
|
||||
@ -2764,6 +2826,7 @@ public:
|
||||
ChannelMixerParams chmixer; ///< Channel mixer parameters
|
||||
BlackWhiteParams blackwhite; ///< Black& White parameters
|
||||
ResizeParams resize; ///< Resize parameters
|
||||
FramingParams framing; ///< Framing parameters
|
||||
SpotParams spot; ///< Spot removal tool
|
||||
ColorManagementParams icm; ///< profiles/color spaces used during the image processing
|
||||
RAWParams raw; ///< RAW parameters before demosaicing
|
||||
|
@ -1185,7 +1185,7 @@ int refreshmap[rtengine::NUMOFEVENTS] = {
|
||||
AUTOEXP, //Evlocallabforcebw
|
||||
AUTOEXP, //Evlocallabsigjz
|
||||
AUTOEXP, //Evlocallabsigq
|
||||
AUTOEXP //Evlocallablogcie
|
||||
AUTOEXP //Evlocallablogcie
|
||||
};
|
||||
|
||||
|
||||
|
@ -1893,20 +1893,52 @@ private:
|
||||
pl->setProgress(0.60);
|
||||
}
|
||||
|
||||
int imw, imh;
|
||||
double tmpScale = ipf.resizeScale(¶ms, fw, fh, imw, imh);
|
||||
bool labResize = params.resize.enabled && params.resize.method != "Nearest" && (tmpScale != 1.0 || params.prsharpening.enabled);
|
||||
LabImage *tmplab;
|
||||
|
||||
// crop and convert to rgb16
|
||||
int cx = 0, cy = 0, cw = labView->W, ch = labView->H;
|
||||
|
||||
if (params.crop.enabled) {
|
||||
cx = params.crop.x;
|
||||
cy = params.crop.y;
|
||||
cw = params.crop.w;
|
||||
ch = params.crop.h;
|
||||
}
|
||||
|
||||
ImProcFunctions::FramingArgs framingArgs;
|
||||
framingArgs.params = ¶ms;
|
||||
framingArgs.cropWidth = cw;
|
||||
framingArgs.cropHeight = ch;
|
||||
{
|
||||
int imw, imh;
|
||||
double tmpScale = ipf.resizeScale(¶ms, fw, fh, imw, imh);
|
||||
framingArgs.resizeWidth = imw;
|
||||
framingArgs.resizeHeight = imh;
|
||||
framingArgs.resizeScale = tmpScale;
|
||||
|
||||
// If upscaling is not permitted, keep original sizing
|
||||
if ((cw < imw || ch < imh) && !params.resize.allowUpscaling) {
|
||||
framingArgs.resizeWidth = cw;
|
||||
framingArgs.resizeHeight = ch;
|
||||
framingArgs.resizeScale = 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
// If framing is not enabled, resize values simply pass through to output
|
||||
ImProcFunctions::FramingData framingData = ipf.framing(framingArgs);
|
||||
if (settings->verbose) {
|
||||
printf("Framing Parameters (enabled=%s)\n", framingData.enabled ? "yes" : "no");
|
||||
printf(" Crop: w=%d h=%d\n", cw, ch);
|
||||
printf(" Original resize: w=%d h=%d s=%f\n",
|
||||
framingArgs.resizeWidth, framingArgs.resizeHeight, framingArgs.resizeScale);
|
||||
printf(" Framed image size: w=%d h=%d s=%f\n",
|
||||
framingData.imgWidth, framingData.imgHeight, framingData.scale);
|
||||
printf(" Total size: w=%d h=%d\n",
|
||||
framingData.framedWidth, framingData.framedHeight);
|
||||
}
|
||||
|
||||
bool labResize = params.resize.enabled && params.resize.method != "Nearest" &&
|
||||
(framingData.scale != 1.0 || params.prsharpening.enabled || framingData.enabled);
|
||||
|
||||
LabImage *tmplab = nullptr;
|
||||
if (params.crop.enabled) {
|
||||
if (labResize) { // crop lab data
|
||||
tmplab = new LabImage(cw, ch);
|
||||
|
||||
@ -1926,11 +1958,12 @@ private:
|
||||
}
|
||||
|
||||
if (labResize) { // resize lab data
|
||||
if ((labView->W != imw || labView->H != imh) &&
|
||||
(params.resize.allowUpscaling || (labView->W >= imw && labView->H >= imh))) {
|
||||
int imw = framingData.imgWidth;
|
||||
int imh = framingData.imgHeight;
|
||||
if (labView->W != imw || labView->H != imh) {
|
||||
// resize image
|
||||
tmplab = new LabImage(imw, imh);
|
||||
ipf.Lanczos(labView, tmplab, tmpScale);
|
||||
ipf.Lanczos(labView, tmplab, framingData.scale);
|
||||
delete labView;
|
||||
labView = tmplab;
|
||||
}
|
||||
@ -1984,12 +2017,20 @@ private:
|
||||
pl->setProgress(0.70);
|
||||
}
|
||||
|
||||
if (tmpScale != 1.0 && params.resize.method == "Nearest" &&
|
||||
(params.resize.allowUpscaling || (readyImg->getWidth() >= imw && readyImg->getHeight() >= imh))) { // resize rgb data (gamma applied)
|
||||
Imagefloat* tempImage = new Imagefloat(imw, imh);
|
||||
ipf.resize(readyImg, tempImage, tmpScale);
|
||||
delete readyImg;
|
||||
readyImg = tempImage;
|
||||
if (framingData.scale != 1.0 && params.resize.method == "Nearest") {
|
||||
int imw = framingData.imgWidth;
|
||||
int imh = framingData.imgHeight;
|
||||
if (readyImg->getWidth() != imw || readyImg->getHeight() != imh) {
|
||||
// resize rgb data (gamma applied)
|
||||
Imagefloat* tempImage = new Imagefloat(imw, imh);
|
||||
ipf.resize(readyImg, tempImage, framingData.scale);
|
||||
delete readyImg;
|
||||
readyImg = tempImage;
|
||||
}
|
||||
}
|
||||
|
||||
if (framingData.enabled) {
|
||||
readyImg = ipf.drawFrame(readyImg, params.framing, framingData);
|
||||
}
|
||||
|
||||
Exiv2Metadata info(imgsrc->getFileName());
|
||||
|
@ -13,6 +13,7 @@ set(CLISOURCEFILES
|
||||
set(NONCLISOURCEFILES
|
||||
adjuster.cc
|
||||
alignedmalloc.cc
|
||||
aspectratios.cc
|
||||
batchqueue.cc
|
||||
batchqueuebuttonset.cc
|
||||
batchqueueentry.cc
|
||||
@ -34,6 +35,7 @@ set(NONCLISOURCEFILES
|
||||
colorappearance.cc
|
||||
coloredbar.cc
|
||||
colortoning.cc
|
||||
colorpreview.cc
|
||||
controllines.cc
|
||||
controlspotpanel.cc
|
||||
coordinateadjuster.cc
|
||||
@ -76,6 +78,7 @@ set(NONCLISOURCEFILES
|
||||
filterpanel.cc
|
||||
flatcurveeditorsubgroup.cc
|
||||
flatfield.cc
|
||||
framing.cc
|
||||
gradient.cc
|
||||
guiutils.cc
|
||||
histogrampanel.cc
|
||||
|
@ -134,6 +134,10 @@ enum {
|
||||
ADDSET_SHARP_EDGETOL,
|
||||
ADDSET_SHARP_HALOCTRL,
|
||||
ADDSET_RESIZE_SCALE,
|
||||
ADDSET_FRAMING_RELATIVE_SCALE,
|
||||
ADDSET_FRAMING_BORDER_RED,
|
||||
ADDSET_FRAMING_BORDER_GREEN,
|
||||
ADDSET_FRAMING_BORDER_BLUE,
|
||||
ADDSET_EPD_STRENGTH,
|
||||
ADDSET_EPD_GAMMA,
|
||||
ADDSET_EPD_EDGESTOPPING,
|
||||
|
65
rtgui/aspectratios.cc
Normal file
65
rtgui/aspectratios.cc
Normal file
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.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 <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 2024-2024 Daniel Gao <daniel.gao.work@gmail.com>
|
||||
*/
|
||||
|
||||
#include "aspectratios.h"
|
||||
|
||||
namespace {
|
||||
|
||||
static const std::vector<AspectRatio> ASPECT_RATIOS {
|
||||
{"3:2", 3.0 / 2.0}, // L1.5, P0.666...
|
||||
{"4:3", 4.0 / 3.0}, // L1.333..., P0.75
|
||||
{"16:9", 16.0 / 9.0}, // L1.777..., P0.5625
|
||||
{"16:10", 16.0 / 10.0}, // L1.6, P0.625
|
||||
{"1:1", 1.0 / 1.0}, // L1, P1
|
||||
{"2:1", 2.0 / 1.0}, // L2, P0.5
|
||||
{"3:1", 3.0 / 1.0}, // L3, P0.333...
|
||||
{"4:1", 4.0 / 1.0}, // L4, P0.25
|
||||
{"5:1", 5.0 / 1.0}, // L5, P0.2
|
||||
{"6:1", 6.0 / 1.0}, // L6, P0.1666...
|
||||
{"7:1", 7.0 / 1.0}, // L7, P0.142...
|
||||
{"4:5", 4.0 / 5.0}, // L1.25, P0.8
|
||||
{"5:7", 5.0 / 7.0}, // L1.4, P0.714...
|
||||
{"6:7", 6.0 / 7.0}, // L1.166..., P0.857...
|
||||
{"6:17", 6.0 / 17.0}, // L2.833..., P0.352...
|
||||
{"24:65 - XPAN", 24.0 / 65.0}, // L2.708..., P0.369...
|
||||
{"1.414 - DIN EN ISO 216", 1.414}, // L1.414, P0.707...
|
||||
{"3.5:5", 3.5 / 5.0}, // L1.428..., P0.7
|
||||
{"8.5:11 - US Letter", 8.5 / 11.0}, // L1.294..., P0.772...
|
||||
{"9.5:12", 9.5 / 12.0}, // L1.263..., P0.791...
|
||||
{"10:12", 10.0 / 12.0}, // L1.2, P0.833...
|
||||
{"11:14", 11.0 / 14.0}, // L1.272..., P0.785...
|
||||
{"11:17 - Tabloid", 11.0 / 17.0}, // L1.545..., P0.647...
|
||||
{"13:19", 13.0 / 19.0}, // L1.461..., P0.684...
|
||||
{"17:22", 17.0 / 22.0}, // L1.294..., P0.772...
|
||||
{"45:35 - ePassport", 45.0 / 35.0}, // L1.285,... P0.777...
|
||||
{"64:27", 64.0 / 27.0}, // L2.370..., P0.421...
|
||||
{"13:18", 13.0 / 18.0}, // L1.384..., P0.722...
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
void fillAspectRatios(std::vector<AspectRatio>& ratios) {
|
||||
ratios.reserve(ratios.size() + ASPECT_RATIOS.size());
|
||||
|
||||
for (const auto& ratio : ASPECT_RATIOS) {
|
||||
ratios.push_back(ratio);
|
||||
}
|
||||
}
|
37
rtgui/aspectratios.h
Normal file
37
rtgui/aspectratios.h
Normal file
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.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 <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 2024-2024 Daniel Gao <daniel.gao.work@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <glibmm/ustring.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
struct AspectRatio {
|
||||
Glib::ustring label;
|
||||
double value;
|
||||
};
|
||||
|
||||
// Pushes known aspect ratios to the given vector.
|
||||
//
|
||||
// Callers should populate ratios for entries like "As Imange" and "Current"
|
||||
// before calling this function.
|
||||
void fillAspectRatios(std::vector<AspectRatio>& ratios);
|
@ -151,6 +151,7 @@ void BatchToolPanelCoordinator::initSession ()
|
||||
colorappearance->setAdjusterBehavior (false, false, false, false, false, false, false, false, false, false, false, false, false, false, false);
|
||||
rotate->setAdjusterBehavior (false);
|
||||
resize->setAdjusterBehavior (false);
|
||||
framing->setAdjusterBehavior (false, false, false, false);
|
||||
distortion->setAdjusterBehavior (false, false);
|
||||
perspective->setAdjusterBehavior (false, false, false, false, false, false, false);
|
||||
gradient->setAdjusterBehavior (false, false, false, false);
|
||||
@ -196,6 +197,11 @@ void BatchToolPanelCoordinator::initSession ()
|
||||
colorappearance->setAdjusterBehavior (options.baBehav[ADDSET_CAT_DEGREE], options.baBehav[ADDSET_CAT_ADAPTSCENE], options.baBehav[ADDSET_CAT_ADAPTVIEWING], options.baBehav[ADDSET_CAT_BADPIX], options.baBehav[ADDSET_CAT_LIGHT], options.baBehav[ADDSET_CAT_CHROMA], options.baBehav[ADDSET_CAT_CONTRAST], options.baBehav[ADDSET_CAT_RSTPRO], options.baBehav[ADDSET_CAT_BRIGHT], options.baBehav[ADDSET_CAT_CONTRAST_Q], options.baBehav[ADDSET_CAT_CHROMA_S], options.baBehav[ADDSET_CAT_CHROMA_M], options.baBehav[ADDSET_CAT_HUE],options.baBehav[ADDSET_CAT_DEGREEOUT], options.baBehav[ADDSET_CAT_TEMPOUT] );
|
||||
rotate->setAdjusterBehavior (options.baBehav[ADDSET_ROTATE_DEGREE]);
|
||||
resize->setAdjusterBehavior (options.baBehav[ADDSET_RESIZE_SCALE]);
|
||||
framing->setAdjusterBehavior (
|
||||
options.baBehav[ADDSET_FRAMING_RELATIVE_SCALE],
|
||||
options.baBehav[ADDSET_FRAMING_BORDER_RED],
|
||||
options.baBehav[ADDSET_FRAMING_BORDER_GREEN],
|
||||
options.baBehav[ADDSET_FRAMING_BORDER_BLUE]);
|
||||
distortion->setAdjusterBehavior (
|
||||
options.baBehav[ADDSET_DIST_AMOUNT],
|
||||
options.baBehav[ADDSET_DIST_FOCAL_LENGTH]
|
||||
@ -324,6 +330,10 @@ void BatchToolPanelCoordinator::initSession ()
|
||||
if (options.baBehav[ADDSET_DEHAZE_STRENGTH]) { pparams.dehaze.strength = 0; }
|
||||
if (options.baBehav[ADDSET_ROTATE_DEGREE]) { pparams.rotate.degree = 0; }
|
||||
if (options.baBehav[ADDSET_RESIZE_SCALE]) { pparams.resize.scale = 0; }
|
||||
if (options.baBehav[ADDSET_FRAMING_RELATIVE_SCALE]) { pparams.framing.relativeBorderSize = 0; }
|
||||
if (options.baBehav[ADDSET_FRAMING_BORDER_RED]) { pparams.framing.borderRed = 0; }
|
||||
if (options.baBehav[ADDSET_FRAMING_BORDER_GREEN]) { pparams.framing.borderGreen = 0; }
|
||||
if (options.baBehav[ADDSET_FRAMING_BORDER_BLUE]) { pparams.framing.borderBlue = 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; }
|
||||
@ -467,9 +477,13 @@ void BatchToolPanelCoordinator::panelChanged(const rtengine::ProcEvent& event, c
|
||||
crop->write (&pparams, &pparamsEdited);
|
||||
resize->update (pparams.crop.enabled, pparams.crop.w, pparams.crop.h, w, h);
|
||||
resize->write (&pparams, &pparamsEdited);
|
||||
framing->update (w, h);
|
||||
framing->write (&pparams, &pparamsEdited);
|
||||
} else if (event == rtengine::EvCrop) {
|
||||
resize->update (pparams.crop.enabled, pparams.crop.w, pparams.crop.h);
|
||||
resize->write (&pparams, &pparamsEdited);
|
||||
framing->update (w, h);
|
||||
framing->write (&pparams, &pparamsEdited);
|
||||
}
|
||||
} else {
|
||||
// Compensate rotation on flip
|
||||
|
69
rtgui/colorpreview.cc
Normal file
69
rtgui/colorpreview.cc
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.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 <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 2024-2024 Daniel Gao <daniel.gao.work@gmail.com>
|
||||
*/
|
||||
|
||||
#include "colorpreview.h"
|
||||
|
||||
#include "rtscalable.h"
|
||||
|
||||
ColorPreview::ColorPreview() : color_red(1.0), color_green(1.0), color_blue(1.0)
|
||||
{
|
||||
}
|
||||
|
||||
void ColorPreview::setRgb(double r, double g, double b)
|
||||
{
|
||||
color_red = r;
|
||||
color_green = g;
|
||||
color_blue = b;
|
||||
|
||||
queue_draw();
|
||||
}
|
||||
|
||||
bool ColorPreview::on_draw(const Cairo::RefPtr<Cairo::Context>& cr)
|
||||
{
|
||||
cr->set_source_rgb(color_red, color_green, color_blue);
|
||||
cr->paint();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ColorPreview::get_preferred_height_vfunc(int& minimum_height, int& natural_height) const
|
||||
{
|
||||
minimum_height = RTScalable::scalePixelSize(10);
|
||||
natural_height = RTScalable::scalePixelSize(100);
|
||||
}
|
||||
|
||||
void ColorPreview::get_preferred_width_vfunc(int& minimum_width, int& natural_width) const
|
||||
{
|
||||
minimum_width = RTScalable::scalePixelSize(10);
|
||||
natural_width = RTScalable::scalePixelSize(100);
|
||||
}
|
||||
|
||||
void ColorPreview::get_preferred_height_for_width_vfunc(int width, int& minimum_height,
|
||||
int& natural_height) const
|
||||
{
|
||||
get_preferred_height_vfunc(minimum_height, natural_height);
|
||||
}
|
||||
|
||||
void ColorPreview::get_preferred_width_for_height_vfunc(int height, int& minimum_width,
|
||||
int& natural_width) const
|
||||
{
|
||||
get_preferred_width_vfunc(minimum_width, natural_width);
|
||||
}
|
53
rtgui/colorpreview.h
Normal file
53
rtgui/colorpreview.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.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 <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 2024-2024 Daniel Gao <daniel.gao.work@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <gtkmm/drawingarea.h>
|
||||
|
||||
/**
|
||||
* This widget displays a singular color as its contents.
|
||||
*/
|
||||
class ColorPreview : public Gtk::DrawingArea
|
||||
{
|
||||
public:
|
||||
ColorPreview();
|
||||
|
||||
// Values between 0.0 and 1.0 as in
|
||||
// Cairo::Context::set_source_rgb()
|
||||
void setRgb(double r, double g, double b);
|
||||
|
||||
// Gtk::DrawingArea
|
||||
bool on_draw(const Cairo::RefPtr<Cairo::Context>& cr) override;
|
||||
|
||||
// Gtk::Widget
|
||||
void get_preferred_height_vfunc(int& minimum_height, int& natural_height) const override;
|
||||
void get_preferred_width_vfunc(int& minimum_width, int& natural_width) const override;
|
||||
void get_preferred_height_for_width_vfunc(int width, int& minimum_height,
|
||||
int& natural_height) const override;
|
||||
void get_preferred_width_for_height_vfunc(int height, int & minimum_width,
|
||||
int& natural_width) const override;
|
||||
|
||||
private:
|
||||
double color_red;
|
||||
double color_green;
|
||||
double color_blue;
|
||||
};
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include "crop.h"
|
||||
|
||||
#include "aspectratios.h"
|
||||
#include "options.h"
|
||||
#include "rtimage.h"
|
||||
|
||||
@ -57,37 +58,10 @@ public:
|
||||
CropRatios() :
|
||||
ratios{
|
||||
{M("GENERAL_ASIMAGE"), 0.0},
|
||||
{M("GENERAL_CURRENT"), -1.0},
|
||||
{"3:2", 3.0 / 2.0}, // L1.5, P0.666...
|
||||
{"4:3", 4.0 / 3.0}, // L1.333..., P0.75
|
||||
{"16:9", 16.0 / 9.0}, // L1.777..., P0.5625
|
||||
{"16:10", 16.0 / 10.0}, // L1.6, P0.625
|
||||
{"1:1", 1.0 / 1.0}, // L1, P1
|
||||
{"2:1", 2.0 / 1.0}, // L2, P0.5
|
||||
{"3:1", 3.0 / 1.0}, // L3, P0.333...
|
||||
{"4:1", 4.0 / 1.0}, // L4, P0.25
|
||||
{"5:1", 5.0 / 1.0}, // L5, P0.2
|
||||
{"6:1", 6.0 / 1.0}, // L6, P0.1666...
|
||||
{"7:1", 7.0 / 1.0}, // L7, P0.142...
|
||||
{"4:5", 4.0 / 5.0}, // L1.25, P0.8
|
||||
{"5:7", 5.0 / 7.0}, // L1.4, P0.714...
|
||||
{"6:7", 6.0 / 7.0}, // L1.166..., P0.857...
|
||||
{"6:17", 6.0 / 17.0}, // L2.833..., P0.352...
|
||||
{"24:65 - XPAN", 24.0 / 65.0}, // L2.708..., P0.369...
|
||||
{"1.414 - DIN EN ISO 216", 1.414}, // L1.414, P0.707...
|
||||
{"3.5:5", 3.5 / 5.0}, // L1.428..., P0.7
|
||||
{"8.5:11 - US Letter", 8.5 / 11.0}, // L1.294..., P0.772...
|
||||
{"9.5:12", 9.5 / 12.0}, // L1.263..., P0.791...
|
||||
{"10:12", 10.0 / 12.0}, // L1.2, P0.833...
|
||||
{"11:14", 11.0 / 14.0}, // L1.272..., P0.785...
|
||||
{"11:17 - Tabloid", 11.0 / 17.0}, // L1.545..., P0.647...
|
||||
{"13:19", 13.0 / 19.0}, // L1.461..., P0.684...
|
||||
{"17:22", 17.0 / 22.0}, // L1.294..., P0.772...
|
||||
{"45:35 - ePassport", 45.0 / 35.0}, // L1.285,... P0.777...
|
||||
{"64:27", 64.0 / 27.0}, // L2.370..., P0.421...
|
||||
{"13:18", 13.0 / 18.0}, // L1.384..., P0.722...
|
||||
{M("GENERAL_CURRENT"), -1.0}
|
||||
}
|
||||
{
|
||||
fillAspectRatios(ratios);
|
||||
}
|
||||
|
||||
std::vector<Glib::ustring> getLabels() const
|
||||
@ -117,12 +91,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
struct CropRatio {
|
||||
Glib::ustring label;
|
||||
double value;
|
||||
};
|
||||
|
||||
std::vector<CropRatio> ratios;
|
||||
std::vector<AspectRatio> ratios;
|
||||
};
|
||||
|
||||
Crop::Crop():
|
||||
|
1093
rtgui/framing.cc
Normal file
1093
rtgui/framing.cc
Normal file
File diff suppressed because it is too large
Load Diff
179
rtgui/framing.h
Normal file
179
rtgui/framing.h
Normal file
@ -0,0 +1,179 @@
|
||||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.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 <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 2024-2024 Daniel Gao <daniel.gao.work@gmail.com>
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "adjuster.h"
|
||||
#include "guiutils.h"
|
||||
#include "toolpanel.h"
|
||||
|
||||
#include "../rtengine/procevents.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
class ColorPreview;
|
||||
|
||||
class Framing final :
|
||||
public ToolParamBlock,
|
||||
public AdjusterListener,
|
||||
public FoldableToolPanel
|
||||
{
|
||||
public:
|
||||
static const Glib::ustring TOOL_NAME;
|
||||
|
||||
Framing();
|
||||
~Framing();
|
||||
|
||||
// FoldableToolPanel
|
||||
void read(const rtengine::procparams::ProcParams* pp,
|
||||
const ParamsEdited* pedited = nullptr) override;
|
||||
void write(rtengine::procparams::ProcParams* pp,
|
||||
ParamsEdited* pedited = nullptr) override;
|
||||
void setDefaults(const rtengine::procparams::ProcParams* defParams,
|
||||
const ParamsEdited* pedited = nullptr) override;
|
||||
void trimValues(rtengine::procparams::ProcParams* pp) override;
|
||||
void setBatchMode(bool batchMode) override;
|
||||
void enabledChanged() override;
|
||||
|
||||
void update(int originalWidth = 0, int originalHeight = 0);
|
||||
void setAdjusterBehavior(bool addRelativeBorderSize, bool addRed, bool addGreen, bool addBlue);
|
||||
|
||||
// AdjusterListener
|
||||
void adjusterChanged(Adjuster* adj, double newVal) override;
|
||||
|
||||
// Signal connections
|
||||
void onFramingMethodChanged();
|
||||
void onAspectRatioChanged();
|
||||
void onOrientationChanged();
|
||||
void onWidthChanged();
|
||||
void onHeightChanged();
|
||||
void onAllowUpscalingToggled();
|
||||
void onBorderSizeMethodChanged();
|
||||
void onBasisChanged();
|
||||
void onMinSizeToggled();
|
||||
void onMinWidthChanged();
|
||||
void onMinHeightChanged();
|
||||
void onAbsWidthChanged();
|
||||
void onAbsHeightChanged();
|
||||
|
||||
private:
|
||||
class AspectRatios;
|
||||
|
||||
// Helper struct for repeated patterns
|
||||
struct DimensionGui
|
||||
{
|
||||
using CallbackFunc = void(Framing::*)();
|
||||
|
||||
DimensionGui() = default;
|
||||
DimensionGui(Gtk::Box* parent, const char* text);
|
||||
|
||||
void setValue(int newValue) { value->set_value(newValue); }
|
||||
void setRange(int min, int max) { value->set_range(min, max); }
|
||||
void connect(Framing& framing, CallbackFunc callback);
|
||||
|
||||
void show() { box->show(); }
|
||||
void hide() { box->hide(); }
|
||||
|
||||
Gtk::Box* box;
|
||||
MySpinButton* value;
|
||||
sigc::connection connection;
|
||||
bool isDirty;
|
||||
};
|
||||
|
||||
void setupEvents();
|
||||
void setupFramingMethodGui();
|
||||
void setupBorderSizeGui();
|
||||
void setupBorderColorsGui();
|
||||
|
||||
void readParams(const rtengine::procparams::ProcParams* pp);
|
||||
void readEdited(const ParamsEdited* pedited);
|
||||
void writeParams(rtengine::procparams::ProcParams* pp);
|
||||
void writeEdited(ParamsEdited* pedited);
|
||||
|
||||
void setDimensions();
|
||||
void updateFramingMethodGui();
|
||||
void updateBorderSizeGui();
|
||||
void updateBorderColorGui();
|
||||
|
||||
// Framing method
|
||||
MyComboBoxText* framingMethod;
|
||||
sigc::connection framingMethodChanged;
|
||||
Gtk::Label* aspectRatioLabel;
|
||||
MyComboBoxText* aspectRatio;
|
||||
sigc::connection aspectRatioChanged;
|
||||
Gtk::Label* orientationLabel;
|
||||
MyComboBoxText* orientation;
|
||||
sigc::connection orientationChanged;
|
||||
DimensionGui width;
|
||||
DimensionGui height;
|
||||
Gtk::CheckButton* allowUpscaling;
|
||||
sigc::connection allowUpscalingConnection;
|
||||
|
||||
// Border sizing
|
||||
MyComboBoxText* borderSizeMethod;
|
||||
sigc::connection borderSizeMethodChanged;
|
||||
Gtk::Label* basisLabel;
|
||||
MyComboBoxText* basis;
|
||||
sigc::connection basisChanged;
|
||||
Adjuster* relativeBorderSize;
|
||||
Gtk::Frame* minSizeFrame;
|
||||
Gtk::Box* minSizeFrameContent;
|
||||
Gtk::CheckButton* minSizeEnabled;
|
||||
sigc::connection minSizeEnabledConnection;
|
||||
DimensionGui minWidth;
|
||||
DimensionGui minHeight;
|
||||
DimensionGui absWidth;
|
||||
DimensionGui absHeight;
|
||||
|
||||
// Border colors
|
||||
Adjuster* redAdj;
|
||||
Adjuster* greenAdj;
|
||||
Adjuster* blueAdj;
|
||||
ColorPreview* colorPreview;
|
||||
|
||||
// Events
|
||||
rtengine::ProcEvent EvFramingEnabled;
|
||||
rtengine::ProcEvent EvFramingMethod;
|
||||
rtengine::ProcEvent EvFramingAspectRatio;
|
||||
rtengine::ProcEvent EvFramingOrientation;
|
||||
rtengine::ProcEvent EvFramingFramedWidth;
|
||||
rtengine::ProcEvent EvFramingFramedHeight;
|
||||
rtengine::ProcEvent EvFramingAllowUpscaling;
|
||||
rtengine::ProcEvent EvFramingBorderSizingMethod;
|
||||
rtengine::ProcEvent EvFramingBasis;
|
||||
rtengine::ProcEvent EvFramingRelativeBorderSize;
|
||||
rtengine::ProcEvent EvFramingMinSizeEnabled;
|
||||
rtengine::ProcEvent EvFramingMinWidth;
|
||||
rtengine::ProcEvent EvFramingMinHeight;
|
||||
rtengine::ProcEvent EvFramingAbsWidth;
|
||||
rtengine::ProcEvent EvFramingAbsHeight;
|
||||
rtengine::ProcEvent EvFramingBorderRed;
|
||||
rtengine::ProcEvent EvFramingBorderGreen;
|
||||
rtengine::ProcEvent EvFramingBorderBlue;
|
||||
|
||||
IdleRegister idleRegister;
|
||||
std::unique_ptr<AspectRatios> aspectRatioData;
|
||||
|
||||
int imgWidth;
|
||||
int imgHeight;
|
||||
bool lastAllowUpscaling;
|
||||
bool lastMinSizeEnabled;
|
||||
};
|
@ -25,6 +25,8 @@
|
||||
#include "rtimage.h"
|
||||
#include "rtscalable.h"
|
||||
#include "multilangmgr.h"
|
||||
#include "adjuster.h"
|
||||
#include "toolpanel.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
@ -77,6 +79,34 @@ void IdleRegister::destroy()
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
BlockAdjusterEvents::BlockAdjusterEvents(Adjuster* adjuster) : adj(adjuster)
|
||||
{
|
||||
if (adj) {
|
||||
adj->block(true);
|
||||
}
|
||||
}
|
||||
|
||||
BlockAdjusterEvents::~BlockAdjusterEvents()
|
||||
{
|
||||
if (adj) {
|
||||
adj->block(false);
|
||||
}
|
||||
}
|
||||
|
||||
DisableListener::DisableListener(ToolPanel* panelToDisable) : panel(panelToDisable)
|
||||
{
|
||||
if (panel) {
|
||||
panel->disableListener();
|
||||
}
|
||||
}
|
||||
|
||||
DisableListener::~DisableListener()
|
||||
{
|
||||
if (panel) {
|
||||
panel->enableListener();
|
||||
}
|
||||
}
|
||||
|
||||
Glib::ustring escapeHtmlChars(const Glib::ustring &src)
|
||||
{
|
||||
|
||||
|
@ -45,7 +45,9 @@ struct CropParams;
|
||||
|
||||
}
|
||||
|
||||
class Adjuster;
|
||||
class RTImage;
|
||||
class ToolPanel;
|
||||
|
||||
Glib::ustring escapeHtmlChars(const Glib::ustring &src);
|
||||
bool removeIfThere (Gtk::Container* cont, Gtk::Widget* w, bool increference = true);
|
||||
@ -161,6 +163,26 @@ private:
|
||||
bool wasBlocked;
|
||||
};
|
||||
|
||||
class BlockAdjusterEvents
|
||||
{
|
||||
public:
|
||||
explicit BlockAdjusterEvents(Adjuster* adjuster);
|
||||
~BlockAdjusterEvents();
|
||||
|
||||
private:
|
||||
Adjuster* adj;
|
||||
};
|
||||
|
||||
class DisableListener
|
||||
{
|
||||
public:
|
||||
explicit DisableListener(ToolPanel* panelToDisable);
|
||||
~DisableListener();
|
||||
|
||||
private:
|
||||
ToolPanel* panel;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Glue box to control visibility of the MyExpender's content ; also handle the frame around it
|
||||
*/
|
||||
|
@ -25,6 +25,134 @@
|
||||
|
||||
#include "../rtengine/procparams.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
using namespace rtengine::procparams;
|
||||
|
||||
void setAll(FramingParamsEdited& framing, bool v)
|
||||
{
|
||||
framing.enabled = v;
|
||||
framing.framingMethod = v;
|
||||
framing.aspectRatio = v;
|
||||
framing.orientation = v;
|
||||
framing.framedWidth = v;
|
||||
framing.framedHeight = v;
|
||||
framing.allowUpscaling = v;
|
||||
|
||||
framing.borderSizingMethod = v;
|
||||
framing.basis = v;
|
||||
framing.relativeBorderSize = v;
|
||||
framing.minSizeEnabled = v;
|
||||
framing.minWidth = v;
|
||||
framing.minHeight = v;
|
||||
framing.absWidth = v;
|
||||
framing.absHeight = v;
|
||||
|
||||
framing.borderRed = v;
|
||||
framing.borderGreen = v;
|
||||
framing.borderBlue = v;
|
||||
}
|
||||
|
||||
void initFrom(FramingParamsEdited& edits, const ProcParams& params, const ProcParams& otherParams)
|
||||
{
|
||||
const FramingParams& curr = params.framing;
|
||||
const FramingParams& other = otherParams.framing;
|
||||
|
||||
edits.enabled &= curr.enabled == other.enabled;
|
||||
edits.framingMethod &= curr.framingMethod == other.framingMethod;
|
||||
edits.aspectRatio &= curr.aspectRatio == other.aspectRatio;
|
||||
edits.orientation &= curr.orientation == other.orientation;
|
||||
edits.framedWidth &= curr.framedWidth == other.framedWidth;
|
||||
edits.framedHeight &= curr.framedHeight == other.framedHeight;
|
||||
edits.allowUpscaling &= curr.allowUpscaling == other.allowUpscaling;
|
||||
|
||||
edits.borderSizingMethod &= curr.borderSizingMethod == other.borderSizingMethod;
|
||||
edits.basis &= curr.basis == other.basis;
|
||||
edits.relativeBorderSize &= curr.relativeBorderSize == other.relativeBorderSize;
|
||||
edits.minSizeEnabled &= curr.minSizeEnabled == other.minSizeEnabled;
|
||||
edits.minWidth &= curr.minWidth == other.minWidth;
|
||||
edits.minHeight &= curr.minHeight == other.minHeight;
|
||||
edits.absWidth &= curr.absWidth == other.absWidth;
|
||||
edits.absHeight &= curr.absHeight == other.absHeight;
|
||||
|
||||
edits.borderRed &= curr.borderRed == other.borderRed;
|
||||
edits.borderGreen &= curr.borderGreen == other.borderGreen;
|
||||
edits.borderBlue &= curr.borderBlue == other.borderBlue;
|
||||
}
|
||||
|
||||
void combine(FramingParams& toEdit, const FramingParams& mod, const FramingParamsEdited& edits,
|
||||
bool dontForceSet)
|
||||
{
|
||||
if (edits.enabled) {
|
||||
toEdit.enabled = mod.enabled;
|
||||
}
|
||||
if (edits.framingMethod) {
|
||||
toEdit.framingMethod = mod.framingMethod;
|
||||
}
|
||||
if (edits.aspectRatio) {
|
||||
toEdit.aspectRatio = mod.aspectRatio;
|
||||
}
|
||||
if (edits.orientation) {
|
||||
toEdit.orientation = mod.orientation;
|
||||
}
|
||||
if (edits.framedWidth) {
|
||||
toEdit.framedWidth = mod.framedWidth;
|
||||
}
|
||||
if (edits.framedHeight) {
|
||||
toEdit.framedHeight = mod.framedHeight;
|
||||
}
|
||||
if (edits.allowUpscaling) {
|
||||
toEdit.allowUpscaling = mod.allowUpscaling;
|
||||
}
|
||||
|
||||
if (edits.borderSizingMethod) {
|
||||
toEdit.borderSizingMethod = mod.borderSizingMethod;
|
||||
}
|
||||
if (edits.basis) {
|
||||
toEdit.basis = mod.basis;
|
||||
}
|
||||
if (edits.relativeBorderSize) {
|
||||
toEdit.relativeBorderSize =
|
||||
dontForceSet && options.baBehav[ADDSET_FRAMING_RELATIVE_SCALE] ?
|
||||
toEdit.relativeBorderSize + mod.relativeBorderSize :
|
||||
mod.relativeBorderSize;
|
||||
}
|
||||
if (edits.minSizeEnabled) {
|
||||
toEdit.minSizeEnabled = mod.minSizeEnabled;
|
||||
}
|
||||
if (edits.minWidth) {
|
||||
toEdit.minWidth = mod.minWidth;
|
||||
}
|
||||
if (edits.minHeight) {
|
||||
toEdit.minHeight = mod.minHeight;
|
||||
}
|
||||
if (edits.absWidth) {
|
||||
toEdit.absWidth = mod.absWidth;
|
||||
}
|
||||
if (edits.absHeight) {
|
||||
toEdit.absHeight = mod.absHeight;
|
||||
}
|
||||
|
||||
if (edits.borderRed) {
|
||||
toEdit.borderRed = dontForceSet && options.baBehav[ADDSET_FRAMING_BORDER_RED] ?
|
||||
toEdit.borderRed + mod.borderRed :
|
||||
mod.borderRed;
|
||||
}
|
||||
if (edits.borderGreen) {
|
||||
toEdit.borderGreen = dontForceSet && options.baBehav[ADDSET_FRAMING_BORDER_GREEN] ?
|
||||
toEdit.borderGreen + mod.borderGreen :
|
||||
mod.borderGreen;
|
||||
}
|
||||
if (edits.borderBlue) {
|
||||
toEdit.borderBlue = dontForceSet && options.baBehav[ADDSET_FRAMING_BORDER_BLUE] ?
|
||||
toEdit.borderBlue + mod.borderBlue :
|
||||
mod.borderBlue;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ParamsEdited::ParamsEdited(bool value)
|
||||
{
|
||||
|
||||
@ -446,7 +574,6 @@ void ParamsEdited::set(bool v)
|
||||
blackwhite.autoc = v;
|
||||
blackwhite.algo = v;
|
||||
|
||||
|
||||
resize.scale = v;
|
||||
resize.appliesTo = v;
|
||||
resize.method = v;
|
||||
@ -456,11 +583,13 @@ void ParamsEdited::set(bool v)
|
||||
resize.longedge = v;
|
||||
resize.shortedge = v;
|
||||
resize.enabled = v;
|
||||
resize.allowUpscaling = v;
|
||||
|
||||
::setAll(framing, v);
|
||||
|
||||
spot.enabled = v;
|
||||
spot.entries = v;
|
||||
|
||||
resize.allowUpscaling = v;
|
||||
icm.inputProfile = v;
|
||||
icm.toneCurve = v;
|
||||
icm.applyLookTable = v;
|
||||
@ -1984,9 +2113,12 @@ void ParamsEdited::initFrom(const std::vector<rtengine::procparams::ProcParams>&
|
||||
resize.longedge = resize.longedge && p.resize.longedge == other.resize.longedge;
|
||||
resize.shortedge = resize.shortedge && p.resize.shortedge == other.resize.shortedge;
|
||||
resize.enabled = resize.enabled && p.resize.enabled == other.resize.enabled;
|
||||
resize.allowUpscaling = resize.allowUpscaling && p.resize.allowUpscaling == other.resize.allowUpscaling;
|
||||
|
||||
::initFrom(framing, p, other);
|
||||
|
||||
spot.enabled = spot.enabled && p.spot.enabled == other.spot.enabled;
|
||||
spot.entries = spot.entries && p.spot.entries == other.spot.entries;
|
||||
resize.allowUpscaling = resize.allowUpscaling && p.resize.allowUpscaling == other.resize.allowUpscaling;
|
||||
icm.inputProfile = icm.inputProfile && p.icm.inputProfile == other.icm.inputProfile;
|
||||
icm.toneCurve = icm.toneCurve && p.icm.toneCurve == other.icm.toneCurve;
|
||||
icm.applyLookTable = icm.applyLookTable && p.icm.applyLookTable == other.icm.applyLookTable;
|
||||
@ -6856,6 +6988,8 @@ void ParamsEdited::combine(rtengine::procparams::ProcParams& toEdit, const rteng
|
||||
toEdit.resize.allowUpscaling = mods.resize.allowUpscaling;
|
||||
}
|
||||
|
||||
::combine(toEdit.framing, mods.framing, framing, dontforceSet);
|
||||
|
||||
if (icm.inputProfile) {
|
||||
toEdit.icm.inputProfile = mods.icm.inputProfile;
|
||||
}
|
||||
|
@ -1307,6 +1307,29 @@ struct ResizeParamsEdited {
|
||||
bool allowUpscaling;
|
||||
};
|
||||
|
||||
struct FramingParamsEdited {
|
||||
bool enabled;
|
||||
bool framingMethod;
|
||||
bool aspectRatio;
|
||||
bool orientation;
|
||||
bool framedWidth;
|
||||
bool framedHeight;
|
||||
bool allowUpscaling;
|
||||
|
||||
bool borderSizingMethod;
|
||||
bool basis;
|
||||
bool relativeBorderSize;
|
||||
bool minSizeEnabled;
|
||||
bool minWidth;
|
||||
bool minHeight;
|
||||
bool absWidth;
|
||||
bool absHeight;
|
||||
|
||||
bool borderRed;
|
||||
bool borderGreen;
|
||||
bool borderBlue;
|
||||
};
|
||||
|
||||
class SpotParamsEdited
|
||||
{
|
||||
public:
|
||||
@ -1682,6 +1705,7 @@ struct ParamsEdited {
|
||||
ChannelMixerParamsEdited chmixer;
|
||||
BlackWhiteParamsEdited blackwhite;
|
||||
ResizeParamsEdited resize;
|
||||
FramingParamsEdited framing;
|
||||
SpotParamsEdited spot;
|
||||
ColorManagementParamsEdited icm;
|
||||
RAWParamsEdited raw;
|
||||
|
@ -266,6 +266,7 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren
|
||||
crop = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_CROP")));
|
||||
resize = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_RESIZE")));
|
||||
prsharpening = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_PRSHARPENING")));
|
||||
framing = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_FRAMING")));
|
||||
perspective = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_PERSPECTIVE")));
|
||||
commonTrans = Gtk::manage (new Gtk::CheckButton (M("PARTIALPASTE_COMMONTRANSFORMPARAMS")));
|
||||
|
||||
@ -384,6 +385,7 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren
|
||||
vboxes[4]->pack_start (*crop, Gtk::PACK_SHRINK, 2);
|
||||
vboxes[4]->pack_start (*resize, Gtk::PACK_SHRINK, 2);
|
||||
vboxes[4]->pack_start (*prsharpening, Gtk::PACK_SHRINK, 2);
|
||||
vboxes[4]->pack_start (*framing, Gtk::PACK_SHRINK, 2);
|
||||
vboxes[4]->pack_start (*perspective, Gtk::PACK_SHRINK, 2);
|
||||
vboxes[4]->pack_start (*commonTrans, Gtk::PACK_SHRINK, 2);
|
||||
|
||||
@ -547,6 +549,7 @@ PartialPasteDlg::PartialPasteDlg (const Glib::ustring &title, Gtk::Window* paren
|
||||
cropConn = crop->signal_toggled().connect (sigc::bind (sigc::mem_fun(*composition, &Gtk::CheckButton::set_inconsistent), true));
|
||||
resizeConn = resize->signal_toggled().connect (sigc::bind (sigc::mem_fun(*composition, &Gtk::CheckButton::set_inconsistent), true));
|
||||
prsharpeningConn = prsharpening->signal_toggled().connect (sigc::bind (sigc::mem_fun(*composition, &Gtk::CheckButton::set_inconsistent), true));
|
||||
framingConn = framing->signal_toggled().connect (sigc::bind (sigc::mem_fun(*composition, &Gtk::CheckButton::set_inconsistent), true));
|
||||
perspectiveConn = perspective->signal_toggled().connect (sigc::bind (sigc::mem_fun(*composition, &Gtk::CheckButton::set_inconsistent), true));
|
||||
commonTransConn = commonTrans->signal_toggled().connect (sigc::bind (sigc::mem_fun(*composition, &Gtk::CheckButton::set_inconsistent), true));
|
||||
|
||||
@ -823,6 +826,7 @@ void PartialPasteDlg::compositionToggled ()
|
||||
ConnectionBlocker cropBlocker(cropConn);
|
||||
ConnectionBlocker resizeBlocker(resizeConn);
|
||||
ConnectionBlocker prsharpeningBlocker(prsharpeningConn);
|
||||
ConnectionBlocker framingBlocker(framingConn);
|
||||
ConnectionBlocker perspectiveBlocker(perspectiveConn);
|
||||
ConnectionBlocker commonTransBlocker(commonTransConn);
|
||||
|
||||
@ -833,6 +837,7 @@ void PartialPasteDlg::compositionToggled ()
|
||||
crop->set_active (composition->get_active ());
|
||||
resize->set_active (composition->get_active ());
|
||||
prsharpening->set_active (composition->get_active ());
|
||||
framing->set_active (composition->get_active ());
|
||||
perspective->set_active (composition->get_active ());
|
||||
commonTrans->set_active (composition->get_active ());
|
||||
}
|
||||
@ -1043,6 +1048,10 @@ void PartialPasteDlg::applyPaste (rtengine::procparams::ProcParams* dstPP, Param
|
||||
filterPE.prsharpening = falsePE.prsharpening;
|
||||
}
|
||||
|
||||
if (!framing->get_active ()) {
|
||||
filterPE.framing = falsePE.framing;
|
||||
}
|
||||
|
||||
if (!perspective->get_active ()) {
|
||||
filterPE.perspective = falsePE.perspective;
|
||||
}
|
||||
|
@ -180,6 +180,7 @@ public:
|
||||
Gtk::CheckButton* crop;
|
||||
Gtk::CheckButton* resize;
|
||||
Gtk::CheckButton* prsharpening;
|
||||
Gtk::CheckButton* framing;
|
||||
Gtk::CheckButton* perspective;
|
||||
Gtk::CheckButton* commonTrans;
|
||||
|
||||
@ -231,7 +232,7 @@ public:
|
||||
sigc::connection spotConn, sharpenConn, gradsharpenConn, microcontrastConn, impdenConn, dirpyrdenConn, defringeConn, epdConn, fattalConn, dirpyreqConn, waveletConn, retinexConn, dehazeConn;
|
||||
sigc::connection vibranceConn, chmixerConn, hsveqConn, rgbcurvesConn, chmixerbwConn, colortoningConn, filmSimulationConn, softlightConn;
|
||||
sigc::connection distortionConn, cacorrConn, vignettingConn, lcpConn;
|
||||
sigc::connection coarserotConn, finerotConn, cropConn, resizeConn, prsharpeningConn, perspectiveConn, commonTransConn;
|
||||
sigc::connection coarserotConn, finerotConn, cropConn, resizeConn, prsharpeningConn, framingConn, perspectiveConn, commonTransConn;
|
||||
sigc::connection metadataConn, exifchConn, iptcConn, icmConn;
|
||||
sigc::connection df_fileConn, df_AutoSelectConn, ff_fileConn, ff_AutoSelectConn, ff_FromMetaDataConn, ff_BlurRadiusConn, ff_BlurTypeConn, ff_ClipControlConn;
|
||||
sigc::connection raw_caredblueConn, raw_ca_autocorrectConn, raw_ca_avoid_colourshiftconn, raw_hotpix_filtConn, raw_deadpix_filtConn, raw_pdaf_lines_filterConn, raw_linenoiseConn, raw_greenthreshConn, raw_ccStepsConn, raw_methodConn, raw_borderConn, raw_imagenumConn, raw_dcb_iterationsConn, raw_lmmse_iterationsConn, raw_pixelshiftConn, raw_dcb_enhanceConn, raw_exposConn, raw_blackConn;
|
||||
|
@ -364,6 +364,13 @@ Gtk::Widget* Preferences::getBatchProcPanel()
|
||||
mi->set_value(behavColumns.label, M("TP_RESIZE_LABEL"));
|
||||
appendBehavList(mi, M("TP_RESIZE_SCALE"), ADDSET_RESIZE_SCALE, true);
|
||||
|
||||
mi = behModel->append();
|
||||
mi->set_value(behavColumns.label, M("TP_FRAMING_LABEL"));
|
||||
appendBehavList(mi, M("TP_FRAMING_BORDER_SIZE"), ADDSET_FRAMING_RELATIVE_SCALE, false);
|
||||
appendBehavList(mi, M("TP_FRAMING_RED"), ADDSET_FRAMING_BORDER_RED, false);
|
||||
appendBehavList(mi, M("TP_FRAMING_GREEN"), ADDSET_FRAMING_BORDER_GREEN, false);
|
||||
appendBehavList(mi, M("TP_FRAMING_BLUE"), ADDSET_FRAMING_BORDER_BLUE, false);
|
||||
|
||||
mi = behModel->append();
|
||||
mi->set_value(behavColumns.label, M("TP_LENSGEOM_SCALE"));
|
||||
appendBehavList(mi, M("TP_LENSGEOM_SCALE"), ADDSET_LENSGEOM_SCALE, true);
|
||||
|
@ -35,7 +35,7 @@ PrSharpening::PrSharpening () : FoldableToolPanel(this, TOOL_NAME, M("TP_PRSHARP
|
||||
milestones.push_back( GradientMilestone(0.0, 0.0, 0.0, 0.0) );
|
||||
milestones.push_back( GradientMilestone(1.0, 1.0, 1.0, 1.0) );
|
||||
|
||||
//setEnabledTooltipMarkup(M("TP_PRSHARPENING_TOOLTIP"));
|
||||
setEnabledTooltipMarkup(M("TP_PRSHARPENING_TOOLTIP"));
|
||||
|
||||
Gtk::Box* hb = Gtk::manage (new Gtk::Box ());
|
||||
hb->show ();
|
||||
|
@ -146,22 +146,22 @@ Resize::Resize () : FoldableToolPanel(this, TOOL_NAME, M("TP_RESIZE_LABEL"), fal
|
||||
|
||||
w->set_digits (0);
|
||||
w->set_increments (1, 100);
|
||||
w->set_range (32, MAX_SCALE * maxw);
|
||||
w->set_range (MIN_SIZE, MAX_SCALE * maxw);
|
||||
w->set_value (800); // Doesn't seem to have any effect (overwritten in Resize::read)
|
||||
|
||||
h->set_digits (0);
|
||||
h->set_increments (1, 100);
|
||||
h->set_range (32, MAX_SCALE * maxh);
|
||||
h->set_range (MIN_SIZE, MAX_SCALE * maxh);
|
||||
h->set_value (600); // Doesn't seem to have any effect (overwritten in Resize::read)
|
||||
|
||||
le->set_digits (0);
|
||||
le->set_increments (1, 100);
|
||||
le->set_range (32, MAX_SCALE * maxw);
|
||||
le->set_range (MIN_SIZE, MAX_SCALE * maxw);
|
||||
le->set_value (900);
|
||||
|
||||
se->set_digits (0);
|
||||
se->set_increments (1, 100);
|
||||
se->set_range (32, MAX_SCALE * maxh);
|
||||
se->set_range (MIN_SIZE, MAX_SCALE * maxh);
|
||||
se->set_value (900);
|
||||
|
||||
wconn = w->signal_value_changed().connect ( sigc::mem_fun(*this, &Resize::entryWChanged), true);
|
||||
@ -173,7 +173,6 @@ Resize::Resize () : FoldableToolPanel(this, TOOL_NAME, M("TP_RESIZE_LABEL"), fal
|
||||
sconn = spec->signal_changed().connect ( sigc::mem_fun(*this, &Resize::specChanged) );
|
||||
|
||||
getSubToolsContainer()->hide();
|
||||
getSubToolsContainer()->set_tooltip_markup (M("TP_PRSHARPENING_TOOLTIP"));
|
||||
|
||||
show_all();
|
||||
}
|
||||
|
@ -22,7 +22,6 @@
|
||||
|
||||
#include "adjuster.h"
|
||||
#include "guiutils.h"
|
||||
#include "guiutils.h"
|
||||
#include "toolpanel.h"
|
||||
|
||||
class Resize final :
|
||||
@ -33,6 +32,8 @@ class Resize final :
|
||||
{
|
||||
public:
|
||||
static const Glib::ustring TOOL_NAME;
|
||||
static constexpr int MAX_SCALE = 16; // 16 to match the main preview max scale of 1600%
|
||||
static constexpr int MIN_SIZE = 32;
|
||||
|
||||
Resize ();
|
||||
~Resize () override;
|
||||
@ -85,6 +86,4 @@ private:
|
||||
sigc::connection sconn, aconn, wconn, hconn, leconn, seconn;
|
||||
bool wDirty, hDirty, leDirty, seDirty;
|
||||
IdleRegister idle_register;
|
||||
|
||||
static constexpr int MAX_SCALE = 16; // 16 to match the main preview max scale of 1600%
|
||||
};
|
||||
|
@ -133,6 +133,8 @@ Glib::ustring getToolTitleKey(Tool tool)
|
||||
return "TP_RESIZE_LABEL";
|
||||
case Tool::PR_SHARPENING:
|
||||
return "TP_PRSHARPENING_LABEL";
|
||||
case Tool::FRAMING:
|
||||
return "TP_FRAMING_LABEL";
|
||||
case Tool::CROP_TOOL:
|
||||
return "TP_CROP_LABEL";
|
||||
case Tool::ICM:
|
||||
|
@ -164,6 +164,9 @@ const std::vector<ToolTree> TRANSFORM_PANEL_TOOLS = {
|
||||
{
|
||||
.id = Tool::PR_SHARPENING,
|
||||
},
|
||||
{
|
||||
.id = Tool::FRAMING,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -324,6 +327,7 @@ ToolPanelCoordinator::ToolPanelCoordinator (bool batch) : ipc (nullptr), favorit
|
||||
blackwhite = Gtk::manage(new BlackWhite());
|
||||
resize = Gtk::manage(new Resize());
|
||||
prsharpening = Gtk::manage(new PrSharpening());
|
||||
framing = Gtk::manage(new Framing());
|
||||
crop = Gtk::manage(new Crop());
|
||||
icm = Gtk::manage(new ICMPanel());
|
||||
metadata = Gtk::manage(new MetaDataPanel());
|
||||
@ -638,6 +642,8 @@ std::string ToolPanelCoordinator::getToolName(Tool tool)
|
||||
return Resize::TOOL_NAME;
|
||||
case Tool::PR_SHARPENING:
|
||||
return PrSharpening::TOOL_NAME;
|
||||
case Tool::FRAMING:
|
||||
return Framing::TOOL_NAME;
|
||||
case Tool::CROP_TOOL:
|
||||
return Crop::TOOL_NAME;
|
||||
case Tool::ICM:
|
||||
@ -1117,9 +1123,13 @@ void ToolPanelCoordinator::panelChanged(const rtengine::ProcEvent& event, const
|
||||
crop->write(params);
|
||||
resize->update(params->crop.enabled, params->crop.w, params->crop.h, ipc->getFullWidth(), ipc->getFullHeight());
|
||||
resize->write(params);
|
||||
framing->update(ipc->getFullWidth(), ipc->getFullHeight());
|
||||
framing->write(params);
|
||||
} else if (event == rtengine::EvCrop) {
|
||||
resize->update(params->crop.enabled, params->crop.w, params->crop.h);
|
||||
resize->write(params);
|
||||
framing->update(ipc->getFullWidth(), ipc->getFullHeight());
|
||||
framing->write(params);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2001,6 +2011,8 @@ FoldableToolPanel *ToolPanelCoordinator::getFoldableToolPanel(Tool tool) const
|
||||
return resize;
|
||||
case Tool::PR_SHARPENING:
|
||||
return prsharpening;
|
||||
case Tool::FRAMING:
|
||||
return framing;
|
||||
case Tool::CROP_TOOL:
|
||||
return crop;
|
||||
case Tool::ICM:
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "filmnegative.h"
|
||||
#include "filmsimulation.h"
|
||||
#include "flatfield.h"
|
||||
#include "framing.h"
|
||||
#include "gradient.h"
|
||||
#include "guiutils.h"
|
||||
#include "hsvequalizer.h"
|
||||
@ -131,6 +132,7 @@ protected:
|
||||
ChMixer* chmixer;
|
||||
BlackWhite* blackwhite;
|
||||
Resize* resize;
|
||||
Framing* framing;
|
||||
PrSharpening* prsharpening;
|
||||
ICMPanel* icm;
|
||||
Crop* crop;
|
||||
@ -282,6 +284,7 @@ public:
|
||||
BLACK_WHITE,
|
||||
RESIZE_TOOL,
|
||||
PR_SHARPENING,
|
||||
FRAMING,
|
||||
CROP_TOOL,
|
||||
ICM,
|
||||
WAVELET,
|
||||
|
Loading…
x
Reference in New Issue
Block a user