You can edit the below JavaScript code to customize the image tool.
function processImage(originalImg, cellSize = 30, lineWidth = 2, lineColor = "gray", lineOpacity = 0.7, linkStyle = "dots", dotColor = "darkgray", dotOpacity = 0.8, dotSizeFactor = 2) {
const canvas = document.createElement('canvas');
const W = originalImg.width;
const H = originalImg.height;
canvas.width = W;
canvas.height = H;
if (W === 0 || H === 0) { // Handle zero-dimension images
return canvas;
}
const ctx = canvas.getContext('2d');
// Draw the original image
ctx.drawImage(originalImg, 0, 0, W, H);
// Helper function to remove duplicate points using a Set for unique keys
// and sort them to ensure consistent line drawing order.
function _removeDuplicatePoints(points) {
if (points.length < 2) return points;
const unique = [];
const seenKeys = new Set();
for (const p of points) {
// Quantize to handle floating point inaccuracies, especially at corners
const key = `${p.x.toFixed(3)},${p.y.toFixed(3)}`;
if (!seenKeys.has(key)) {
unique.push(p);
seenKeys.add(key);
}
}
// Sort points by x, then by y
unique.sort((a, b) => {
if (Math.abs(a.x - b.x) > 1e-4) return a.x - b.x; // Compare with tolerance for float
if (Math.abs(a.y - b.y) > 1e-4) return a.y - b.y;
return 0;
});
return unique;
}
// cellSize is the perpendicular distance between parallel wires.
// spacingConstant is the shift along the x or y axis for the line equation constant.
const spacingConstant = cellSize * Math.sqrt(2);
ctx.lineWidth = lineWidth;
const originalGlobalAlpha = ctx.globalAlpha; // Save current globalAlpha
// --- Draw lines ---
ctx.strokeStyle = lineColor;
ctx.globalAlpha = lineOpacity;
// Family 1: lines of the form x + y = k
// k ranges from 0 (passing through origin) to W+H (passing through W,H)
ctx.beginPath();
// Iterate kVal. Start slightly before 0 and end slightly after W+H to ensure coverage.
// The loop starts from `kValInit1` and goes up to `kValEnd1`.
const kValInit1 = Math.min(0, W + H) - spacingConstant; // Ensure it covers from a bit less than smallest sum
const kValEnd1 = Math.max(0, W + H) + spacingConstant; // To a bit more than largest sum
for (let kVal = kValInit1; kVal <= kValEnd1; kVal += spacingConstant) {
const pts = [];
// Intersection with y-axis (x=0): y = kVal. Point (0, kVal)
if (kVal >= -lineWidth && kVal <= H + lineWidth) pts.push({ x: 0, y: kVal });
// Intersection with x-axis (y=0): x = kVal. Point (kVal, 0)
if (kVal >= -lineWidth && kVal <= W + lineWidth) pts.push({ x: kVal, y: 0 });
// Intersection with x=W: y = kVal - W. Point (W, kVal - W)
if ((kVal - W) >= -lineWidth && (kVal - W) <= H + lineWidth) pts.push({ x: W, y: kVal - W });
// Intersection with y=H: x = kVal - H. Point (kVal - H, H)
if ((kVal - H) >= -lineWidth && (kVal - H) <= W + lineWidth) pts.push({ x: kVal - H, y: H });
const validPts = pts.filter(p =>
p.x >= -lineWidth && p.x <= W + lineWidth && p.y >= -lineWidth && p.y <= H + lineWidth
);
const uniquePts = _removeDuplicatePoints(validPts);
if (uniquePts.length >= 2) {
// Draw line between the first and last points (covers cases where line might be on edge)
ctx.moveTo(uniquePts[0].x, uniquePts[0].y);
ctx.lineTo(uniquePts[uniquePts.length - 1].x, uniquePts[uniquePts.length - 1].y);
}
}
ctx.stroke();
// Family 2: lines of the form x - y = k (or y - x = -k)
// k ranges from 0-H = -H (passing through 0,H) to W-0 = W (passing through W,0)
ctx.beginPath();
const kValInit2 = Math.min(-H, W) - spacingConstant;
const kValEnd2 = Math.max(-H, W) + spacingConstant;
for (let kVal = kValInit2; kVal <= kValEnd2; kVal += spacingConstant) {
const pts = [];
// Intersection with y-axis (x=0): y = -kVal. Point (0, -kVal)
if ((-kVal) >= -lineWidth && (-kVal) <= H + lineWidth) pts.push({ x: 0, y: -kVal });
// Intersection with x-axis (y=0): x = kVal. Point (kVal, 0)
if (kVal >= -lineWidth && kVal <= W + lineWidth) pts.push({ x: kVal, y: 0 });
// Intersection with x=W: y = W - kVal. Point (W, W - kVal)
if ((W - kVal) >= -lineWidth && (W - kVal) <= H + lineWidth) pts.push({ x: W, y: W - kVal });
// Intersection with y=H: x = kVal + H. Point (kVal + H, H)
if ((kVal + H) >= -lineWidth && (kVal + H) <= W + lineWidth) pts.push({ x: kVal + H, y: H });
const validPts = pts.filter(p =>
p.x >= -lineWidth && p.x <= W + lineWidth && p.y >= -lineWidth && p.y <= H + lineWidth
);
const uniquePts = _removeDuplicatePoints(validPts);
if (uniquePts.length >= 2) {
ctx.moveTo(uniquePts[0].x, uniquePts[0].y);
ctx.lineTo(uniquePts[uniquePts.length-1].x, uniquePts[uniquePts.length-1].y);
}
}
ctx.stroke();
// --- Draw intersection dots if specified ---
if (linkStyle === "dots" && lineWidth > 0) { // Also ensure lineWidth is positive for dotSize calc
ctx.fillStyle = dotColor;
ctx.globalAlpha = dotOpacity;
const dotDiameter = lineWidth * dotSizeFactor;
const dotRadius = dotDiameter / 2;
if (dotRadius > 0) { // Only draw dots if they have a positive size
const k1_values = [];
for (let kVal = kValInit1; kVal <= kValEnd1; kVal += spacingConstant) {
k1_values.push(kVal);
}
const k2_values = [];
for (let kVal = kValInit2; kVal <= kValEnd2; kVal += spacingConstant) {
k2_values.push(kVal);
}
k1_values.forEach(k1 => {
k2_values.forEach(k2 => {
// Intersection of x+y=k1 and x-y=k2
const intersectX = (k1 + k2) / 2;
const intersectY = (k1 - k2) / 2;
// Check if intersection is within canvas bounds (or close enough for dot to be visible)
if (intersectX >= -dotRadius && intersectX <= W + dotRadius &&
intersectY >= -dotRadius && intersectY <= H + dotRadius) {
ctx.beginPath();
ctx.arc(intersectX, intersectY, dotRadius, 0, 2 * Math.PI);
ctx.fill();
}
});
});
}
}
// Restore original globalAlpha
ctx.globalAlpha = originalGlobalAlpha;
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 Chain Link Fence Filter Effect Tool allows users to apply a unique chain link fence effect to images. This effect creates a pattern of overlapping lines and optional dots, mimicking the appearance of a chain link fence. Users can customize various parameters, including the size of the cells in the pattern, the color and opacity of the lines, as well as the style and appearance of the dots. This tool can be used for artistic purposes, graphic design, or to add textured effects to images, making it ideal for artists, designers, and anyone looking to creatively enhance their photos.