You can edit the below JavaScript code to customize the image tool.
function processImage(originalImg, dotRadius = 1, density = 30, spraySpread = 10) {
const width = originalImg.naturalWidth || originalImg.width;
const height = originalImg.naturalHeight || originalImg.height;
const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
// The output canvas context doesn't necessarily need willReadFrequently,
// as it's primarily being written to.
const ctx = canvas.getContext('2d');
if (width === 0 || height === 0) {
// If the image has no dimensions (e.g., not loaded or invalid),
// return the canvas, which will be 0x0 or Wx0 / 0xH.
return canvas;
}
// Create a temporary canvas to get pixel data from the original image.
// This avoids repeated getImageData calls on the main context if we were to sample per pixel.
const tempCanvas = document.createElement('canvas');
tempCanvas.width = width;
tempCanvas.height = height;
// Hint that this canvas will be read from frequently (actually, once, but potentially large data).
const tempCtx = tempCanvas.getContext('2d', { willReadFrequently: true });
try {
tempCtx.drawImage(originalImg, 0, 0, width, height);
} catch (e) {
console.error("Error drawing original image to temporary canvas:", e);
// Fallback: return an empty canvas of the correct size.
// Alternatively, could try to draw originalImg to ctx and return, but if it failed here, it might fail there too.
return canvas;
}
let originalPixelData;
try {
originalPixelData = tempCtx.getImageData(0, 0, width, height).data;
} catch (e) {
console.error("Error getting image data (possibly due to cross-origin restrictions):", e);
// Fallback: draw the original image onto the main canvas and return that.
// This might still be useful even if pixel manipulation failed.
try {
ctx.drawImage(originalImg, 0, 0, width, height);
} catch (drawError) {
console.error("Error drawing original image to output canvas after getImageData failed:", drawError);
// If all fails, the blank canvas is returned.
}
return canvas;
}
// Optional: Fill background if transparency is not desired.
// By default, the canvas background is transparent.
// Example for a white background:
// ctx.fillStyle = 'white';
// ctx.fillRect(0, 0, width, height);
// Determine the step for iterating over the image for spray centers.
// A smaller step means more spray centers and a denser, more detailed effect, but slower.
// This step is based on spraySpread to adapt sampling density.
const step = Math.max(1, Math.floor(spraySpread / 3));
for (let y = 0; y < height; y += step) {
for (let x = 0; x < width; x += step) {
// current x, y are spray centers, guaranteed to be integers due to step calculation.
const pixelIndex = (y * width + x) * 4; // Each pixel has 4 components (R,G,B,A)
const r = originalPixelData[pixelIndex];
const g = originalPixelData[pixelIndex + 1];
const b = originalPixelData[pixelIndex + 2];
const a = originalPixelData[pixelIndex + 3];
// Optimization: if source pixel is fully transparent, skip spraying "transparent" dots.
// Spraying with alpha=0 has no visual effect on a blank/transparent canvas.
if (a === 0 && dotRadius > 0) {
continue;
}
ctx.fillStyle = `rgba(${r},${g},${b},${a / 255})`;
// Spray 'density' number of dots for the current spray center (x,y)
for (let i = 0; i < density; i++) {
// If dotRadius is invalid, no dots can be drawn for this center.
if (dotRadius <= 0) {
break; // Exit density loop for this (x,y) center
}
const angle = Math.random() * 2 * Math.PI;
// Use Math.sqrt(Math.random()) for radius to ensure uniform dot distribution over the circular area.
// Math.random() alone would cluster dots towards the edge of the spray circle.
const radiusOffset = Math.sqrt(Math.random()) * spraySpread;
const dotX = x + radiusOffset * Math.cos(angle);
const dotY = y + radiusOffset * Math.sin(angle);
ctx.beginPath();
// arc(centerX, centerY, radius, startAngle, endAngle_radians)
ctx.arc(dotX, dotY, dotRadius, 0, 2 * Math.PI);
ctx.fill();
}
}
}
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 Spray Paint Filter Effect Tool allows users to apply a spray paint effect to their images, simulating a tactile, artistic finish. By adjusting parameters such as dot radius, density of the spray, and spray spread, users can create unique visual styles that resemble traditional spray painting. This tool is ideal for artists, graphic designers, or anyone looking to add a creative touch to digital images, making it suitable for use in personal projects, social media posts, or digital art creations.