Restore smooth gradient sampling

This commit is contained in:
wuyanwanwu
2026-08-14 01:33:23 +08:00
parent daffe4daca
commit cf0f53d148
12 changed files with 24 additions and 34 deletions
+10 -20
View File
@@ -268,21 +268,24 @@ function sampleDominantRegions(
cropX: number,
cropY: number,
) {
// A mildly center-weighted 3x3 vote keeps geometric corners without letting
// one anti-aliased center sample overpower the surrounding real colors.
// Keep the previously stable center-weighted 3x3 sampler. The canvas
// interpolation is important for broad gradients (sky, shadows, skin tones),
// while the later transition-band cleanup handles one-cell anti-aliased
// colors at hard object boundaries.
const scale = 3;
const sampleWeights = [
[1, 1, 1],
[1, 2, 1],
[1, 1, 1],
[2, 4, 2],
[1, 2, 1],
];
const totalSampleWeight = 10;
const totalSampleWeight = 16;
const sample = document.createElement("canvas");
sample.width = width * scale;
sample.height = height * scale;
const ctx = sample.getContext("2d", { willReadFrequently: true })!;
ctx.clearRect(0, 0, sample.width, sample.height);
ctx.imageSmoothingEnabled = false;
ctx.imageSmoothingEnabled = true;
ctx.imageSmoothingQuality = "high";
drawFittedImage(ctx, image, sample.width, sample.height, fitMode, cropZoom, cropX, cropY);
const source = ctx.getImageData(0, 0, sample.width, sample.height).data;
const result = new Uint8ClampedArray(width * height * 4);
@@ -331,20 +334,7 @@ function sampleDominantRegions(
confidence[row * width + column] = transparentWeight / totalSampleWeight;
continue;
}
const rankedGroups = groups.map((group) => {
let effectiveWeight = group.weight;
if (group.count <= 2) {
for (let first = 0; first < groups.length; first++) {
for (let second = first + 1; second < groups.length; second++) {
if (groups[first] === group || groups[second] === group) continue;
if (groups[first].weight + groups[second].weight < group.weight) continue;
if (isPerceptualBridge(group.lab, groups[first].lab, groups[second].lab)) effectiveWeight = 0;
}
}
}
return { group, effectiveWeight };
});
const dominant = rankedGroups.sort((a, b) => b.effectiveWeight - a.effectiveWeight || b.group.weight - a.group.weight || Number(b.group.containsCenter) - Number(a.group.containsCenter))[0].group;
const dominant = groups.sort((a, b) => b.weight - a.weight || Number(b.containsCenter) - Number(a.containsCenter))[0];
const representative = dominant.samples.reduce((best, current) =>
oklabDistance(current.lab, dominant.lab) < oklabDistance(best.lab, dominant.lab) ? current : best,
);