This commit is contained in:
Akko
2025-08-04 18:57:35 +02:00
parent 8cf6e78a79
commit 9495868c2e
5030 changed files with 518594 additions and 17609 deletions

View File

@@ -0,0 +1,11 @@
import { Rectangle } from '../../maths/shapes/Rectangle';
import type { ICanvas } from '../../environment/canvas/ICanvas';
/**
* Measuring the bounds of a canvas' visible (non-transparent) pixels.
* @param canvas - The canvas to measure.
* @param resolution - The resolution of the canvas.
* @returns The bounding box of the canvas' visible pixels.
* @since 7.1.0
* @memberof utils
*/
export declare function getCanvasBoundingBox(canvas: ICanvas, resolution?: number): Rectangle;

View File

@@ -0,0 +1,51 @@
'use strict';
var Rectangle = require('../../maths/shapes/Rectangle.js');
"use strict";
function checkRow(data, width, y) {
for (let x = 0, index = 4 * y * width; x < width; ++x, index += 4) {
if (data[index + 3] !== 0)
return false;
}
return true;
}
function checkColumn(data, width, x, top, bottom) {
const stride = 4 * width;
for (let y = top, index = top * stride + 4 * x; y <= bottom; ++y, index += stride) {
if (data[index + 3] !== 0)
return false;
}
return true;
}
function getCanvasBoundingBox(canvas, resolution = 1) {
const { width, height } = canvas;
const context = canvas.getContext("2d", {
willReadFrequently: true
});
if (context === null) {
throw new TypeError("Failed to get canvas 2D context");
}
const imageData = context.getImageData(0, 0, width, height);
const data = imageData.data;
let left = 0;
let top = 0;
let right = width - 1;
let bottom = height - 1;
while (top < height && checkRow(data, width, top))
++top;
if (top === height)
return Rectangle.Rectangle.EMPTY;
while (checkRow(data, width, bottom))
--bottom;
while (checkColumn(data, width, left, top, bottom))
++left;
while (checkColumn(data, width, right, top, bottom))
--right;
++right;
++bottom;
return new Rectangle.Rectangle(left / resolution, top / resolution, (right - left) / resolution, (bottom - top) / resolution);
}
exports.getCanvasBoundingBox = getCanvasBoundingBox;
//# sourceMappingURL=getCanvasBoundingBox.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"getCanvasBoundingBox.js","sources":["../../../src/utils/canvas/getCanvasBoundingBox.ts"],"sourcesContent":["import { Rectangle } from '../../maths/shapes/Rectangle';\n\nimport type { ICanvas } from '../../environment/canvas/ICanvas';\n\nfunction checkRow(data: Uint8ClampedArray, width: number, y: number)\n{\n for (let x = 0, index = 4 * y * width; x < width; ++x, index += 4)\n {\n if (data[index + 3] !== 0) return false;\n }\n\n return true;\n}\n\nfunction checkColumn(data: Uint8ClampedArray, width: number, x: number, top: number, bottom: number)\n{\n const stride = 4 * width;\n\n for (let y = top, index = (top * stride) + (4 * x); y <= bottom; ++y, index += stride)\n {\n if (data[index + 3] !== 0) return false;\n }\n\n return true;\n}\n\n/**\n * Measuring the bounds of a canvas' visible (non-transparent) pixels.\n * @param canvas - The canvas to measure.\n * @param resolution - The resolution of the canvas.\n * @returns The bounding box of the canvas' visible pixels.\n * @since 7.1.0\n * @memberof utils\n */\nexport function getCanvasBoundingBox(canvas: ICanvas, resolution = 1): Rectangle\n{\n // https://gist.github.com/timdown/021d9c8f2aabc7092df564996f5afbbf\n\n const { width, height } = canvas;\n\n const context = canvas.getContext('2d', {\n willReadFrequently: true,\n });\n\n if (context === null)\n {\n throw new TypeError('Failed to get canvas 2D context');\n }\n\n const imageData = context.getImageData(0, 0, width, height);\n const data = imageData.data;\n\n let left = 0;\n let top = 0;\n let right = width - 1;\n let bottom = height - 1;\n\n while (top < height && checkRow(data, width, top)) ++top;\n if (top === height) return Rectangle.EMPTY;\n while (checkRow(data, width, bottom)) --bottom;\n while (checkColumn(data, width, left, top, bottom)) ++left;\n while (checkColumn(data, width, right, top, bottom)) --right;\n\n ++right;\n ++bottom;\n\n return new Rectangle(left / resolution, top / resolution, (right - left) / resolution, (bottom - top) / resolution);\n}\n"],"names":["Rectangle"],"mappings":";;;;;AAIA,SAAS,QAAA,CAAS,IAAyB,EAAA,KAAA,EAAe,CAC1D,EAAA;AACI,EAAS,KAAA,IAAA,CAAA,GAAI,CAAG,EAAA,KAAA,GAAQ,CAAI,GAAA,CAAA,GAAI,KAAO,EAAA,CAAA,GAAI,KAAO,EAAA,EAAE,CAAG,EAAA,KAAA,IAAS,CAChE,EAAA;AACI,IAAI,IAAA,IAAA,CAAK,KAAQ,GAAA,CAAC,CAAM,KAAA,CAAA;AAAG,MAAO,OAAA,KAAA,CAAA;AAAA,GACtC;AAEA,EAAO,OAAA,IAAA,CAAA;AACX,CAAA;AAEA,SAAS,WAAY,CAAA,IAAA,EAAyB,KAAe,EAAA,CAAA,EAAW,KAAa,MACrF,EAAA;AACI,EAAA,MAAM,SAAS,CAAI,GAAA,KAAA,CAAA;AAEnB,EAAA,KAAA,IAAS,CAAI,GAAA,GAAA,EAAK,KAAS,GAAA,GAAA,GAAM,MAAW,GAAA,CAAA,GAAI,CAAI,EAAA,CAAA,IAAK,MAAQ,EAAA,EAAE,CAAG,EAAA,KAAA,IAAS,MAC/E,EAAA;AACI,IAAI,IAAA,IAAA,CAAK,KAAQ,GAAA,CAAC,CAAM,KAAA,CAAA;AAAG,MAAO,OAAA,KAAA,CAAA;AAAA,GACtC;AAEA,EAAO,OAAA,IAAA,CAAA;AACX,CAAA;AAUgB,SAAA,oBAAA,CAAqB,MAAiB,EAAA,UAAA,GAAa,CACnE,EAAA;AAGI,EAAM,MAAA,EAAE,KAAO,EAAA,MAAA,EAAW,GAAA,MAAA,CAAA;AAE1B,EAAM,MAAA,OAAA,GAAU,MAAO,CAAA,UAAA,CAAW,IAAM,EAAA;AAAA,IACpC,kBAAoB,EAAA,IAAA;AAAA,GACvB,CAAA,CAAA;AAED,EAAA,IAAI,YAAY,IAChB,EAAA;AACI,IAAM,MAAA,IAAI,UAAU,iCAAiC,CAAA,CAAA;AAAA,GACzD;AAEA,EAAA,MAAM,YAAY,OAAQ,CAAA,YAAA,CAAa,CAAG,EAAA,CAAA,EAAG,OAAO,MAAM,CAAA,CAAA;AAC1D,EAAA,MAAM,OAAO,SAAU,CAAA,IAAA,CAAA;AAEvB,EAAA,IAAI,IAAO,GAAA,CAAA,CAAA;AACX,EAAA,IAAI,GAAM,GAAA,CAAA,CAAA;AACV,EAAA,IAAI,QAAQ,KAAQ,GAAA,CAAA,CAAA;AACpB,EAAA,IAAI,SAAS,MAAS,GAAA,CAAA,CAAA;AAEtB,EAAA,OAAO,GAAM,GAAA,MAAA,IAAU,QAAS,CAAA,IAAA,EAAM,OAAO,GAAG,CAAA;AAAG,IAAE,EAAA,GAAA,CAAA;AACrD,EAAA,IAAI,GAAQ,KAAA,MAAA;AAAQ,IAAA,OAAOA,mBAAU,CAAA,KAAA,CAAA;AACrC,EAAO,OAAA,QAAA,CAAS,IAAM,EAAA,KAAA,EAAO,MAAM,CAAA;AAAG,IAAE,EAAA,MAAA,CAAA;AACxC,EAAA,OAAO,WAAY,CAAA,IAAA,EAAM,KAAO,EAAA,IAAA,EAAM,KAAK,MAAM,CAAA;AAAG,IAAE,EAAA,IAAA,CAAA;AACtD,EAAA,OAAO,WAAY,CAAA,IAAA,EAAM,KAAO,EAAA,KAAA,EAAO,KAAK,MAAM,CAAA;AAAG,IAAE,EAAA,KAAA,CAAA;AAEvD,EAAE,EAAA,KAAA,CAAA;AACF,EAAE,EAAA,MAAA,CAAA;AAEF,EAAO,OAAA,IAAIA,mBAAU,CAAA,IAAA,GAAO,UAAY,EAAA,GAAA,GAAM,UAAa,EAAA,CAAA,KAAA,GAAQ,IAAQ,IAAA,UAAA,EAAA,CAAa,MAAS,GAAA,GAAA,IAAO,UAAU,CAAA,CAAA;AACtH;;;;"}

View File

@@ -0,0 +1,49 @@
import { Rectangle } from '../../maths/shapes/Rectangle.mjs';
"use strict";
function checkRow(data, width, y) {
for (let x = 0, index = 4 * y * width; x < width; ++x, index += 4) {
if (data[index + 3] !== 0)
return false;
}
return true;
}
function checkColumn(data, width, x, top, bottom) {
const stride = 4 * width;
for (let y = top, index = top * stride + 4 * x; y <= bottom; ++y, index += stride) {
if (data[index + 3] !== 0)
return false;
}
return true;
}
function getCanvasBoundingBox(canvas, resolution = 1) {
const { width, height } = canvas;
const context = canvas.getContext("2d", {
willReadFrequently: true
});
if (context === null) {
throw new TypeError("Failed to get canvas 2D context");
}
const imageData = context.getImageData(0, 0, width, height);
const data = imageData.data;
let left = 0;
let top = 0;
let right = width - 1;
let bottom = height - 1;
while (top < height && checkRow(data, width, top))
++top;
if (top === height)
return Rectangle.EMPTY;
while (checkRow(data, width, bottom))
--bottom;
while (checkColumn(data, width, left, top, bottom))
++left;
while (checkColumn(data, width, right, top, bottom))
--right;
++right;
++bottom;
return new Rectangle(left / resolution, top / resolution, (right - left) / resolution, (bottom - top) / resolution);
}
export { getCanvasBoundingBox };
//# sourceMappingURL=getCanvasBoundingBox.mjs.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"getCanvasBoundingBox.mjs","sources":["../../../src/utils/canvas/getCanvasBoundingBox.ts"],"sourcesContent":["import { Rectangle } from '../../maths/shapes/Rectangle';\n\nimport type { ICanvas } from '../../environment/canvas/ICanvas';\n\nfunction checkRow(data: Uint8ClampedArray, width: number, y: number)\n{\n for (let x = 0, index = 4 * y * width; x < width; ++x, index += 4)\n {\n if (data[index + 3] !== 0) return false;\n }\n\n return true;\n}\n\nfunction checkColumn(data: Uint8ClampedArray, width: number, x: number, top: number, bottom: number)\n{\n const stride = 4 * width;\n\n for (let y = top, index = (top * stride) + (4 * x); y <= bottom; ++y, index += stride)\n {\n if (data[index + 3] !== 0) return false;\n }\n\n return true;\n}\n\n/**\n * Measuring the bounds of a canvas' visible (non-transparent) pixels.\n * @param canvas - The canvas to measure.\n * @param resolution - The resolution of the canvas.\n * @returns The bounding box of the canvas' visible pixels.\n * @since 7.1.0\n * @memberof utils\n */\nexport function getCanvasBoundingBox(canvas: ICanvas, resolution = 1): Rectangle\n{\n // https://gist.github.com/timdown/021d9c8f2aabc7092df564996f5afbbf\n\n const { width, height } = canvas;\n\n const context = canvas.getContext('2d', {\n willReadFrequently: true,\n });\n\n if (context === null)\n {\n throw new TypeError('Failed to get canvas 2D context');\n }\n\n const imageData = context.getImageData(0, 0, width, height);\n const data = imageData.data;\n\n let left = 0;\n let top = 0;\n let right = width - 1;\n let bottom = height - 1;\n\n while (top < height && checkRow(data, width, top)) ++top;\n if (top === height) return Rectangle.EMPTY;\n while (checkRow(data, width, bottom)) --bottom;\n while (checkColumn(data, width, left, top, bottom)) ++left;\n while (checkColumn(data, width, right, top, bottom)) --right;\n\n ++right;\n ++bottom;\n\n return new Rectangle(left / resolution, top / resolution, (right - left) / resolution, (bottom - top) / resolution);\n}\n"],"names":[],"mappings":";;;AAIA,SAAS,QAAA,CAAS,IAAyB,EAAA,KAAA,EAAe,CAC1D,EAAA;AACI,EAAS,KAAA,IAAA,CAAA,GAAI,CAAG,EAAA,KAAA,GAAQ,CAAI,GAAA,CAAA,GAAI,KAAO,EAAA,CAAA,GAAI,KAAO,EAAA,EAAE,CAAG,EAAA,KAAA,IAAS,CAChE,EAAA;AACI,IAAI,IAAA,IAAA,CAAK,KAAQ,GAAA,CAAC,CAAM,KAAA,CAAA;AAAG,MAAO,OAAA,KAAA,CAAA;AAAA,GACtC;AAEA,EAAO,OAAA,IAAA,CAAA;AACX,CAAA;AAEA,SAAS,WAAY,CAAA,IAAA,EAAyB,KAAe,EAAA,CAAA,EAAW,KAAa,MACrF,EAAA;AACI,EAAA,MAAM,SAAS,CAAI,GAAA,KAAA,CAAA;AAEnB,EAAA,KAAA,IAAS,CAAI,GAAA,GAAA,EAAK,KAAS,GAAA,GAAA,GAAM,MAAW,GAAA,CAAA,GAAI,CAAI,EAAA,CAAA,IAAK,MAAQ,EAAA,EAAE,CAAG,EAAA,KAAA,IAAS,MAC/E,EAAA;AACI,IAAI,IAAA,IAAA,CAAK,KAAQ,GAAA,CAAC,CAAM,KAAA,CAAA;AAAG,MAAO,OAAA,KAAA,CAAA;AAAA,GACtC;AAEA,EAAO,OAAA,IAAA,CAAA;AACX,CAAA;AAUgB,SAAA,oBAAA,CAAqB,MAAiB,EAAA,UAAA,GAAa,CACnE,EAAA;AAGI,EAAM,MAAA,EAAE,KAAO,EAAA,MAAA,EAAW,GAAA,MAAA,CAAA;AAE1B,EAAM,MAAA,OAAA,GAAU,MAAO,CAAA,UAAA,CAAW,IAAM,EAAA;AAAA,IACpC,kBAAoB,EAAA,IAAA;AAAA,GACvB,CAAA,CAAA;AAED,EAAA,IAAI,YAAY,IAChB,EAAA;AACI,IAAM,MAAA,IAAI,UAAU,iCAAiC,CAAA,CAAA;AAAA,GACzD;AAEA,EAAA,MAAM,YAAY,OAAQ,CAAA,YAAA,CAAa,CAAG,EAAA,CAAA,EAAG,OAAO,MAAM,CAAA,CAAA;AAC1D,EAAA,MAAM,OAAO,SAAU,CAAA,IAAA,CAAA;AAEvB,EAAA,IAAI,IAAO,GAAA,CAAA,CAAA;AACX,EAAA,IAAI,GAAM,GAAA,CAAA,CAAA;AACV,EAAA,IAAI,QAAQ,KAAQ,GAAA,CAAA,CAAA;AACpB,EAAA,IAAI,SAAS,MAAS,GAAA,CAAA,CAAA;AAEtB,EAAA,OAAO,GAAM,GAAA,MAAA,IAAU,QAAS,CAAA,IAAA,EAAM,OAAO,GAAG,CAAA;AAAG,IAAE,EAAA,GAAA,CAAA;AACrD,EAAA,IAAI,GAAQ,KAAA,MAAA;AAAQ,IAAA,OAAO,SAAU,CAAA,KAAA,CAAA;AACrC,EAAO,OAAA,QAAA,CAAS,IAAM,EAAA,KAAA,EAAO,MAAM,CAAA;AAAG,IAAE,EAAA,MAAA,CAAA;AACxC,EAAA,OAAO,WAAY,CAAA,IAAA,EAAM,KAAO,EAAA,IAAA,EAAM,KAAK,MAAM,CAAA;AAAG,IAAE,EAAA,IAAA,CAAA;AACtD,EAAA,OAAO,WAAY,CAAA,IAAA,EAAM,KAAO,EAAA,KAAA,EAAO,KAAK,MAAM,CAAA;AAAG,IAAE,EAAA,KAAA,CAAA;AAEvD,EAAE,EAAA,KAAA,CAAA;AACF,EAAE,EAAA,MAAA,CAAA;AAEF,EAAO,OAAA,IAAI,SAAU,CAAA,IAAA,GAAO,UAAY,EAAA,GAAA,GAAM,UAAa,EAAA,CAAA,KAAA,GAAQ,IAAQ,IAAA,UAAA,EAAA,CAAa,MAAS,GAAA,GAAA,IAAO,UAAU,CAAA,CAAA;AACtH;;;;"}