You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, stitchSizeStr = "12", colorsCountStr = "8") {
// Parse parameters
const stitchSize = Math.max(4, parseInt(stitchSizeStr, 10)) || 12;
const colorsCount = Math.max(2, parseInt(colorsCountStr, 10)) || 8;
// Get dimensions based on multiple of stitch size to prevent cutoff
const width = originalImg.width;
const height = originalImg.height;
const cols = Math.floor(width / stitchSize);
const rows = Math.floor(height / stitchSize);
// Create the output canvas
const canvas = document.createElement('canvas');
canvas.width = cols * stitchSize;
canvas.height = rows * stitchSize;
const ctx = canvas.getContext('2d');
// Create a temporary canvas to read original pixel data
const tempCanvas = document.createElement('canvas');
tempCanvas.width = width;
tempCanvas.height = height;
const tempCtx = tempCanvas.getContext('2d');
tempCtx.drawImage(originalImg, 0, 0);
let imgData;
try {
imgData = tempCtx.getImageData(0, 0, width, height).data;
} catch (e) {
// Fallback for CORS issues if originalImg is tainted
console.error("CORS error getting image data", e);
return canvas;
}
// Color quantization step
const step = 255 / (colorsCount - 1);
// Draw base dark background (simulate shadows between yarn)
ctx.fillStyle = '#111111';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Iterate through the grid to create the knitted pattern
for (let r = 0; r < rows; r++) {
for (let c = 0; c < cols; c++) {
const x = c * stitchSize;
const y = r * stitchSize;
// Calculate the average color of the current grid cell
let rSum = 0, gSum = 0, bSum = 0, count = 0;
for (let dy = 0; dy < stitchSize; dy++) {
for (let dx = 0; dx < stitchSize; dx++) {
const px = x + dx;
const py = y + dy;
const idx = (py * width + px) * 4;
rSum += imgData[idx];
gSum += imgData[idx + 1];
bSum += imgData[idx + 2];
count++;
}
}
let rAvg = rSum / count;
let gAvg = gSum / count;
let bAvg = bSum / count;
// Quantize to restrict palette and mimic dyed yarn colors
let rQuant = Math.round(Math.round(rAvg / step) * step);
let gQuant = Math.round(Math.round(gAvg / step) * step);
let bQuant = Math.round(Math.round(bAvg / step) * step);
// Draw a slightly darker tile background to simulate depth in the knit
ctx.fillStyle = `rgb(${rQuant * 0.6}, ${gQuant * 0.6}, ${bQuant * 0.6})`;
ctx.fillRect(x, y, stitchSize, stitchSize);
// Knit Stitch settings
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
// Helper function to draw the "V" shape of a knit stitch
const drawV = (offsetX, offsetY, strokeStyle, lineWidth) => {
ctx.beginPath();
// Left arm of the V
ctx.moveTo(x + stitchSize * 0.1 + offsetX, y + stitchSize * 0.05 + offsetY);
// Bottom point of the V
ctx.lineTo(x + stitchSize * 0.5 + offsetX, y + stitchSize * 0.95 + offsetY);
// Right arm of the V
ctx.lineTo(x + stitchSize * 0.9 + offsetX, y + stitchSize * 0.05 + offsetY);
ctx.strokeStyle = strokeStyle;
ctx.lineWidth = lineWidth;
ctx.stroke();
};
// 1. Drop shadow for 3D effect
drawV(0, stitchSize * 0.1, 'rgba(0, 0, 0, 0.4)', stitchSize * 0.45);
// 2. Main yarn color
drawV(0, 0, `rgb(${rQuant}, ${gQuant}, ${bQuant})`, stitchSize * 0.4);
// 3. Optional yarn highlight for texture and volume
drawV(0, -stitchSize * 0.05, 'rgba(255, 255, 255, 0.15)', stitchSize * 0.15);
}
}
return canvas;
}
Apply Changes