Files
OmaPhoto/src/Document/CameraRaw.h
T

180 lines
7.2 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#pragma once
#include "Document/CameraRawColor.h"
#include "Document/CameraRawDetailOptics.h"
#include "Document/CameraRawGeometryCalibration.h"
#include <QImage>
#include <array>
#include <optional>
#include <utility>
struct FilterJob;
// Relative offsets, not kelvin; `auto` is a keyword here.
enum class CameraRawWhiteBalance { custom, automatic };
enum class CameraRawGlowStyle { diffusion, bloom, halation };
// Highlight Priority's Highlights slider protects bright pixels.
enum class CameraRawVignetteStyle { highlightPriority, colorPriority, paintOverlay };
// Option on a Light slider shows clipping; never written in.
enum class CameraRawClipping { highlights = 1, shadows = 2 };
enum class CameraRawScopeMode { histogram, vectorscope };
// Swift's panel eyes: a hidden group leaves the grade.
struct CameraRawGroups {
bool light = true;
bool color = true;
bool effects = true;
bool curve = true;
bool mixer = true;
bool grading = true;
bool detail = true;
bool optics = true;
bool geometry = true;
bool calibration = true;
friend bool operator==(const CameraRawGroups &, const CameraRawGroups &) = default;
};
// Defaults leave the image unchanged.
struct CameraRawSettings {
static constexpr double exposureLow = -5, exposureHigh = 5;
// A full warm or cool swing on red and blue.
static constexpr double temperatureGain = 0.35;
static constexpr double tintRedBlue = 0.15;
static constexpr double tintGreen = 0.30;
CameraRawWhiteBalance whiteBalance = CameraRawWhiteBalance::custom;
// Cool to warm, −100 to 100; tint green to magenta.
double temperature = 0;
double tint = 0;
// Stops of linear light, −5 to 5.
double exposure = 0;
double contrast = 0;
double highlights = 0;
double shadows = 0;
double whites = 0;
double blacks = 0;
double vibrance = 0;
double saturation = 0;
// Local contrast: Texture the finer band, Clarity the broader.
double texture = 0;
double clarity = 0;
double dehaze = 0;
// 0 to 100; range, spread and warmth rest at zero.
double glow = 0;
CameraRawGlowStyle glowStyle = CameraRawGlowStyle::diffusion;
double glowRange = 0;
double glowSpread = 0;
double glowWarmth = 0;
// Negative darkens the edges, positive lightens; the centre stays.
double vignetteAmount = 0;
CameraRawVignetteStyle vignetteStyle = CameraRawVignetteStyle::highlightPriority;
double vignetteMidpoint = 50;
double vignetteRoundness = 0;
double vignetteFeather = 50;
double vignetteHighlights = 0;
double grainAmount = 0;
double grainSize = 25;
double grainRoughness = 50;
CameraRawCurveSettings curve;
CameraRawMixerSettings mixer;
CameraRawGradingSettings grading;
CameraRawDetailSettings detail;
CameraRawOpticsSettings optics;
CameraRawGeometrySettings geometry;
CameraRawCalibrationSettings calibration;
bool adjustsLight() const;
bool adjustsColor() const;
bool adjustsEffects() const;
bool isIdentity() const;
CameraRawSettings normalized() const;
// The grade with some panel eyes off: those groups zeroed.
CameraRawSettings applying(const CameraRawGroups &shown) const;
// Camera Raw's 0 to 100 size in `adjust_grain`'s pixels.
double grainKernelSize() const;
struct Gains {
double red;
double green;
double blue;
};
Gains gains() const;
// `clipping`: the Option view; `scale`: preview pixels a pixel.
QImage apply(const QImage &image, std::optional<CameraRawClipping> clipping = std::nullopt, double scale = 1, quint32 seed = 0,
int visualizePointColor = -1, bool sharpenMask = false) const;
struct Balance {
double temperature;
double tint;
};
// The temperature and tint making a linear pixel neutral.
static std::optional<Balance> neutralizeLinear(double red, double green, double blue);
static std::optional<Balance> neutralizeStraight(double red, double green, double blue);
// Gray-world balance of the opaque pixels.
static std::optional<Balance> autoBalance(const QImage &image);
void applyCurveColor(uchar *pixels, int width, int height, qsizetype stride, int visualize) const;
void applyDetailOptics(uchar *pixels, int width, int height, qsizetype stride, double scale, double profileStrength, bool sharpenMask) const;
void applyCalibration(uchar *pixels, int width, int height, qsizetype stride) const;
friend bool operator==(const CameraRawSettings &, const CameraRawSettings &) = default;
};
// An RGB histogram and a hue and saturation vectorscope.
struct CameraRawScope {
static constexpr int binCount = 256;
static constexpr int scopeSide = 64;
std::array<double, binCount> red{};
std::array<double, binCount> green{};
std::array<double, binCount> blue{};
// Density from the centre out, row by row.
std::vector<double> vectorscope = std::vector<double>(scopeSide * scopeSide);
// One vertical scale, so the ribbons stay comparable.
double peak() const;
// Counts the graded image, clear pixels skipped.
static std::optional<CameraRawScope> make(const QImage &image);
// Clipped shadows blue, clipped highlights red, over the grade.
static QImage overlay(const QImage &image, bool shadows, bool highlights);
// The preview and the scope of the grade itself.
static std::pair<QImage, CameraRawScope> preview(const FilterJob &job);
friend bool operator==(const CameraRawScope &, const CameraRawScope &) = default;
};
// Swift's CameraRawDrag: a targeted adjustment under way.
struct CameraRawDrag {
double startY;
CameraRawSettings settings;
double tone;
double hue;
};
// Swift's FilterEdit fields for the Camera Raw panel.
struct CameraRawPanel {
// Eyes off drop a group from preview and OK.
CameraRawGroups shows;
CameraRawCurvePage curvePage = CameraRawCurvePage::parametric;
CameraRawPointChannel pointChannel = CameraRawPointChannel::rgb;
CameraRawMixerPage mixerPage = CameraRawMixerPage::hsl;
CameraRawMixerTab mixerTab = CameraRawMixerTab::hue;
int mixerSwatch = 0;
int pointIndex = 0;
CameraRawGradePage gradePage = CameraRawGradePage::threeWay;
bool targetsCurve = false;
bool targetsMixer = false;
bool samplesPointColor = false;
std::optional<CameraRawDrag> drag;
// The white-balance and defringe eyedroppers.
bool samplesWhiteBalance = false;
bool samplesDefringe = false;
// Guided Upright: lines dragged on the preview.
bool drawingGeometryGuide = false;
std::optional<std::pair<QPointF, QPointF>> guideDraft;
// Option on a Light slider, or on Sharpening's Masking.
std::optional<CameraRawClipping> clipping;
bool sharpenMask = false;
// The histogram's clipping marks, never baked in on OK.
bool showsShadowClipping = false;
bool showsHighlightClipping = false;
CameraRawScopeMode scopeMode = CameraRawScopeMode::histogram;
std::optional<CameraRawScope> scope;
// The adjusted preview's RGB under the pointer.
std::optional<std::array<int, 3>> readout;
// The point colour being shown in isolation, or −1.
int pointColorVisualizeIndex(const CameraRawSettings &settings) const;
};