You can edit the below JavaScript code to customize the image tool.
function processImage(originalImg, stripWidth = 8, spacing = 2, shadowIntensity = 0.3, gapColorStr = "0,0,0,0") {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const imgWidth = originalImg.naturalWidth || originalImg.width;
const imgHeight = originalImg.naturalHeight || originalImg.height;
canvas.width = imgWidth;
canvas.height = imgHeight;
// Draw original image to a temporary canvas to get pixel data
// This is necessary because we need pixel access, and originalImg might be an HTMLImageElement
// not yet on a canvas or from a different origin (tainting canvas if drawn directly).
// Assuming originalImg is loaded and accessible.
const tempCanvas = document.createElement('canvas');
const tempCtx = tempCanvas.getContext('2d');
tempCanvas.width = imgWidth;
tempCanvas.height = imgHeight;
tempCtx.drawImage(originalImg, 0, 0, imgWidth, imgHeight);
const imageData = tempCtx.getImageData(0, 0, imgWidth, imgHeight);
const sourcePixels = imageData.data;
const outputImageData = ctx.createImageData(imgWidth, imgHeight);
const destPixels = outputImageData.data;
// Parameter parsing and validation
let sw = Number(stripWidth);
let sp = Number(spacing);
let sh = Number(shadowIntensity);
// Validate and set defaults if necessary
sw = (!isNaN(sw) && sw > 0) ? Math.floor(sw) : 8;
sp = (!isNaN(sp) && sp >= 0) ? Math.floor(sp) : 2;
sh = (!isNaN(sh)) ? Math.max(0, Math.min(1, sh)) : 0.3;
let gapR = 0, gapG = 0, gapB = 0, gapA = 0; // Default: transparent black
if (typeof gapColorStr === 'string') {
const loweredGapColorStr = gapColorStr.toLowerCase().trim();
if (loweredGapColorStr === 'transparent') {
gapR = 0; gapG = 0; gapB = 0; gapA = 0;
} else {
const parts = loweredGapColorStr.split(',').map(s => Number(s.trim()));
if ((parts.length === 3 || parts.length === 4) && parts.every(p => !isNaN(p))) {
gapR = Math.max(0, Math.min(255, Math.floor(parts[0])));
gapG = Math.max(0, Math.min(255, Math.floor(parts[1])));
gapB = Math.max(0, Math.min(255, Math.floor(parts[2])));
gapA = (parts.length === 4) ? Math.max(0, Math.min(255, Math.floor(parts[3]))) : 255; // Default alpha to opaque for RGB
}
// If parsing fails, it remains transparent black by default initialization
}
}
const period = sw + sp;
// If strip width is 0 (after potential bad input that bypasses initial default)
// or period is 0 (e.g. sw=0, sp=0), drawing original might be best.
// sw is validated to be > 0 and sp >=0, so period will be > 0.
for (let y = 0; y < imgHeight; y++) {
for (let x = 0; x < imgWidth; x++) {
const idx = (y * imgWidth + x) * 4;
const sR = sourcePixels[idx];
const sG = sourcePixels[idx + 1];
const sB = sourcePixels[idx + 2];
const sA = sourcePixels[idx + 3];
let destR, destG, destB, destA;
const isPixelInHorizStripBand = (y % period) < sw;
const isPixelInVertStripBand = (x % period) < sw;
const cellX = Math.floor(x / period);
const cellY = Math.floor(y / period);
const horizThreadsAreTopInCell = (cellX + cellY) % 2 === 0;
if (isPixelInHorizStripBand && horizThreadsAreTopInCell) {
// Case 1: Horizontal thread is "on top" in this cell and pixel is in its band.
destR = sR; destG = sG; destB = sB; destA = sA;
} else if (isPixelInVertStripBand && !horizThreadsAreTopInCell) {
// Case 2: Vertical thread is "on top" in this cell and pixel is in its band.
destR = sR; destG = sG; destB = sB; destA = sA;
} else if (isPixelInHorizStripBand && !horizThreadsAreTopInCell) {
// Case 3: Horizontal thread is present, but it's an "under" segment in this cell
// (because vertical threads are "on top" type for this cell).
// This shows if the "on top" vertical thread is gapped here.
destR = sR * (1 - sh);
destG = sG * (1 - sh);
destB = sB * (1 - sh);
destA = sA;
} else if (isPixelInVertStripBand && horizThreadsAreTopInCell) {
// Case 4: Vertical thread is present, but it's an "under" segment in this cell
// (because horizontal threads are "on top" type for this cell).
// This shows if the "on top" horizontal thread is gapped here.
destR = sR * (1 - sh);
destG = sG * (1 - sh);
destB = sB * (1 - sh);
destA = sA;
} else {
// Case 5: Pixel is in a gap (neither horizontal nor vertical strip covers it according to priorities)
// This occurs if sp > 0 and pixel falls into !isPixelInHorizStripBand AND !isPixelInVertStripBand.
if (sp > 0) { // A true gap pixel due to spacing
destR = gapR; destG = gapG; destB = gapB; destA = gapA;
} else { // Should not happen if sp = 0 unless sw became 0 somehow.
// Default to original color as a fallback.
destR = sR; destG = sG; destB = sB; destA = sA;
}
}
destPixels[idx] = destR;
destPixels[idx + 1] = destG;
destPixels[idx + 2] = destB;
destPixels[idx + 3] = destA;
}
}
ctx.putImageData(outputImageData, 0, 0);
return canvas;
}
Free Image Tool Creator
Can't find the image tool you're looking for? Create one based on your own needs now!
The Image Weave Pattern Filter Effect Tool allows users to apply a unique weaving pattern effect to their images. By adjusting parameters such as strip width, spacing, and shadow intensity, users can create visually striking designs that blend horizontal and vertical stripes into their original images. This tool is ideal for graphic designers, artists, and anyone looking to enhance images for creative projects, social media, or digital artwork. The weaving effect can add depth and texture, making it a versatile option for both personal and professional use.