asciify-engine 1.0.45 → 1.0.47

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 CHANGED
@@ -129,8 +129,44 @@ All conversion and render functions accept an `AsciiOptions` object. Spread `DEF
129
129
  | `invert` | `boolean` | `false` | Inverts the luminance mapping — light areas become dense, dark areas sparse. |
130
130
  | `renderMode` | `'ascii' \| 'dots'` | `'ascii'` | Render as text characters or circular dot particles. |
131
131
  | `hoverEffect` | `string` | `'none'` | Interactive effect driven by cursor position. See hover effects below. |
132
- | `hoverStrength` | `number` | `0.8` | Effect intensity (0–1). |
133
- | `hoverRadius` | `number` | `0.3` | Effect radius relative to canvas size (0–1). |
132
+ | `hoverStrength` | `number` | `0` | Effect intensity (0–1). `0` = hover disabled. |
133
+ | `hoverRadius` | `number` | `0.2` | Effect radius relative to canvas size (0–1). |
134
+ | `chromaKey` | `{r,g,b} \| string \| null` | `null` | Remove a background colour (green/blue screen). Keyed pixels become transparent spaces. Accepts `{r,g,b}`, any CSS colour string, or `null` to disable. |
135
+ | `chromaKeyTolerance` | `number` | `60` | Euclidean RGB distance threshold for chroma-key detection. `0` = exact match, higher = more pixels removed (max useful ~100). |
136
+
137
+ ### Chroma Key (Green/Blue Screen)
138
+
139
+ Remove a solid background colour from any source — images, GIFs, or video — so the canvas background shows through keyed pixels.
140
+
141
+ ```ts
142
+ import { asciify, DEFAULT_OPTIONS } from 'asciify-engine';
143
+
144
+ // Green screen — zero config, just set true:
145
+ asciify(img, canvas, {
146
+ options: { ...DEFAULT_OPTIONS, chromaKey: true, colorMode: 'fullcolor' },
147
+ });
148
+
149
+ // Blue screen
150
+ asciify(img, canvas, {
151
+ options: { ...DEFAULT_OPTIONS, chromaKey: 'blue', chromaKeyTolerance: 70 },
152
+ });
153
+
154
+ // Custom RGB key
155
+ asciify(img, canvas, {
156
+ options: { ...DEFAULT_OPTIONS, chromaKey: { r: 0, g: 180, b: 90 }, chromaKeyTolerance: 50 },
157
+ });
158
+
159
+ // Live video with green screen
160
+ asciifyVideo('/footage.mp4', canvas, {
161
+ fitTo: '#container',
162
+ options: { ...DEFAULT_OPTIONS, chromaKey: true, colorMode: 'fullcolor' },
163
+ });
164
+ ```
165
+
166
+ **Tolerance guide:**
167
+ - `40–60` — tight key, natural green screen under good lighting
168
+ - `60–80` — broader key, wrinkled fabric or uneven lighting
169
+ - `80–120` — aggressive; expect some spill into the subject
134
170
 
135
171
  ### Color Modes
136
172
 
package/dist/index.cjs CHANGED
@@ -119,7 +119,9 @@ var DEFAULT_OPTIONS = {
119
119
  hoverEffect: "spotlight",
120
120
  hoverColor: "#ffffff",
121
121
  artStyle: "classic",
122
- customText: ""
122
+ customText: "",
123
+ chromaKey: null,
124
+ chromaKeyTolerance: 60
123
125
  };
124
126
  var HOVER_PRESETS = {
125
127
  none: {
@@ -258,6 +260,17 @@ function getCellColorRGB(cell, colorMode, acR, acG, acB) {
258
260
  }
259
261
  return _colorRGB;
260
262
  }
263
+ function parseChromaKeyColor(color) {
264
+ if (typeof color !== "string") return color;
265
+ const canvas = document.createElement("canvas");
266
+ canvas.width = 1;
267
+ canvas.height = 1;
268
+ const ctx = canvas.getContext("2d");
269
+ ctx.fillStyle = color;
270
+ ctx.fillRect(0, 0, 1, 1);
271
+ const d = ctx.getImageData(0, 0, 1, 1).data;
272
+ return { r: d[0], g: d[1], b: d[2] };
273
+ }
261
274
 
262
275
  // src/core/animation.ts
263
276
  function smoothstep(t) {
@@ -635,6 +648,13 @@ function imageToAsciiFrame(source, options, targetWidth, targetHeight) {
635
648
  normRange = hi > lo ? hi - lo : 255;
636
649
  }
637
650
  const frame = [];
651
+ let ckRGB = null;
652
+ let ckTolSq = 0;
653
+ const ck = options.chromaKey;
654
+ if (ck != null && ck !== false) {
655
+ ckRGB = ck === true ? { r: 0, g: 177, b: 64 } : parseChromaKeyColor(ck);
656
+ ckTolSq = (options.chromaKeyTolerance ?? 60) ** 2;
657
+ }
638
658
  for (let y = 0; y < rows; y++) {
639
659
  const row = [];
640
660
  for (let x = 0; x < cols; x++) {
@@ -643,6 +663,15 @@ function imageToAsciiFrame(source, options, targetWidth, targetHeight) {
643
663
  const g = pixels[i + 1];
644
664
  const b = pixels[i + 2];
645
665
  const a = pixels[i + 3];
666
+ if (ckRGB !== null) {
667
+ const dr = r - ckRGB.r;
668
+ const dg = g - ckRGB.g;
669
+ const db = b - ckRGB.b;
670
+ if (dr * dr + dg * dg + db * db <= ckTolSq) {
671
+ row.push({ char: " ", r: 0, g: 0, b: 0, a: 0 });
672
+ continue;
673
+ }
674
+ }
646
675
  const rawLum = 0.299 * r + 0.587 * g + 0.114 * b;
647
676
  const lum = options.normalize ? (rawLum - normMin) / normRange * 255 : rawLum;
648
677
  const adjustedLum = adjustLuminance(lum, options.brightness, options.contrast);