Skip to content

Instantly share code, notes, and snippets.

@zazaulola
Created July 20, 2024 05:33
Show Gist options
  • Save zazaulola/0409d84ab61c24032937666bbc01eae6 to your computer and use it in GitHub Desktop.
Save zazaulola/0409d84ab61c24032937666bbc01eae6 to your computer and use it in GitHub Desktop.
Basic one-thread image hermite resample
const s2l = c => (c > 0.04045 ? ((c + 0.055) / 1.055) ** 2.4 : c / 12.92);
const l2s = c => (c > 0.0031308 ? 1.055 * Math.pow(c, 1 / 2.4) - 0.055 : 12.92 * c);
const LINEAR = new Array(256).fill().map((_, i) => s2l(i / 255));
onmessage = ({ data: { srcData, srcWidth, srcHeight, dstWidth, dstHeight } }) => {
const { ceil, floor, abs, min, hypot } = Math;
const ratioH = srcHeight / dstHeight;
const ratioW = srcWidth / dstWidth;
const halfRatioW = ceil(ratioW / 2);
const halfRatioH = ceil(ratioH / 2);
const dstData = new Uint8ClampedArray(dstWidth * dstHeight * 4);
for (let dstY = 0; dstY < dstHeight; dstY++) {
for (let dstX = 0; dstX < dstWidth; dstX++) {
let dstOfs = (dstX + dstY * dstWidth) * 4;
let weight = 0;
let sAlp = 0;
let sAA = 0;
let [gxRed, gxGrn, gxBlu, gxAlp] = [0, 0, 0, 0];
const [centerX, centerY] = [(dstX + 0.5) * ratioW, (dstY + 0.5) * ratioH];
const [begY, endY] = [floor(dstY * ratioH), min(ceil((dstY + 1) * ratioH), srcHeight)];
const [begX, endX] = [floor(dstX * ratioW), min(ceil((dstX + 1) * ratioW), srcWidth)];
for (let srcY = begY; srcY < endY; srcY++) {
const dH = abs(centerY - (srcY + 0.5)) / halfRatioH;
for (let srcX = begX; srcX < endX; srcX++) {
const dW = abs(centerX - (srcX + 0.5)) / halfRatioW;
const far = hypot(dH, dW);
if (far >= 1) {
//pixel too far
continue;
}
//hermite filter
weight = 2 * far ** 3 - 3 * far ** 2 + 1;
const srcOfs = 4 * (srcX + srcY * srcWidth);
//alpha
gxAlp += weight * srcData[srcOfs + 3];
sAA += weight;
if (srcData[srcOfs + 3] < 255) {
// s *= sD[ofs + 3] / 250;
weight *= srcData[srcOfs + 3] / 255;
}
//colors
gxRed += weight * LINEAR[srcData[srcOfs + 0]];
gxGrn += weight * LINEAR[srcData[srcOfs + 1]];
gxBlu += weight * LINEAR[srcData[srcOfs + 2]];
sAlp += weight;
}
}
dstData[dstOfs + 0] = l2s(gxRed / sAlp) * 255;
dstData[dstOfs + 1] = l2s(gxGrn / sAlp) * 255;
dstData[dstOfs + 2] = l2s(gxBlu / sAlp) * 255;
dstData[dstOfs + 3] = l2s(gxAlp / sAA) * 255;
}
}
postMessage(dstData);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment