asciify-engine 1.0.69 → 1.0.70
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 +63 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +63 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1162,6 +1162,25 @@ function renderFrameToCanvas(ctx, frame, options, canvasWidth, canvasHeight, tim
|
|
|
1162
1162
|
}
|
|
1163
1163
|
|
|
1164
1164
|
// src/core/simple-api.ts
|
|
1165
|
+
function getSourceDims(el) {
|
|
1166
|
+
if (el instanceof HTMLVideoElement) return { w: el.videoWidth, h: el.videoHeight };
|
|
1167
|
+
if (el instanceof HTMLImageElement) return { w: el.naturalWidth || el.width, h: el.naturalHeight || el.height };
|
|
1168
|
+
return { w: el.width, h: el.height };
|
|
1169
|
+
}
|
|
1170
|
+
function makeHiResCanvas(srcW, srcH, displayW, displayH) {
|
|
1171
|
+
if (srcW <= displayW && srcH <= displayH) return null;
|
|
1172
|
+
const MAX = 2048;
|
|
1173
|
+
const scale = Math.min(1, MAX / Math.max(srcW, srcH));
|
|
1174
|
+
const offW = Math.round(srcW * scale);
|
|
1175
|
+
const offH = Math.round(srcH * scale);
|
|
1176
|
+
if (offW <= displayW && offH <= displayH) return null;
|
|
1177
|
+
const offCanvas = document.createElement("canvas");
|
|
1178
|
+
offCanvas.width = offW;
|
|
1179
|
+
offCanvas.height = offH;
|
|
1180
|
+
const offCtx = offCanvas.getContext("2d");
|
|
1181
|
+
if (!offCtx) return null;
|
|
1182
|
+
return { offCanvas, offCtx, offW, offH };
|
|
1183
|
+
}
|
|
1165
1184
|
function sizeCanvasToContainer(canvas, container, aspect, srcW, srcH) {
|
|
1166
1185
|
const { width, height } = container.getBoundingClientRect();
|
|
1167
1186
|
if (!width || !height) return;
|
|
@@ -1213,8 +1232,17 @@ async function asciify(source, canvas, { fontSize, artStyle = "classic", options
|
|
|
1213
1232
|
const merged = { ...DEFAULT_OPTIONS, ...preset, ...options, fontSize: resolvedFontSize };
|
|
1214
1233
|
const ctx = canvas.getContext("2d");
|
|
1215
1234
|
if (!ctx) throw new Error("Could not get 2d context from canvas");
|
|
1216
|
-
const {
|
|
1217
|
-
|
|
1235
|
+
const { w: srcW, h: srcH } = getSourceDims(el);
|
|
1236
|
+
const hires = makeHiResCanvas(srcW, srcH, canvas.width, canvas.height);
|
|
1237
|
+
if (hires) {
|
|
1238
|
+
const { frame } = imageToAsciiFrame(el, merged, hires.offW, hires.offH);
|
|
1239
|
+
renderFrameToCanvas(hires.offCtx, frame, merged, hires.offW, hires.offH);
|
|
1240
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
1241
|
+
ctx.drawImage(hires.offCanvas, 0, 0, canvas.width, canvas.height);
|
|
1242
|
+
} else {
|
|
1243
|
+
const { frame } = imageToAsciiFrame(el, merged, canvas.width, canvas.height);
|
|
1244
|
+
renderFrameToCanvas(ctx, frame, merged, canvas.width, canvas.height);
|
|
1245
|
+
}
|
|
1218
1246
|
}
|
|
1219
1247
|
async function asciifyGif(source, canvas, { fontSize, artStyle = "classic", options = {} } = {}) {
|
|
1220
1248
|
const buffer = typeof source === "string" ? await fetch(source).then((r) => r.arrayBuffer()) : source;
|
|
@@ -1267,15 +1295,24 @@ async function asciifyVideo(source, canvas, { fontSize, artStyle = "classic", op
|
|
|
1267
1295
|
video2 = source;
|
|
1268
1296
|
}
|
|
1269
1297
|
if (container) sizeCanvasToContainer(canvas, container, video2.videoWidth / video2.videoHeight, video2.videoWidth, video2.videoHeight);
|
|
1298
|
+
const hires2 = makeHiResCanvas(video2.videoWidth, video2.videoHeight, canvas.width, canvas.height);
|
|
1299
|
+
const renderW = hires2 ? hires2.offW : canvas.width;
|
|
1300
|
+
const renderH = hires2 ? hires2.offH : canvas.height;
|
|
1270
1301
|
const maxDur = trimEnd !== void 0 ? trimEnd - trimStart : 10;
|
|
1271
|
-
const { frames, fps } = await videoToAsciiFrames(video2, merged,
|
|
1302
|
+
const { frames, fps } = await videoToAsciiFrames(video2, merged, renderW, renderH, void 0, maxDur, void 0, trimStart);
|
|
1272
1303
|
let cancelled2 = false, animId2, i = 0, last = performance.now();
|
|
1273
1304
|
let firstFrame2 = true;
|
|
1274
1305
|
const interval = 1e3 / fps;
|
|
1275
1306
|
const tick2 = (now) => {
|
|
1276
1307
|
if (cancelled2) return;
|
|
1277
1308
|
if (now - last >= interval) {
|
|
1278
|
-
|
|
1309
|
+
if (hires2) {
|
|
1310
|
+
renderFrameToCanvas(hires2.offCtx, frames[i], merged, hires2.offW, hires2.offH);
|
|
1311
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
1312
|
+
ctx.drawImage(hires2.offCanvas, 0, 0, canvas.width, canvas.height);
|
|
1313
|
+
} else {
|
|
1314
|
+
renderFrameToCanvas(ctx, frames[i], merged, canvas.width, canvas.height);
|
|
1315
|
+
}
|
|
1279
1316
|
i = (i + 1) % frames.length;
|
|
1280
1317
|
last = now;
|
|
1281
1318
|
if (firstFrame2) {
|
|
@@ -1353,6 +1390,7 @@ async function asciifyVideo(source, canvas, { fontSize, artStyle = "classic", op
|
|
|
1353
1390
|
ro = new ResizeObserver(() => sizeCanvasToContainer(canvas, container, aspect, vw, vh));
|
|
1354
1391
|
ro.observe(container);
|
|
1355
1392
|
}
|
|
1393
|
+
const hires = makeHiResCanvas(video.videoWidth, video.videoHeight, canvas.width, canvas.height);
|
|
1356
1394
|
let cancelled = false;
|
|
1357
1395
|
let animId;
|
|
1358
1396
|
let firstFrame = true;
|
|
@@ -1362,14 +1400,28 @@ async function asciifyVideo(source, canvas, { fontSize, artStyle = "classic", op
|
|
|
1362
1400
|
if (video.readyState < 2 || canvas.width === 0 || canvas.height === 0) return;
|
|
1363
1401
|
if (trimStart > 0 && video.currentTime < trimStart) return;
|
|
1364
1402
|
if (trimEnd !== void 0 && video.currentTime >= trimEnd) return;
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1403
|
+
if (hires) {
|
|
1404
|
+
const { frame } = imageToAsciiFrame(video, merged, hires.offW, hires.offH);
|
|
1405
|
+
if (frame.length > 0) {
|
|
1406
|
+
renderFrameToCanvas(hires.offCtx, frame, merged, hires.offW, hires.offH, 0, null);
|
|
1407
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
1408
|
+
ctx.drawImage(hires.offCanvas, 0, 0, canvas.width, canvas.height);
|
|
1409
|
+
if (firstFrame) {
|
|
1410
|
+
firstFrame = false;
|
|
1411
|
+
onReady?.(video);
|
|
1412
|
+
}
|
|
1413
|
+
onFrame?.();
|
|
1414
|
+
}
|
|
1415
|
+
} else {
|
|
1416
|
+
const { frame } = imageToAsciiFrame(video, merged, canvas.width, canvas.height);
|
|
1417
|
+
if (frame.length > 0) {
|
|
1418
|
+
renderFrameToCanvas(ctx, frame, merged, canvas.width, canvas.height, 0, null);
|
|
1419
|
+
if (firstFrame) {
|
|
1420
|
+
firstFrame = false;
|
|
1421
|
+
onReady?.(video);
|
|
1422
|
+
}
|
|
1423
|
+
onFrame?.();
|
|
1371
1424
|
}
|
|
1372
|
-
onFrame?.();
|
|
1373
1425
|
}
|
|
1374
1426
|
};
|
|
1375
1427
|
animId = requestAnimationFrame(tick);
|