asciify-engine 1.0.14 → 1.0.16

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 CHANGED
@@ -381,7 +381,7 @@ async function gifToAsciiFrames(buffer, options, targetWidth, targetHeight, onPr
381
381
  prevCtx.clearRect(0, 0, logicalW, logicalH);
382
382
  prevCtx.drawImage(compCanvas, 0, 0);
383
383
  }
384
- const frameImageData = new ImageData(patch, dims.width, dims.height);
384
+ const frameImageData = new ImageData(new Uint8ClampedArray(patch.buffer), dims.width, dims.height);
385
385
  const tempCanvas = document.createElement("canvas");
386
386
  tempCanvas.width = dims.width;
387
387
  tempCanvas.height = dims.height;
@@ -832,7 +832,7 @@ async function asciifyVideo(source, canvas, { fontSize = 10, style = "classic",
832
832
  cancelAnimationFrame(animId);
833
833
  };
834
834
  }
835
- var EMBED_CDN_VERSION = "1.0.14";
835
+ var EMBED_CDN_VERSION = "1.0.16";
836
836
  function buildEmbedOpts(options, rows, cols, width, height, fps, animated) {
837
837
  const o = {
838
838
  r: rows,
@@ -1120,6 +1120,303 @@ function renderStarsBackground(ctx, width, height, time, mousePos = { x: 0.5, y:
1120
1120
  }
1121
1121
  ctx.textAlign = "left";
1122
1122
  }
1123
+ function renderPulseBackground(ctx, width, height, time, mousePos = { x: 0.5, y: 0.5 }, options = {}) {
1124
+ const {
1125
+ fontSize = 13,
1126
+ chars = " .:-=+*#%@",
1127
+ accentColor = "#d4ff00",
1128
+ color,
1129
+ rings = 6,
1130
+ speed = 1,
1131
+ sharpness = 4,
1132
+ lightMode = false
1133
+ } = options;
1134
+ const charW = fontSize * 0.62;
1135
+ const lineH = fontSize * 1.4;
1136
+ const cols = Math.ceil(width / charW);
1137
+ const rows = Math.ceil(height / lineH);
1138
+ ctx.clearRect(0, 0, width, height);
1139
+ ctx.font = `${fontSize}px monospace`;
1140
+ ctx.textBaseline = "top";
1141
+ const maxR = Math.sqrt(width * width + height * height) * 0.5;
1142
+ const ox = mousePos.x * width;
1143
+ const oy = mousePos.y * height;
1144
+ let br = 255, bg2 = 255, bb = 255;
1145
+ if (lightMode) {
1146
+ br = 0;
1147
+ bg2 = 0;
1148
+ bb = 0;
1149
+ }
1150
+ if (color) {
1151
+ const p = _parseColor(color);
1152
+ if (p) {
1153
+ br = p.r;
1154
+ bg2 = p.g;
1155
+ bb = p.b;
1156
+ }
1157
+ }
1158
+ let acR = 212, acG = 255, acB = 0;
1159
+ const ap = _parseColor(accentColor);
1160
+ if (ap) {
1161
+ acR = ap.r;
1162
+ acG = ap.g;
1163
+ acB = ap.b;
1164
+ }
1165
+ const t = time * speed;
1166
+ for (let row = 0; row < rows; row++) {
1167
+ for (let col = 0; col < cols; col++) {
1168
+ const px = col * charW + charW * 0.5;
1169
+ const py = row * lineH + lineH * 0.5;
1170
+ const dist = Math.sqrt((px - ox) ** 2 + (py - oy) ** 2);
1171
+ const norm = dist / maxR;
1172
+ const phase = (norm * rings - t * 1.4) % 1;
1173
+ const wave = Math.pow(Math.max(0, Math.cos(phase * Math.PI * 2)), sharpness);
1174
+ if (wave < 0.02) continue;
1175
+ const charIdx = Math.floor(wave * (chars.length - 1));
1176
+ const ch = chars[charIdx];
1177
+ if (ch === " ") continue;
1178
+ const isAccent = wave > 0.75;
1179
+ const alpha = lightMode ? wave * 0.22 : wave * 0.14;
1180
+ ctx.fillStyle = isAccent ? `rgba(${acR},${acG},${acB},${lightMode ? 0.5 : 0.35})` : `rgba(${br},${bg2},${bb},${alpha})`;
1181
+ ctx.fillText(ch, col * charW, row * lineH);
1182
+ }
1183
+ }
1184
+ }
1185
+ function renderNoiseBackground(ctx, width, height, time, mousePos = { x: 0.5, y: 0.5 }, options = {}) {
1186
+ const {
1187
+ fontSize = 14,
1188
+ chars = " .\xB7:;=+*#%@\u2591\u2592\u2593",
1189
+ accentColor = "#d4ff00",
1190
+ color,
1191
+ octaves = 4,
1192
+ speed = 1,
1193
+ scale = 1,
1194
+ accentThreshold = 0.78,
1195
+ mouseWarp = 0.3,
1196
+ lightMode = false
1197
+ } = options;
1198
+ const charW = fontSize * 0.62;
1199
+ const lineH = fontSize * 1.4;
1200
+ const cols = Math.ceil(width / charW);
1201
+ const rows = Math.ceil(height / lineH);
1202
+ ctx.clearRect(0, 0, width, height);
1203
+ ctx.font = `${fontSize}px monospace`;
1204
+ ctx.textBaseline = "top";
1205
+ let br = 255, bgc = 255, bb = 255;
1206
+ if (lightMode) {
1207
+ br = 0;
1208
+ bgc = 0;
1209
+ bb = 0;
1210
+ }
1211
+ if (color) {
1212
+ const p = _parseColor(color);
1213
+ if (p) {
1214
+ br = p.r;
1215
+ bgc = p.g;
1216
+ bb = p.b;
1217
+ }
1218
+ }
1219
+ let acR = 212, acG = 255, acB = 0;
1220
+ const ap = _parseColor(accentColor);
1221
+ if (ap) {
1222
+ acR = ap.r;
1223
+ acG = ap.g;
1224
+ acB = ap.b;
1225
+ }
1226
+ const noiseScale = 0.035 * scale;
1227
+ const t = time * speed;
1228
+ const oct = Math.min(6, Math.max(1, octaves));
1229
+ const fbmN = (x, y) => {
1230
+ let v = 0, amp = 0.5, freq = 1, norm = 0;
1231
+ for (let o = 0; o < oct; o++) {
1232
+ v += _vnoise(x * freq, y * freq) * amp;
1233
+ norm += amp;
1234
+ amp *= 0.5;
1235
+ freq *= 2.1;
1236
+ }
1237
+ return v / norm;
1238
+ };
1239
+ for (let row = 0; row < rows; row++) {
1240
+ for (let col = 0; col < cols; col++) {
1241
+ const nx = col * noiseScale + t * 0.06;
1242
+ const ny = row * noiseScale * 1.3 - t * 0.04;
1243
+ const dx = col / cols - mousePos.x;
1244
+ const dy = row / rows - mousePos.y;
1245
+ const dist = Math.sqrt(dx * dx + dy * dy);
1246
+ const warp = mouseWarp > 0 ? Math.max(0, 1 - dist / mouseWarp) * 0.12 : 0;
1247
+ const wx = nx + warp * Math.sin(t * 1.3 + dy * 8);
1248
+ const wy = ny + warp * Math.cos(t * 0.9 + dx * 8);
1249
+ const raw = fbmN(wx, wy);
1250
+ const norm2 = raw * 0.5 + 0.5;
1251
+ if (norm2 < 0.12) continue;
1252
+ const charIdx = Math.floor(norm2 * (chars.length - 1));
1253
+ const ch = chars[charIdx];
1254
+ if (ch === " ") continue;
1255
+ const isAccent = norm2 > accentThreshold;
1256
+ const alpha = lightMode ? norm2 * 0.2 : norm2 * 0.13;
1257
+ ctx.fillStyle = isAccent ? `rgba(${acR},${acG},${acB},${lightMode ? 0.42 : 0.28})` : `rgba(${br},${bgc},${bb},${alpha})`;
1258
+ ctx.fillText(ch, col * charW, row * lineH);
1259
+ }
1260
+ }
1261
+ }
1262
+ function renderGridBackground(ctx, width, height, time, mousePos = { x: 0.5, y: 0.5 }, options = {}) {
1263
+ const {
1264
+ fontSize = 12,
1265
+ chars = "\xB7-=+|/",
1266
+ accentColor = "#d4ff00",
1267
+ color,
1268
+ bands = 3,
1269
+ speed = 1,
1270
+ bandWidth = 0.12,
1271
+ glitch = true,
1272
+ lightMode = false
1273
+ } = options;
1274
+ const charW = fontSize * 0.62;
1275
+ const lineH = fontSize * 1.4;
1276
+ const cols = Math.ceil(width / charW);
1277
+ const rows = Math.ceil(height / lineH);
1278
+ ctx.clearRect(0, 0, width, height);
1279
+ ctx.font = `${fontSize}px monospace`;
1280
+ ctx.textBaseline = "top";
1281
+ let br = 255, bgv = 255, bb = 255;
1282
+ if (lightMode) {
1283
+ br = 0;
1284
+ bgv = 0;
1285
+ bb = 0;
1286
+ }
1287
+ if (color) {
1288
+ const p = _parseColor(color);
1289
+ if (p) {
1290
+ br = p.r;
1291
+ bgv = p.g;
1292
+ bb = p.b;
1293
+ }
1294
+ }
1295
+ let acR = 212, acG = 255, acB = 0;
1296
+ const ap = _parseColor(accentColor);
1297
+ if (ap) {
1298
+ acR = ap.r;
1299
+ acG = ap.g;
1300
+ acB = ap.b;
1301
+ }
1302
+ const t = time * speed;
1303
+ for (let row = 0; row < rows; row++) {
1304
+ for (let col = 0; col < cols; col++) {
1305
+ const ny = row / rows;
1306
+ const scanPhase = ((ny * bands - t * 0.5) % 1 + 1) % 1;
1307
+ const bandIntensity = Math.max(0, 1 - scanPhase / bandWidth);
1308
+ const gridSeed = _hash2(col * 3, row * 7);
1309
+ const gridBase = (gridSeed * 0.5 + 0.5) * 0.35;
1310
+ let glitchBump = 0;
1311
+ if (glitch) {
1312
+ const dx = col / cols - mousePos.x;
1313
+ const dy = ny - mousePos.y;
1314
+ const d = Math.sqrt(dx * dx + dy * dy);
1315
+ if (d < 0.18) {
1316
+ const g = _hash2(col * 11 + Math.floor(t * 12), row * 5);
1317
+ glitchBump = Math.max(0, 1 - d / 0.18) * (g > 0.5 ? g - 0.3 : 0);
1318
+ }
1319
+ }
1320
+ const intensity = Math.min(1, gridBase + bandIntensity * 0.8 + glitchBump * 0.6);
1321
+ if (intensity < 0.04) continue;
1322
+ const charIdx = Math.floor(intensity * (chars.length - 1));
1323
+ const ch = chars[charIdx];
1324
+ const isAccent = bandIntensity > 0.55;
1325
+ const alpha = lightMode ? intensity * 0.2 : intensity * 0.12;
1326
+ ctx.fillStyle = isAccent ? `rgba(${acR},${acG},${acB},${lightMode ? 0.46 : 0.28})` : `rgba(${br},${bgv},${bb},${alpha})`;
1327
+ ctx.fillText(ch, col * charW, row * lineH);
1328
+ }
1329
+ }
1330
+ }
1331
+ function renderAuroraBackground(ctx, width, height, time, mousePos = { x: 0.5, y: 0.5 }, options = {}) {
1332
+ const {
1333
+ fontSize = 14,
1334
+ chars = " \xB7\u2219\u2022:;+=\u2261\u2263#@",
1335
+ color,
1336
+ accentColor = "#d4ff00",
1337
+ speed = 1,
1338
+ layers = 5,
1339
+ softness = 1.2,
1340
+ mouseRipple = 0.2,
1341
+ lightMode = false
1342
+ } = options;
1343
+ const charW = fontSize * 0.62;
1344
+ const lineH = fontSize * 1.4;
1345
+ const cols = Math.ceil(width / charW);
1346
+ const rows = Math.ceil(height / lineH);
1347
+ ctx.clearRect(0, 0, width, height);
1348
+ ctx.font = `${fontSize}px monospace`;
1349
+ ctx.textBaseline = "top";
1350
+ let cr = 255, cg = 255, cb = 255;
1351
+ if (lightMode) {
1352
+ cr = 0;
1353
+ cg = 0;
1354
+ cb = 0;
1355
+ }
1356
+ if (color) {
1357
+ const p = _parseColor(color);
1358
+ if (p) {
1359
+ cr = p.r;
1360
+ cg = p.g;
1361
+ cb = p.b;
1362
+ }
1363
+ }
1364
+ let acR = 212, acG = 255, acB = 0;
1365
+ const ap = _parseColor(accentColor);
1366
+ if (ap) {
1367
+ acR = ap.r;
1368
+ acG = ap.g;
1369
+ acB = ap.b;
1370
+ }
1371
+ const t = time * speed;
1372
+ const layerParams = [];
1373
+ for (let l = 0; l < layers; l++) {
1374
+ const seed = _hash2(l * 17, l * 31 + 7);
1375
+ const seed2 = _hash2(l * 23 + 5, l * 11);
1376
+ layerParams.push({
1377
+ fx: 0.8 + seed * 2.2,
1378
+ // x spatial frequency
1379
+ fy: 1.2 + seed2 * 1.8,
1380
+ // y spatial frequency
1381
+ phase: seed * Math.PI * 4,
1382
+ // phase offset
1383
+ dt: (0.3 + _hash2(l * 7, l * 13 + 3) * 0.5) * (l % 2 === 0 ? 1 : -1),
1384
+ // drift speed & direction
1385
+ amp: 0.55 + _hash2(l * 29, l * 3) * 0.45
1386
+ // amplitude weight
1387
+ });
1388
+ }
1389
+ for (let row = 0; row < rows; row++) {
1390
+ const ny = row / rows;
1391
+ for (let col = 0; col < cols; col++) {
1392
+ const nx = col / cols;
1393
+ const mdx = nx - mousePos.x;
1394
+ const mdy = ny - mousePos.y;
1395
+ const md = Math.sqrt(mdx * mdx + mdy * mdy);
1396
+ const warp = mouseRipple * Math.exp(-md * md / 0.06);
1397
+ const wx = nx + mdx * warp;
1398
+ const wy = ny + mdy * warp;
1399
+ let sum = 0;
1400
+ let totalAmp = 0;
1401
+ for (let l = 0; l < layers; l++) {
1402
+ const { fx, fy, phase, dt, amp } = layerParams[l];
1403
+ const wave = Math.sin(wx * fx * Math.PI * 2 + t * dt + phase) * Math.cos(wy * fy * Math.PI * 2 + t * dt * 0.7 + phase * 1.3);
1404
+ sum += wave * amp;
1405
+ totalAmp += amp;
1406
+ }
1407
+ const rawVal = sum / totalAmp;
1408
+ const curved = 0.5 + 0.5 * Math.tanh(rawVal * softness * 2.2);
1409
+ if (curved < 0.12) continue;
1410
+ const normalized = (curved - 0.12) / 0.88;
1411
+ const charIdx = Math.min(chars.length - 1, Math.floor(normalized * chars.length));
1412
+ const ch = chars[charIdx];
1413
+ const isAccent = curved > 0.82;
1414
+ const alpha = lightMode ? curved * 0.18 : curved * 0.14;
1415
+ ctx.fillStyle = isAccent ? `rgba(${acR},${acG},${acB},${lightMode ? 0.5 : 0.32})` : `rgba(${cr},${cg},${cb},${alpha})`;
1416
+ ctx.fillText(ch, col * charW, row * lineH);
1417
+ }
1418
+ }
1419
+ }
1123
1420
  function _parseColor(c) {
1124
1421
  const hex = c.match(/^#([0-9a-f]{3,8})$/i)?.[1];
1125
1422
  if (hex) {
@@ -1188,10 +1485,34 @@ function asciiBackground(target, options = {}) {
1188
1485
  lightMode: renderOpts.lightMode !== void 0 ? renderOpts.lightMode : isLight(),
1189
1486
  color: color ?? renderOpts.color
1190
1487
  });
1488
+ const buildPulseOpts = () => ({
1489
+ ...renderOpts,
1490
+ lightMode: renderOpts.lightMode !== void 0 ? renderOpts.lightMode : isLight(),
1491
+ color: color ?? renderOpts.color
1492
+ });
1493
+ const buildNoiseOpts = () => ({
1494
+ ...renderOpts,
1495
+ lightMode: renderOpts.lightMode !== void 0 ? renderOpts.lightMode : isLight(),
1496
+ color: color ?? renderOpts.color
1497
+ });
1498
+ const buildGridOpts = () => ({
1499
+ ...renderOpts,
1500
+ lightMode: renderOpts.lightMode !== void 0 ? renderOpts.lightMode : isLight(),
1501
+ color: color ?? renderOpts.color
1502
+ });
1503
+ const buildAuroraOpts = () => ({
1504
+ ...renderOpts,
1505
+ lightMode: renderOpts.lightMode !== void 0 ? renderOpts.lightMode : isLight(),
1506
+ color: color ?? renderOpts.color
1507
+ });
1191
1508
  const optsRef = { current: buildWaveOpts() };
1192
1509
  const rebuildOpts = () => {
1193
1510
  if (type === "rain") optsRef.current = buildRainOpts();
1194
1511
  else if (type === "stars") optsRef.current = buildStarsOpts();
1512
+ else if (type === "pulse") optsRef.current = buildPulseOpts();
1513
+ else if (type === "noise") optsRef.current = buildNoiseOpts();
1514
+ else if (type === "grid") optsRef.current = buildGridOpts();
1515
+ else if (type === "aurora") optsRef.current = buildAuroraOpts();
1195
1516
  else optsRef.current = buildWaveOpts();
1196
1517
  };
1197
1518
  rebuildOpts();
@@ -1224,6 +1545,14 @@ function asciiBackground(target, options = {}) {
1224
1545
  renderRainBackground(ctx, r.width, r.height, time, optsRef.current);
1225
1546
  } else if (type === "stars") {
1226
1547
  renderStarsBackground(ctx, r.width, r.height, time, smoothMouse, optsRef.current);
1548
+ } else if (type === "pulse") {
1549
+ renderPulseBackground(ctx, r.width, r.height, time, smoothMouse, optsRef.current);
1550
+ } else if (type === "noise") {
1551
+ renderNoiseBackground(ctx, r.width, r.height, time, smoothMouse, optsRef.current);
1552
+ } else if (type === "grid") {
1553
+ renderGridBackground(ctx, r.width, r.height, time, smoothMouse, optsRef.current);
1554
+ } else if (type === "aurora") {
1555
+ renderAuroraBackground(ctx, r.width, r.height, time, smoothMouse, optsRef.current);
1227
1556
  } else {
1228
1557
  renderWaveBackground(ctx, r.width, r.height, time, smoothMouse, optsRef.current);
1229
1558
  }
@@ -1705,7 +2034,11 @@ exports.generateEmbedCode = generateEmbedCode;
1705
2034
  exports.gifToAsciiFrames = gifToAsciiFrames;
1706
2035
  exports.imageToAsciiFrame = imageToAsciiFrame;
1707
2036
  exports.mountWaveBackground = mountWaveBackground;
2037
+ exports.renderAuroraBackground = renderAuroraBackground;
1708
2038
  exports.renderFrameToCanvas = renderFrameToCanvas;
2039
+ exports.renderGridBackground = renderGridBackground;
2040
+ exports.renderNoiseBackground = renderNoiseBackground;
2041
+ exports.renderPulseBackground = renderPulseBackground;
1709
2042
  exports.renderRainBackground = renderRainBackground;
1710
2043
  exports.renderStarsBackground = renderStarsBackground;
1711
2044
  exports.renderWaveBackground = renderWaveBackground;