web: SHARPENING lifts only the edge it was pointed at, so a flat half of the frame keeps the grain it came with
SHARPENING was the doc's §4.2 kernel with the two parts of §4.2 missing from
it. `CLARITY_SKSL` evaluated the 3x3 unsharp mask with Mask = 1 on every pixel
and no coring at all, so a flat sky, a cheek and a noise speckle all took the
gain an eyelash took. That is `thay_doi_thong_so_giong_lightroom.md` §1 written
out as a bug: "khi Sharpen, ảnh nổi đầy sạn hạt cát" — the knob could not raise
the contrast of an edge without raising the noise of everything beside it, and
on a grainy frame the second effect won.
`SHARPEN_SKSL` is the doc's own line, `Image + Amount x HighPass x Mask`, with
the two terms it names:
- EDGE DETECTION: the Sobel magnitude G = sqrt(Gx^2 + Gy^2) on luminance, put
through the doc's soft threshold smoothstep(T, T + 0.1, G). Flat fields
read G = 0 and get Mask = 0 — the pixel is handed back untouched.
- DETAIL (halo coring): a high-pass under SHARPEN_CORE is a speckle, not a
detail, and is suppressed. The coring is soft (a ramp across the threshold,
not a cliff) so a detail sitting on it is not switched on and off from one
pixel to the next.
The HIGH-PASS is the doc's Radius, held at one image pixel — 0.7-0.9px on a
Retina panel — and it is a LUMINANCE high-pass carried by all three channels.
A per-channel kernel sharpens a red edge against a green one and draws a colour
fringe down every contour; the file's own §3 rule is to keep R/L, G/L and B/L
where they were.
`scripts/sharpen-check.mjs` pins the three properties the old kernel could not
have: a flat field and a field of grain come back unchanged, a step below the
threshold comes back unchanged, and a hard step moves apart on both sides while
the flat halves beside it stay put. `CLARITY_SKSL` and `clarityUniforms` are
gone with it, and the header note that said CanvasKit had two convolution steps
to replace now says the one it has.
Checked: node scripts/sharpen-check.mjs; node scripts/denoise-check.mjs; node
scripts/tone-base-check.mjs; node scripts/highlight-knee-check.mjs; node
scripts/auto-tone-check.mjs; node scripts/half-check.mjs; node
scripts/mask-wb-check.mjs; node scripts/preview-match-check.mjs; node
scripts/raw-develop-check.mjs; node scripts/white-level-check.mjs; node
scripts/wb-table-check.mjs; npx tsc --noEmit.
This commit is contained in:
@@ -6,11 +6,12 @@
|
||||
// - `Skia.Data.fromURI` + expo file APIs → the caller hands in the JPEG bytes
|
||||
// and gets JPEG bytes back; the file save / gallery / MediaLibrary tail is
|
||||
// gone (the browser downloads a Blob instead).
|
||||
// - `MakeMatrixConvolution` does not exist in CanvasKit. The two convolution
|
||||
// steps (CLARITY, output sharpen) run through `CLARITY_SKSL` from
|
||||
// `toneShader.ts` — the same kernel `[0,-a,0,-a,1+4a,-a,0,-a,0]`, evaluated
|
||||
// as a shader pass. `convolve` replaces the pixels outright (the shader's
|
||||
// output is opaque and covers the same rect), so no clearing pass is needed.
|
||||
// - `MakeMatrixConvolution` does not exist in CanvasKit. The output sharpen
|
||||
// (and CLARITY's own kernel) run through shader passes instead —
|
||||
// `SHARPEN_SKSL` for the knob, the same kernel with the doc's Sobel edge
|
||||
// mask and detail coring on it. `convolve` replaces the pixels outright (the
|
||||
// shader's output is opaque and covers the same rect), so no clearing pass
|
||||
// is needed.
|
||||
// - The negative-side blurs stay on `ImageFilter.MakeBlur`, but a blur cannot
|
||||
// be composited over the un-blurred content, so those passes snapshot, clear
|
||||
// and redraw. Order matches RN's nested filter chain: denoise → clarity →
|
||||
@@ -28,7 +29,7 @@ import {
|
||||
TONE_SKSL,
|
||||
EXPOSURE_SKSL,
|
||||
GLOW_SKSL,
|
||||
CLARITY_SKSL,
|
||||
SHARPEN_SKSL,
|
||||
CLARITY_BLUR_SKSL,
|
||||
CLARITY_BLEND_SKSL,
|
||||
NR_SKSL,
|
||||
@@ -173,7 +174,7 @@ let nrEffect: any = null;
|
||||
let dehazeEffect: any = null;
|
||||
|
||||
function effects() {
|
||||
if (!sharpenEffect) sharpenEffect = Skia.RuntimeEffect.Make(CLARITY_SKSL);
|
||||
if (!sharpenEffect) sharpenEffect = Skia.RuntimeEffect.Make(SHARPEN_SKSL);
|
||||
if (!toneEffect) toneEffect = Skia.RuntimeEffect.Make(TONE_SKSL);
|
||||
if (!exposureEffect) exposureEffect = Skia.RuntimeEffect.Make(EXPOSURE_SKSL);
|
||||
if (!cinemaEffect) cinemaEffect = Skia.RuntimeEffect.Make(CINEMA_SKSL);
|
||||
@@ -242,7 +243,7 @@ function maskEffectFor(count: number, spatial: boolean): any {
|
||||
return effect;
|
||||
}
|
||||
|
||||
// CLARITY_SKSL uniforms are (a, px.x, px.y); px = one source pixel = 1 unit on
|
||||
// SHARPEN_SKSL uniforms are (a, px.x, px.y); px = one source pixel = 1 unit on
|
||||
// a 1:1 export canvas, so the radius matches what the preview tuned.
|
||||
function convolvePaint(srcImage: any, amount: number): any {
|
||||
const { sharpenEffect: effect } = effects();
|
||||
|
||||
Reference in New Issue
Block a user