mirror of
https://github.com/sotam0316/drawNET.git
synced 2026-04-25 03:58:37 +09:00
Initial commit: drawNET Alpha v1.0 - Professional Topology Designer with Full i18n and Performance Optimizations
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
import { potrace, init } from 'https://cdn.jsdelivr.net/npm/esm-potrace-wasm@0.4.1/dist/index.js';
|
||||
import { logger } from '../utils/logger.js';
|
||||
|
||||
let isWasmInitialized = false;
|
||||
|
||||
/**
|
||||
* Image Tracing using WASM Potrace (High performance & quality)
|
||||
* @param {HTMLImageElement} imageElement
|
||||
* @param {Object} options
|
||||
*/
|
||||
export async function traceImage(imageElement, options = {}) {
|
||||
if (!isWasmInitialized) {
|
||||
await init();
|
||||
isWasmInitialized = true;
|
||||
}
|
||||
|
||||
// Ensure image is loaded
|
||||
if (imageElement instanceof HTMLImageElement && !imageElement.complete) {
|
||||
await new Promise(r => imageElement.onload = r);
|
||||
}
|
||||
|
||||
// --- Pre-process with Canvas for Thresholding ---
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = imageElement.naturalWidth || imageElement.width;
|
||||
canvas.height = imageElement.naturalHeight || imageElement.height;
|
||||
const ctx = canvas.getContext('2d');
|
||||
ctx.drawImage(imageElement, 0, 0);
|
||||
|
||||
const threshold = options.threshold !== undefined ? options.threshold : 128;
|
||||
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||
const data = imageData.data;
|
||||
|
||||
for (let i = 0; i < data.length; i += 4) {
|
||||
// Luminance calculation
|
||||
const brightness = 0.2126 * data[i] + 0.7152 * data[i + 1] + 0.0722 * data[i + 2];
|
||||
const v = brightness < threshold ? 0 : 255;
|
||||
data[i] = data[i+1] = data[i+2] = v;
|
||||
// Keep alpha as is or flatten to white?
|
||||
// For icons, if alpha is low, treat as white
|
||||
if (data[i+3] < 128) {
|
||||
data[i] = data[i+1] = data[i+2] = 255;
|
||||
data[i+3] = 255;
|
||||
}
|
||||
}
|
||||
ctx.putImageData(imageData, 0, 0);
|
||||
|
||||
// Potrace Options (WASM version)
|
||||
const potraceOptions = {
|
||||
turdsize: options.turdsize || 2,
|
||||
turnpolicy: options.turnpolicy || 4,
|
||||
alphamax: options.alphamax !== undefined ? options.alphamax : 1,
|
||||
opticurve: options.opticurve !== undefined ? options.opticurve : 1,
|
||||
opttolerance: options.opttolerance || 0.2
|
||||
};
|
||||
|
||||
try {
|
||||
// Pass the thresholded canvas instead of the original image
|
||||
const svgStr = await potrace(canvas, potraceOptions);
|
||||
return svgStr;
|
||||
} catch (err) {
|
||||
logger.critical("WASM Potrace Error:", err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a clean SVG string from path data
|
||||
* (Maintained for API compatibility, though WASM potrace returns full SVG)
|
||||
*/
|
||||
export function wrapAsSVG(svgData, width = 64, height = 64) {
|
||||
if (typeof svgData === 'string' && svgData.trim().startsWith('<svg')) {
|
||||
return svgData;
|
||||
}
|
||||
return `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}">
|
||||
${svgData}
|
||||
</svg>`;
|
||||
}
|
||||
Reference in New Issue
Block a user