Blur and noise adjustment layers, Image Trim, Inner Glow (12.8c)

This commit is contained in:
雷电芽衣 committed 2026-09-28 08:35:59 -04:00
1 parent 7ae263de80
commit 31e2dd3864
60 files changed
+1673 -105

No files matched your search

+105 -2
View File
@@ -13,6 +13,9 @@ QString rawValue(AdjustmentKind kind)
case AdjustmentKind::exposure: return QStringLiteral("Exposure");
case AdjustmentKind::gradientMap: return QStringLiteral("Gradient Map");
case AdjustmentKind::grain: return QStringLiteral("Grain");
case AdjustmentKind::addNoise: return QStringLiteral("Add Noise");
case AdjustmentKind::gaussianBlur: return QStringLiteral("Gaussian Blur");
case AdjustmentKind::motionBlur: return QStringLiteral("Motion Blur");
case AdjustmentKind::invert: return QStringLiteral("Invert");
case AdjustmentKind::blackWhite: return QStringLiteral("Black & White");
case AdjustmentKind::colorBalance: return QStringLiteral("Color Balance");
@@ -36,6 +39,9 @@ std::optional<FilterKind> filterKind(AdjustmentKind kind)
case AdjustmentKind::exposure: return FilterKind::exposure;
case AdjustmentKind::gradientMap: return FilterKind::gradientMap;
case AdjustmentKind::grain: return FilterKind::grain;
case AdjustmentKind::addNoise: return FilterKind::addNoise;
case AdjustmentKind::gaussianBlur: return FilterKind::gaussianBlur;
case AdjustmentKind::motionBlur: return FilterKind::motionBlur;
case AdjustmentKind::blackWhite: return FilterKind::blackWhite;
case AdjustmentKind::colorBalance: return FilterKind::colorBalance;
// Panels of their own; Invert has nothing to set.
@@ -106,6 +112,85 @@ void LayerAdjustment::setColorBalance(const ColorBalanceSettings &value)
colorBalanceSettings = value;
}
double LayerAdjustment::gaussianRadius() const
{
return blurRadius.value_or(10);
}
void LayerAdjustment::setGaussianRadius(double value)
{
blurRadius = value;
}
double LayerAdjustment::resolvedMotionAngle() const
{
return motionAngle.value_or(0);
}
void LayerAdjustment::setResolvedMotionAngle(double value)
{
motionAngle = value;
}
double LayerAdjustment::resolvedMotionDistance() const
{
return motionDistance.value_or(10);
}
void LayerAdjustment::setResolvedMotionDistance(double value)
{
motionDistance = value;
}
double LayerAdjustment::resolvedNoiseAmount() const
{
return noiseAmount.value_or(10);
}
void LayerAdjustment::setResolvedNoiseAmount(double value)
{
noiseAmount = value;
}
bool LayerAdjustment::resolvedNoiseGaussian() const
{
return noiseGaussian.value_or(false);
}
void LayerAdjustment::setResolvedNoiseGaussian(bool value)
{
noiseGaussian = value;
}
bool LayerAdjustment::resolvedNoiseMonochromatic() const
{
return noiseMonochromatic.value_or(false);
}
void LayerAdjustment::setResolvedNoiseMonochromatic(bool value)
{
noiseMonochromatic = value;
}
quint32 LayerAdjustment::resolvedNoiseSeed() const
{
return noiseSeed.value_or(0);
}
void LayerAdjustment::setResolvedNoiseSeed(quint32 value)
{
noiseSeed = value;
}
double LayerAdjustment::samplingMargin() const
{
switch (kind) {
case AdjustmentKind::gaussianBlur: return gaussianRadius() * 3 + 2;
case AdjustmentKind::motionBlur: return resolvedMotionDistance() / 2 + 2;
default: return 0;
}
}
// Bounds refuse what is no number: no isFinite terms.
bool LayerAdjustment::isValid() const
{
@@ -130,10 +215,11 @@ bool LayerAdjustment::isValid() const
return false;
}
return curves.isValid() && exposure().isValid() && gradientMap().isValid() && grain().isValid() && blackWhite().isValid()
&& colorBalance().isValid();
&& colorBalance().isValid() && gaussianRadius() >= 0.1 && gaussianRadius() <= 250 && std::abs(resolvedMotionAngle()) <= 90
&& resolvedMotionDistance() >= 1 && resolvedMotionDistance() <= 2000 && resolvedNoiseAmount() >= 0.1 && resolvedNoiseAmount() <= 400;
}
QImage LayerAdjustment::apply(const QImage &image, std::optional<QRectF> region) const
QImage LayerAdjustment::apply(const QImage &image, std::optional<QRectF> region, double scale) const
{
switch (kind) {
case AdjustmentKind::hsv:
@@ -144,6 +230,21 @@ QImage LayerAdjustment::apply(const QImage &image, std::optional<QRectF> region)
case AdjustmentKind::gradientMap: return gradientMap().apply(image);
case AdjustmentKind::blackWhite: return blackWhite().apply(image);
case AdjustmentKind::colorBalance: return colorBalance().apply(image);
case AdjustmentKind::addNoise:
case AdjustmentKind::gaussianBlur:
case AdjustmentKind::motionBlur: {
const FilterSettings settings{.radius = gaussianRadius(),
.angle = resolvedMotionAngle(),
.distance = resolvedMotionDistance(),
.amount = resolvedNoiseAmount(),
.gaussian = resolvedNoiseGaussian(),
.monochromatic = resolvedNoiseMonochromatic()};
FilterJob job{filterKind(kind).value(), image, settings, scale, std::nullopt, QTransform(), resolvedNoiseSeed()};
// Swift's region origin, counted in the image's own pixels.
if (region)
job.noiseOrigin = region->topLeft() * (image.width() / region->width());
return PixelFilter::run(job);
}
case AdjustmentKind::invert: return PixelInvert::run(PixelInvert::Job{image, false, QTransform(), std::nullopt});
case AdjustmentKind::grain: {
// Grain sits in the document, however the image is cut.
@@ -169,6 +270,8 @@ void EditorSession::addAdjustment(AdjustmentKind kind)
grain.seed = QRandomGenerator::global()->generate();
adjustment.setGrain(grain);
}
if (kind == AdjustmentKind::addNoise)
adjustment.setResolvedNoiseSeed(QRandomGenerator::global()->generate());
layer.adjustment = adjustment;
const std::optional<ImageLayer> active = activeLayer();
layer.parentID = active && active->isGroup ? m_activeLayerID : active ? active->parentID : std::nullopt;