@bashbers/astro-image-dithering
Version:
Astro image dithering plugin - converts png's in project to dithered.pngs and uses them inside markdown files.
90 lines (89 loc) • 3.11 kB
JavaScript
import { readdirSync, statSync } from "fs";
import path from 'node:path';
function colorClamp(value) {
if (value < 0)
return 0;
else if (value > 255)
return 255;
return value;
}
var bayerMatrix8x8 = [
[],
[],
[],
[],
[],
[],
[],
[]
];
const pattern = [
[], /* 8x8 Bayer ordered dithering */
[], /* pattern. Each input pixel */
[], /* is scaled to the 0..63 range */
[], /* before looking in this table */
[], /* to determine the action. */
[],
[],
[]
];
// int r, int g, int b, int[][] palette, int paletteLength
function getClosestPaletteColorIndex(r, g, b, palette, paletteLength) {
var minDistance = 195076;
var diffR, diffG, diffB;
var distanceSquared;
var bestIndex = 0;
var paletteChannels;
for (var i = 0; i < paletteLength; i++) {
paletteChannels = palette[i];
diffR = r - paletteChannels[0];
diffG = g - paletteChannels[1];
diffB = b - paletteChannels[2];
distanceSquared = diffR * diffR + diffG * diffG + diffB * diffB;
if (distanceSquared < minDistance) {
bestIndex = i;
minDistance = distanceSquared;
}
}
return bestIndex;
}
export function BayerDithering(inPixels, width, height, palette) {
var offset = 0;
var indexedOffset = 0;
var r, g, b;
var pixel, threshold, index;
var paletteLength = palette.length;
var matrix = pattern;
var indexedPixels = new Uint8Array(width * height);
var modI = 8;
var modJ = 8;
for (var j = 0; j < height; j++) {
var modj = j % modJ;
for (var i = 0; i < width; i++) {
threshold = matrix[i % modI][modj];
r = colorClamp(inPixels[offset] + threshold);
g = colorClamp(inPixels[offset + 1] + threshold);
b = colorClamp(inPixels[offset + 2] + threshold);
offset += 4;
index = getClosestPaletteColorIndex(r, g, b, palette, paletteLength);
indexedPixels[indexedOffset++] = index;
}
}
return indexedPixels;
}
export function recursiveFindByExtension(base, ext, files, result) {
files = files || readdirSync(base);
result = result || [];
files.forEach(function (file) {
var newbase = path.join(base, file);
if (statSync(newbase).isDirectory()) {
result = recursiveFindByExtension(newbase, ext, readdirSync(newbase), result);
}
else {
if (file.substr(-1 * (ext.length + 1)) == '.' + ext) {
result.push(newbase);
}
}
});
return result;
}