Finishing filters: Vignette, Bloom / Glow, Tonal Contrast (12.9a)

This commit is contained in:
雷电芽衣 committed 2026-09-28 10:50:06 -04:00
1 parent 96ce546508
commit fdb62978c5
20 files changed
+756 -35

No files matched your search

+75 -5
View File
@@ -408,10 +408,8 @@ static void effects_dehaze(double *r, double *g, double *b, double amount) {
*b = camera_clamp(y2 + (*b - y2) * sat);
}
static void effects_vignette(double *r, double *g, double *b, size_t x, size_t y, size_t width, size_t height,
double amount, double midpoint, double roundness, double feather, double highlights,
int style) {
if (amount == 0 || width == 0 || height == 0) return;
static double vignette_mask(size_t x, size_t y, size_t width, size_t height,
double midpoint, double roundness, double feather) {
double nx = ((double)x + 0.5) / (double)width * 2.0 - 1.0;
double ny = ((double)y + 0.5) / (double)height * 2.0 - 1.0;
double square = fmax(fabs(nx), fabs(ny));
@@ -423,7 +421,14 @@ static void effects_vignette(double *r, double *g, double *b, size_t x, size_t y
if (soft < 0.05) soft = 0.05;
double t = (dist - start) / soft;
t = camera_clamp(t);
double mask = t * t * (3.0 - 2.0 * t);
return t * t * (3.0 - 2.0 * t);
}
static void effects_vignette(double *r, double *g, double *b, size_t x, size_t y, size_t width, size_t height,
double amount, double midpoint, double roundness, double feather, double highlights,
int style) {
if (amount == 0 || width == 0 || height == 0) return;
double mask = vignette_mask(x, y, width, height, midpoint, roundness, feather);
double effect = (amount / 100.0) * mask;
// Highlight Priority eases a darkening vignette off bright pixels. The other styles do not.
if (effect < 0 && style == 0) {
@@ -447,6 +452,33 @@ static void effects_vignette(double *r, double *g, double *b, size_t x, size_t y
}
}
void adjust_colored_vignette(uint8_t *rgba, size_t width, size_t height, size_t stride,
double amount, double midpoint, double roundness, double feather,
double highlights, double red, double green, double blue) {
if (!rgba || amount <= 0 || width == 0 || height == 0) return;
double strength = camera_clamp(amount / 100.0);
red = camera_clamp(red); green = camera_clamp(green); blue = camera_clamp(blue);
for (size_t y = 0; y < height; ++y) {
uint8_t *row = rgba + y * stride;
for (size_t x = 0; x < width; ++x) {
uint8_t *p = row + x * 4;
double alpha = p[3];
if (!alpha) continue;
double mask = vignette_mask(x, y, width, height, midpoint, roundness, feather);
if (mask <= 0) continue;
double r = fmin(1.0, p[0] / alpha);
double g = fmin(1.0, p[1] / alpha);
double b = fmin(1.0, p[2] / alpha);
double bright = camera_clamp((rec709(r, g, b) - 0.45) / 0.55);
double effect = strength * mask * (1.0 - (highlights / 100.0) * bright);
r += (red - r) * effect;
g += (green - g) * effect;
b += (blue - b) * effect;
write_premultiplied(p, r, g, b, alpha);
}
}
}
void adjust_camera_raw_clip_overlay(uint8_t *rgba, size_t width, size_t height, size_t stride, int shadows, int highlights) {
if (!shadows && !highlights) return;
for (size_t y = 0; y < height; ++y) {
@@ -581,6 +613,44 @@ void adjust_camera_raw_effects(uint8_t *rgba, size_t width, size_t height, size_
free(glowPlane);
}
static double tonal_smooth(double low, double high, double value) {
double t = camera_clamp((value - low) / (high - low));
return t * t * (3.0 - 2.0 * t);
}
void adjust_tonal_contrast(uint8_t *rgba, const uint8_t *blurred, size_t width, size_t height,
size_t stride, size_t blurredStride, double amount,
double shadows, double midtones, double highlights) {
if (amount <= 0 || (shadows == 0 && midtones == 0 && highlights == 0)) return;
double strength = amount / 50.0;
for (size_t y = 0; y < height; ++y) {
uint8_t *row = rgba + y * stride;
const uint8_t *baseRow = blurred + y * blurredStride;
for (size_t x = 0; x < width; ++x) {
uint8_t *p = row + x * 4;
const uint8_t *base = baseRow + x * 4;
double alpha = p[3];
if (alpha == 0 || base[3] == 0) continue;
double r = fmin(1.0, p[0] / alpha);
double g = fmin(1.0, p[1] / alpha);
double b = fmin(1.0, p[2] / alpha);
double lum = rec709(r, g, b);
double baseLum = rec709(fmin(1.0, base[0] / (double)base[3]),
fmin(1.0, base[1] / (double)base[3]),
fmin(1.0, base[2] / (double)base[3]));
double shadowWeight = 1.0 - tonal_smooth(0.15, 0.5, baseLum);
double highlightWeight = tonal_smooth(0.5, 0.85, baseLum);
double midtoneWeight = 1.0 - shadowWeight - highlightWeight;
double weight = (shadows * shadowWeight + midtones * midtoneWeight +
highlights * highlightWeight) / 100.0;
double detail = lum - baseLum;
double delta = 0.18 * tanh(detail * 6.0) * weight * strength * (4.0 * lum * (1.0 - lum));
write_premultiplied(p, camera_clamp(r + delta), camera_clamp(g + delta),
camera_clamp(b + delta), alpha);
}
}
}
static double lut_at(const float *lut, double value) {
double scaled = camera_clamp(value) * 255.0;
int lo = (int)scaled;