asciify-engine 1.0.38 → 1.0.40
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/README.md +117 -336
- package/dist/index.cjs +17 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +17 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -79,6 +79,24 @@ interface AsciiOptions {
|
|
|
79
79
|
* `0` = no dithering, `1` = full dithering. Default: `0`
|
|
80
80
|
*/
|
|
81
81
|
ditherStrength: number;
|
|
82
|
+
/**
|
|
83
|
+
* Assumed aspect ratio (width ÷ height) of a single output character.
|
|
84
|
+
* Controls how many rows vs columns are generated — must match your rendering
|
|
85
|
+
* environment to preserve the source image's proportions.
|
|
86
|
+
* - `0.55` — browser monospace at `line-height: 1.09` (default)
|
|
87
|
+
* - `0.52` — browser monospace at `line-height: 1.15`
|
|
88
|
+
* - `0.5` — most terminal emulators
|
|
89
|
+
* Default: `0.55`
|
|
90
|
+
*/
|
|
91
|
+
charAspect: number;
|
|
92
|
+
/**
|
|
93
|
+
* Auto-stretch the luminance range before charset mapping.
|
|
94
|
+
* When `true`, the darkest pixel in the frame maps to the first charset character
|
|
95
|
+
* and the brightest to the last, maximising perceived detail and contrast.
|
|
96
|
+
* Particularly useful for images with low inherent contrast or muted tones.
|
|
97
|
+
* Default: `false`
|
|
98
|
+
*/
|
|
99
|
+
normalize: boolean;
|
|
82
100
|
/**
|
|
83
101
|
* Overall intensity of the hover / cursor interaction effect.
|
|
84
102
|
* `0` disables the effect. Default: `0`
|
package/dist/index.d.ts
CHANGED
|
@@ -79,6 +79,24 @@ interface AsciiOptions {
|
|
|
79
79
|
* `0` = no dithering, `1` = full dithering. Default: `0`
|
|
80
80
|
*/
|
|
81
81
|
ditherStrength: number;
|
|
82
|
+
/**
|
|
83
|
+
* Assumed aspect ratio (width ÷ height) of a single output character.
|
|
84
|
+
* Controls how many rows vs columns are generated — must match your rendering
|
|
85
|
+
* environment to preserve the source image's proportions.
|
|
86
|
+
* - `0.55` — browser monospace at `line-height: 1.09` (default)
|
|
87
|
+
* - `0.52` — browser monospace at `line-height: 1.15`
|
|
88
|
+
* - `0.5` — most terminal emulators
|
|
89
|
+
* Default: `0.55`
|
|
90
|
+
*/
|
|
91
|
+
charAspect: number;
|
|
92
|
+
/**
|
|
93
|
+
* Auto-stretch the luminance range before charset mapping.
|
|
94
|
+
* When `true`, the darkest pixel in the frame maps to the first charset character
|
|
95
|
+
* and the brightest to the last, maximising perceived detail and contrast.
|
|
96
|
+
* Particularly useful for images with low inherent contrast or muted tones.
|
|
97
|
+
* Default: `false`
|
|
98
|
+
*/
|
|
99
|
+
normalize: boolean;
|
|
82
100
|
/**
|
|
83
101
|
* Overall intensity of the hover / cursor interaction effect.
|
|
84
102
|
* `0` disables the effect. Default: `0`
|
package/dist/index.js
CHANGED
|
@@ -110,6 +110,8 @@ var DEFAULT_OPTIONS = {
|
|
|
110
110
|
animationSpeed: 1,
|
|
111
111
|
dotSizeRatio: 0.8,
|
|
112
112
|
ditherStrength: 0,
|
|
113
|
+
charAspect: 0.55,
|
|
114
|
+
normalize: false,
|
|
113
115
|
hoverStrength: 0,
|
|
114
116
|
hoverRadius: 0.2,
|
|
115
117
|
hoverEffect: "spotlight",
|
|
@@ -604,7 +606,7 @@ function imageToAsciiFrame(source, options, targetWidth, targetHeight) {
|
|
|
604
606
|
if (srcWidth === 0 || srcHeight === 0) {
|
|
605
607
|
return { frame: [], cols: 0, rows: 0 };
|
|
606
608
|
}
|
|
607
|
-
const charAspect =
|
|
609
|
+
const charAspect = options.charAspect;
|
|
608
610
|
const cellW = options.fontSize * options.charSpacing;
|
|
609
611
|
const cellH = options.fontSize / charAspect * options.charSpacing;
|
|
610
612
|
const renderW = targetWidth || srcWidth;
|
|
@@ -618,6 +620,18 @@ function imageToAsciiFrame(source, options, targetWidth, targetHeight) {
|
|
|
618
620
|
ctx.drawImage(source, 0, 0, cols, rows);
|
|
619
621
|
const imageData = ctx.getImageData(0, 0, cols, rows);
|
|
620
622
|
const pixels = imageData.data;
|
|
623
|
+
let normMin = 0;
|
|
624
|
+
let normRange = 255;
|
|
625
|
+
if (options.normalize) {
|
|
626
|
+
let lo = 255, hi = 0;
|
|
627
|
+
for (let k = 0; k < pixels.length; k += 4) {
|
|
628
|
+
const l = 0.299 * pixels[k] + 0.587 * pixels[k + 1] + 0.114 * pixels[k + 2];
|
|
629
|
+
if (l < lo) lo = l;
|
|
630
|
+
if (l > hi) hi = l;
|
|
631
|
+
}
|
|
632
|
+
normMin = lo;
|
|
633
|
+
normRange = hi > lo ? hi - lo : 255;
|
|
634
|
+
}
|
|
621
635
|
const frame = [];
|
|
622
636
|
for (let y = 0; y < rows; y++) {
|
|
623
637
|
const row = [];
|
|
@@ -627,7 +641,8 @@ function imageToAsciiFrame(source, options, targetWidth, targetHeight) {
|
|
|
627
641
|
const g = pixels[i + 1];
|
|
628
642
|
const b = pixels[i + 2];
|
|
629
643
|
const a = pixels[i + 3];
|
|
630
|
-
const
|
|
644
|
+
const rawLum = 0.299 * r + 0.587 * g + 0.114 * b;
|
|
645
|
+
const lum = options.normalize ? (rawLum - normMin) / normRange * 255 : rawLum;
|
|
631
646
|
const adjustedLum = adjustLuminance(lum, options.brightness, options.contrast);
|
|
632
647
|
const ditheredLum = applyDither(adjustedLum, x, y, options.ditherStrength);
|
|
633
648
|
const char = options.customText ? customTextToChar(ditheredLum, options.customText, x, y, cols, options.invert) : luminanceToChar(ditheredLum, options.charset, options.invert);
|