Camera Raw panel's remaining groups and the Filter menu entry (12.8b2)
This commit is contained in:
1 parent
bb8129e8d5
commit
7ae263de80
26 files changed
+3227
-82
No files matched your search
@@ -0,0 +1,254 @@
|
||||
#include "UI/CameraRawDetailOpticsControls.h"
|
||||
#include "Rendering/EyedropperIcon.h"
|
||||
#include "UI/CameraRawControls.h"
|
||||
#include <QCheckBox>
|
||||
#include <QGraphicsOpacityEffect>
|
||||
#include <QGuiApplication>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QToolButton>
|
||||
#include <QVBoxLayout>
|
||||
|
||||
namespace {
|
||||
QLabel *text(const QString &words, int pixels, bool secondary)
|
||||
{
|
||||
auto *label = new QLabel(words);
|
||||
QFont font = label->font();
|
||||
font.setPixelSize(pixels);
|
||||
label->setFont(font);
|
||||
label->setWordWrap(true);
|
||||
if (secondary)
|
||||
label->setForegroundRole(QPalette::PlaceholderText);
|
||||
return label;
|
||||
}
|
||||
|
||||
// Swift's `.opacity(0.45).disabled(…)` over a group of rows.
|
||||
QWidget *group(QVBoxLayout *column)
|
||||
{
|
||||
auto *box = new QWidget;
|
||||
auto *rows = new QVBoxLayout(box);
|
||||
rows->setContentsMargins(0, 0, 0, 0);
|
||||
rows->setSpacing(8);
|
||||
box->setGraphicsEffect(new QGraphicsOpacityEffect(box));
|
||||
column->addWidget(box);
|
||||
return box;
|
||||
}
|
||||
|
||||
void dim(QWidget *box, bool active)
|
||||
{
|
||||
box->setEnabled(active);
|
||||
static_cast<QGraphicsOpacityEffect *>(box->graphicsEffect())->setOpacity(active ? 1 : 0.45);
|
||||
}
|
||||
|
||||
void update(EditorSession &session, const std::function<void(CameraRawSettings &)> &change)
|
||||
{
|
||||
FilterSettings settings = session.filterEdit() ? session.filterEdit()->settings : FilterSettings();
|
||||
change(settings.cameraRaw);
|
||||
session.updateFilter(settings, session.filterEdit() ? session.filterEdit()->preview : true);
|
||||
}
|
||||
|
||||
CameraRawSettings raw(const EditorSession &session)
|
||||
{
|
||||
return session.filterEdit() ? session.filterEdit()->settings.cameraRaw : CameraRawSettings();
|
||||
}
|
||||
}
|
||||
|
||||
CameraRawDetailControls::CameraRawDetailControls(EditorSession &session, QWidget *parent) : QWidget(parent), m_session(session)
|
||||
{
|
||||
auto *column = new QVBoxLayout(this);
|
||||
column->setContentsMargins(0, 0, 0, 0);
|
||||
column->setSpacing(8);
|
||||
column->addWidget(text(QStringLiteral("Sharpening"), 11, false));
|
||||
row(column, QStringLiteral("sharpenAmount"), QStringLiteral("Amount"), &CameraRawDetailSettings::sharpenAmount, 150, 0, false,
|
||||
QStringLiteral("Controls how strong the sharpening is."));
|
||||
row(column, QStringLiteral("sharpenRadius"), QStringLiteral("Radius"), &CameraRawDetailSettings::sharpenRadius, 100, 10, false,
|
||||
QStringLiteral("How far from each edge the sharpening reaches, in pixels."));
|
||||
row(column, QStringLiteral("sharpenDetail"), QStringLiteral("Detail"), &CameraRawDetailSettings::sharpenDetail, 100, 25, false,
|
||||
QStringLiteral("Emphasizes fine texture over broader edges."));
|
||||
row(column, QStringLiteral("sharpenMasking"), QStringLiteral("Masking"), &CameraRawDetailSettings::sharpenMasking, 100, 0, true,
|
||||
QStringLiteral("Limits sharpening to stronger edges. Hold Alt to see the mask."));
|
||||
column->addWidget(text(QStringLiteral("Noise Reduction"), 11, false));
|
||||
row(column, QStringLiteral("noiseLuminance"), QStringLiteral("Luminance"), &CameraRawDetailSettings::noiseLuminance, 100, 0, false,
|
||||
QStringLiteral("Smooths grain and noise in brightness."));
|
||||
m_luminanceDetail = group(column);
|
||||
auto *luminance = static_cast<QVBoxLayout *>(m_luminanceDetail->layout());
|
||||
row(luminance, QStringLiteral("noiseLuminanceDetail"), QStringLiteral("Luminance Detail"), &CameraRawDetailSettings::noiseLuminanceDetail, 100, 50,
|
||||
false, QStringLiteral("Preserves fine texture while luminance noise is reduced."));
|
||||
row(luminance, QStringLiteral("noiseLuminanceContrast"), QStringLiteral("Luminance Contrast"), &CameraRawDetailSettings::noiseLuminanceContrast, 100, 0,
|
||||
false, QStringLiteral("Keeps local contrast after luminance smoothing."));
|
||||
row(column, QStringLiteral("noiseColor"), QStringLiteral("Color"), &CameraRawDetailSettings::noiseColor, 100, 0, false,
|
||||
QStringLiteral("Smooths colored speckles."));
|
||||
m_colorDetail = group(column);
|
||||
auto *color = static_cast<QVBoxLayout *>(m_colorDetail->layout());
|
||||
row(color, QStringLiteral("noiseColorDetail"), QStringLiteral("Color Detail"), &CameraRawDetailSettings::noiseColorDetail, 100, 50, false,
|
||||
QStringLiteral("Preserves colored edges while color noise is reduced."));
|
||||
row(color, QStringLiteral("noiseColorSmoothness"), QStringLiteral("Color Smoothness"), &CameraRawDetailSettings::noiseColorSmoothness, 100, 50, false,
|
||||
QStringLiteral("Makes the color smoothing softer or tighter."));
|
||||
connect(&m_session, &EditorSession::changed, this, &CameraRawDetailControls::synchronize);
|
||||
synchronize();
|
||||
}
|
||||
|
||||
void CameraRawDetailControls::row(QVBoxLayout *column, const QString &name, const QString &title, double CameraRawDetailSettings::*key,
|
||||
double high, double reset, bool maskingPreview, const QString &help)
|
||||
{
|
||||
auto *row = new CameraRawRow({.name = name, .title = title, .help = help, .low = 0, .high = high, .titleWidth = CameraRawControls::labelWidth},
|
||||
[this, key] { return raw(m_session).detail.*key; },
|
||||
[this, key, maskingPreview](double value) { assign(key, std::round(value), maskingPreview); },
|
||||
[this, key](double value) { assign(key, value, false); }, [this, key, reset] { assign(key, reset, false); });
|
||||
column->addWidget(row);
|
||||
m_rows.push_back(row);
|
||||
}
|
||||
|
||||
// Swift's assignDetail: the sharpen mask shows while Alt is held.
|
||||
void CameraRawDetailControls::assign(double CameraRawDetailSettings::*key, double value, bool maskingPreview)
|
||||
{
|
||||
if (!m_session.filterEdit())
|
||||
return;
|
||||
CameraRawPanel panel = m_session.filterEdit()->rawPanel;
|
||||
panel.sharpenMask = maskingPreview && QGuiApplication::keyboardModifiers().testFlag(Qt::AltModifier);
|
||||
m_session.setCameraRawPanel(panel);
|
||||
::update(m_session, [key, value](CameraRawSettings &settings) { settings.detail.*key = value; });
|
||||
}
|
||||
|
||||
void CameraRawDetailControls::synchronize()
|
||||
{
|
||||
const CameraRawDetailSettings detail = raw(m_session).detail;
|
||||
dim(m_luminanceDetail, detail.noiseLuminance > 0);
|
||||
dim(m_colorDetail, detail.noiseColor > 0);
|
||||
for (CameraRawRow *row : m_rows)
|
||||
row->synchronize();
|
||||
}
|
||||
|
||||
CameraRawOpticsControls::CameraRawOpticsControls(EditorSession &session, QWidget *parent) : QWidget(parent), m_session(session)
|
||||
{
|
||||
auto *column = new QVBoxLayout(this);
|
||||
column->setContentsMargins(0, 0, 0, 0);
|
||||
column->setSpacing(8);
|
||||
const auto toggle = [this, column](const QString &name, const QString &title, const QString &help, bool CameraRawOpticsSettings::*key) {
|
||||
auto *box = new QCheckBox(title, this);
|
||||
box->setObjectName(name);
|
||||
box->setToolTip(help);
|
||||
connect(box, &QCheckBox::clicked, this, [this, key](bool on) { update([key, on](CameraRawOpticsSettings &optics) { optics.*key = on; }); });
|
||||
column->addWidget(box);
|
||||
return box;
|
||||
};
|
||||
m_chromatic = toggle(QStringLiteral("removeChromaticAberration"), QStringLiteral("Remove Chromatic Aberration"),
|
||||
QStringLiteral("Pulls red and blue fringes apart toward the center to reduce color edging."),
|
||||
&CameraRawOpticsSettings::removeChromaticAberration);
|
||||
m_profile = toggle(QStringLiteral("enableLensProfile"), QStringLiteral("Enable Lens Profile Corrections"),
|
||||
QStringLiteral("Applies generic profile strength when camera metadata is not available."), &CameraRawOpticsSettings::enableLensProfile);
|
||||
m_profileRows = new QWidget(this);
|
||||
auto *profile = new QVBoxLayout(m_profileRows);
|
||||
profile->setContentsMargins(0, 0, 0, 0);
|
||||
profile->setSpacing(8);
|
||||
profile->addWidget(text(QStringLiteral("No lens metadata on this layer. Profile sliders set generic correction strength."), 10, true));
|
||||
row(profile, QStringLiteral("profileDistortion"), QStringLiteral("Distortion"), &CameraRawOpticsSettings::profileDistortion, 0, 100, 100,
|
||||
QStringLiteral("How much of the profile distortion correction is applied."));
|
||||
row(profile, QStringLiteral("profileVignetting"), QStringLiteral("Vignetting"), &CameraRawOpticsSettings::profileVignetting, 0, 100, 100,
|
||||
QStringLiteral("How much of the profile vignetting correction is applied."));
|
||||
column->addWidget(m_profileRows);
|
||||
column->addWidget(text(QStringLiteral("Manual"), 11, false));
|
||||
row(column, QStringLiteral("distortion"), QStringLiteral("Distortion"), &CameraRawOpticsSettings::distortion, -100, 100, 0,
|
||||
QStringLiteral("Straightens barrel or pincushion bending."));
|
||||
auto *defringe = new QHBoxLayout;
|
||||
defringe->setSpacing(10);
|
||||
auto *title = new QLabel(QStringLiteral("Defringe"), this);
|
||||
title->setMinimumWidth(CameraRawControls::labelWidth);
|
||||
title->setToolTip(QStringLiteral("Click a purple or green fringe to set its hue range."));
|
||||
m_defringe = new QToolButton(this);
|
||||
m_defringe->setObjectName(QStringLiteral("defringeSampler"));
|
||||
m_defringe->setAutoRaise(true);
|
||||
m_defringe->setToolTip(QStringLiteral("Click a purple or green fringe to set its hue range."));
|
||||
connect(m_defringe, &QToolButton::clicked, this, [this] {
|
||||
if (!m_session.filterEdit())
|
||||
return;
|
||||
CameraRawPanel panel = m_session.filterEdit()->rawPanel;
|
||||
panel.samplesDefringe = !panel.samplesDefringe;
|
||||
m_session.setCameraRawPanel(panel);
|
||||
});
|
||||
defringe->addWidget(title);
|
||||
defringe->addWidget(m_defringe);
|
||||
defringe->addStretch(1);
|
||||
column->addLayout(defringe);
|
||||
m_defringeHint = text(QStringLiteral("Click the fringe on the layer. Click the eyedropper again to stop."), 10, true);
|
||||
m_defringeHint->setObjectName(QStringLiteral("defringeHint"));
|
||||
column->addWidget(m_defringeHint);
|
||||
row(column, QStringLiteral("purpleAmount"), QStringLiteral("Purple Amount"), &CameraRawOpticsSettings::purpleAmount, 0, 100, 0,
|
||||
QStringLiteral("Weakens purple fringes inside the purple hue range."));
|
||||
column->addWidget(hueRange(QStringLiteral("purpleHue"), QStringLiteral("Purple Hue"), &CameraRawOpticsSettings::purpleHueLow,
|
||||
&CameraRawOpticsSettings::purpleHueHigh, 270, 310, QStringLiteral("Hue range where purple defringe runs.")));
|
||||
row(column, QStringLiteral("greenAmount"), QStringLiteral("Green Amount"), &CameraRawOpticsSettings::greenAmount, 0, 100, 0,
|
||||
QStringLiteral("Weakens green fringes inside the green hue range."));
|
||||
column->addWidget(hueRange(QStringLiteral("greenHue"), QStringLiteral("Green Hue"), &CameraRawOpticsSettings::greenHueLow,
|
||||
&CameraRawOpticsSettings::greenHueHigh, 60, 120, QStringLiteral("Hue range where green defringe runs.")));
|
||||
row(column, QStringLiteral("lensVignetting"), QStringLiteral("Vignetting"), &CameraRawOpticsSettings::vignetteAmount, -100, 100, 0,
|
||||
QStringLiteral("Brightens or darkens the corners to counter lens falloff."));
|
||||
row(column, QStringLiteral("lensMidpoint"), QStringLiteral("Midpoint"), &CameraRawOpticsSettings::vignetteMidpoint, 0, 100, 50,
|
||||
QStringLiteral("Moves the vignette correction inward or outward."));
|
||||
connect(&m_session, &EditorSession::changed, this, &CameraRawOpticsControls::synchronize);
|
||||
synchronize();
|
||||
}
|
||||
|
||||
// Swift's opticsSlider: ranges from zero round the slider's value.
|
||||
void CameraRawOpticsControls::row(QVBoxLayout *column, const QString &name, const QString &title, double CameraRawOpticsSettings::*key, double low,
|
||||
double high, double reset, const QString &help)
|
||||
{
|
||||
const auto set = [this, key](double value) { update([key, value](CameraRawOpticsSettings &optics) { optics.*key = value; }); };
|
||||
auto *row = new CameraRawRow({.name = name, .title = title, .help = help, .low = low, .high = high, .titleWidth = CameraRawControls::labelWidth},
|
||||
[this, key] { return raw(m_session).optics.*key; },
|
||||
[set, low](double value) { set(low < 0 ? value : std::round(value)); }, set, [set, reset] { set(reset); });
|
||||
column->addWidget(row);
|
||||
m_rows.push_back(row);
|
||||
}
|
||||
|
||||
// Swift's hueRange: Low and High, inset past the titles.
|
||||
QWidget *CameraRawOpticsControls::hueRange(const QString &name, const QString &title, double CameraRawOpticsSettings::*low,
|
||||
double CameraRawOpticsSettings::*high, double lowReset, double highReset, const QString &help)
|
||||
{
|
||||
auto *box = new QWidget;
|
||||
auto *column = new QVBoxLayout(box);
|
||||
column->setContentsMargins(CameraRawControls::labelWidth + 10, 0, 0, 0);
|
||||
column->setSpacing(4);
|
||||
QLabel *heading = text(title, 10, true);
|
||||
heading->setToolTip(help);
|
||||
column->addWidget(heading);
|
||||
auto *row = new QHBoxLayout;
|
||||
row->setSpacing(8);
|
||||
for (const bool start : {true, false}) {
|
||||
double CameraRawOpticsSettings::*key = start ? low : high;
|
||||
const QString words = start ? QStringLiteral("Start of the hue range, in degrees.") : QStringLiteral("End of the hue range, in degrees.");
|
||||
QLabel *end = text(start ? QStringLiteral("Low") : QStringLiteral("High"), 10, false);
|
||||
end->setToolTip(words);
|
||||
const double reset = start ? lowReset : highReset;
|
||||
auto *slider = new CameraRawSlider(
|
||||
0, 360, {}, words, [this, key](double value) { update([key, value](CameraRawOpticsSettings &optics) { optics.*key = std::round(value); }); },
|
||||
[this, key, reset] { update([key, reset](CameraRawOpticsSettings &optics) { optics.*key = reset; }); }, box);
|
||||
slider->setObjectName(name + (start ? QStringLiteral("Low") : QStringLiteral("High")));
|
||||
row->addWidget(end);
|
||||
row->addWidget(slider, 1);
|
||||
m_hueSliders.push_back({slider, key});
|
||||
}
|
||||
column->addLayout(row);
|
||||
return box;
|
||||
}
|
||||
|
||||
void CameraRawOpticsControls::update(const std::function<void(CameraRawOpticsSettings &)> &change)
|
||||
{
|
||||
::update(m_session, [&change](CameraRawSettings &settings) { change(settings.optics); });
|
||||
}
|
||||
|
||||
void CameraRawOpticsControls::synchronize()
|
||||
{
|
||||
const CameraRawOpticsSettings optics = raw(m_session).optics;
|
||||
const QSignalBlocker chromatic(m_chromatic), profile(m_profile);
|
||||
m_chromatic->setChecked(optics.removeChromaticAberration);
|
||||
m_profile->setChecked(optics.enableLensProfile);
|
||||
m_profileRows->setVisible(optics.enableLensProfile);
|
||||
const bool sampling = m_session.filterEdit() && m_session.filterEdit()->rawPanel.samplesDefringe;
|
||||
m_defringe->setIcon(EyedropperIcon::icon(palette().color(sampling ? QPalette::Highlight : QPalette::PlaceholderText), devicePixelRatioF()));
|
||||
m_defringeHint->setVisible(sampling);
|
||||
for (CameraRawRow *row : m_rows)
|
||||
row->synchronize();
|
||||
for (const auto &[slider, key] : m_hueSliders)
|
||||
slider->display(optics.*key);
|
||||
}
|
||||
Reference in new issue
Block a user