asciify-engine 1.0.61 → 1.0.64
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +50 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +50 -32
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -284,9 +284,7 @@ function getCellColorStr(cell, colorMode, acR, acG, acB, _isInverted = false) {
|
|
|
284
284
|
case "matrix":
|
|
285
285
|
return GREEN_LUT[0.299 * cell.r + 0.587 * cell.g + 0.114 * cell.b | 0];
|
|
286
286
|
case "accent": {
|
|
287
|
-
|
|
288
|
-
const ab = _isInverted ? 1 - rawAb : rawAb;
|
|
289
|
-
return `rgb(${acR * ab | 0},${acG * ab | 0},${acB * ab | 0})`;
|
|
287
|
+
return `rgb(${acR},${acG},${acB})`;
|
|
290
288
|
}
|
|
291
289
|
default: {
|
|
292
290
|
const gray = 0.299 * cell.r + 0.587 * cell.g + 0.114 * cell.b | 0;
|
|
@@ -310,11 +308,9 @@ function getCellColorRGB(cell, colorMode, acR, acG, acB, _isInverted = false) {
|
|
|
310
308
|
break;
|
|
311
309
|
}
|
|
312
310
|
case "accent": {
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
_colorRGB[
|
|
316
|
-
_colorRGB[1] = acG * ab | 0;
|
|
317
|
-
_colorRGB[2] = acB * ab | 0;
|
|
311
|
+
_colorRGB[0] = acR;
|
|
312
|
+
_colorRGB[1] = acG;
|
|
313
|
+
_colorRGB[2] = acB;
|
|
318
314
|
break;
|
|
319
315
|
}
|
|
320
316
|
default: {
|
|
@@ -730,9 +726,14 @@ function imageToAsciiFrame(source, options, targetWidth, targetHeight) {
|
|
|
730
726
|
if (cols <= 0 || rows <= 0) {
|
|
731
727
|
return { frame: [], cols: 0, rows: 0 };
|
|
732
728
|
}
|
|
733
|
-
const
|
|
734
|
-
|
|
735
|
-
const
|
|
729
|
+
const maxDim = 2048;
|
|
730
|
+
const ssX = Math.max(1, Math.min(Math.floor(maxDim / cols), Math.floor(srcWidth / cols)));
|
|
731
|
+
const ssY = Math.max(1, Math.min(Math.floor(maxDim / rows), Math.floor(srcHeight / rows)));
|
|
732
|
+
const sampleW = cols * ssX;
|
|
733
|
+
const sampleH = rows * ssY;
|
|
734
|
+
const { ctx } = createOffscreenCanvas(sampleW, sampleH);
|
|
735
|
+
ctx.drawImage(source, 0, 0, sampleW, sampleH);
|
|
736
|
+
const imageData = ctx.getImageData(0, 0, sampleW, sampleH);
|
|
736
737
|
const pixels = imageData.data;
|
|
737
738
|
const ck = options.chromaKey;
|
|
738
739
|
const ckEnabled = ck != null && ck !== false;
|
|
@@ -771,36 +772,53 @@ function imageToAsciiFrame(source, options, targetWidth, targetHeight) {
|
|
|
771
772
|
}
|
|
772
773
|
const frame = [];
|
|
773
774
|
const invertVal = resolveInvert(options.invert);
|
|
775
|
+
const effectiveCharset = ckEnabled ? options.charset.replace(/ /g, "") || options.charset : options.charset;
|
|
776
|
+
const ssCount = ssX * ssY;
|
|
774
777
|
for (let y = 0; y < rows; y++) {
|
|
775
778
|
const row = [];
|
|
776
779
|
for (let x = 0; x < cols; x++) {
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
780
|
+
let sumR = 0, sumG = 0, sumB = 0, sumA = 0;
|
|
781
|
+
let keyedCount = 0;
|
|
782
|
+
for (let sy = 0; sy < ssY; sy++) {
|
|
783
|
+
const rowOff = (y * ssY + sy) * sampleW;
|
|
784
|
+
for (let sx = 0; sx < ssX; sx++) {
|
|
785
|
+
const i = (rowOff + x * ssX + sx) * 4;
|
|
786
|
+
const pr = pixels[i], pg = pixels[i + 1], pb = pixels[i + 2], pa = pixels[i + 3];
|
|
787
|
+
if (ckEnabled) {
|
|
788
|
+
let keyed = false;
|
|
789
|
+
if (ckHeuristicGreen) {
|
|
790
|
+
keyed = pg > pr * 1.4 && pg > pb * 1.4 && pg > 80;
|
|
791
|
+
} else if (ckHeuristicBlue) {
|
|
792
|
+
keyed = pb > pr * 1.4 && pb > pg * 1.4 && pb > 80;
|
|
793
|
+
} else if (ckRGB !== null) {
|
|
794
|
+
const dr = pr - ckRGB.r, dg = pg - ckRGB.g, db = pb - ckRGB.b;
|
|
795
|
+
keyed = dr * dr + dg * dg + db * db <= ckTolSq;
|
|
796
|
+
}
|
|
797
|
+
if (keyed) {
|
|
798
|
+
keyedCount++;
|
|
799
|
+
continue;
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
sumR += pr;
|
|
803
|
+
sumG += pg;
|
|
804
|
+
sumB += pb;
|
|
805
|
+
sumA += pa;
|
|
797
806
|
}
|
|
798
807
|
}
|
|
808
|
+
if (ckEnabled && keyedCount > ssCount / 2) {
|
|
809
|
+
row.push({ char: " ", r: 0, g: 0, b: 0, a: 0 });
|
|
810
|
+
continue;
|
|
811
|
+
}
|
|
812
|
+
const nonKeyed = ssCount - keyedCount;
|
|
813
|
+
const r = nonKeyed > 0 ? sumR / nonKeyed : 0;
|
|
814
|
+
const g = nonKeyed > 0 ? sumG / nonKeyed : 0;
|
|
815
|
+
const b = nonKeyed > 0 ? sumB / nonKeyed : 0;
|
|
816
|
+
const a = nonKeyed > 0 ? sumA / nonKeyed : 0;
|
|
799
817
|
const rawLum = 0.299 * r + 0.587 * g + 0.114 * b;
|
|
800
818
|
const lum = options.normalize ? (rawLum - normMin) / normRange * 255 : rawLum;
|
|
801
819
|
const adjustedLum = adjustLuminance(lum, options.brightness, options.contrast);
|
|
802
820
|
const ditheredLum = applyDither(adjustedLum, x, y, options.ditherStrength);
|
|
803
|
-
const char = options.customText ? customTextToChar(ditheredLum, options.customText, x, y, cols, invertVal) : luminanceToChar(ditheredLum,
|
|
821
|
+
const char = options.customText ? customTextToChar(ditheredLum, options.customText, x, y, cols, invertVal) : luminanceToChar(ditheredLum, effectiveCharset, invertVal);
|
|
804
822
|
row.push({ char, r, g, b, a, lum: ditheredLum });
|
|
805
823
|
}
|
|
806
824
|
frame.push(row);
|