You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(
originalImg,
padding = 20, // Base padding (top, left, right) in pixels
bottomPaddingFactor = 3, // Multiplier for bottom padding relative to 'padding'
frameColor = "#f8f8f8", // Color of the Polaroid frame
frameCornerRadius = 8, // Corner radius for the frame
imageCornerRadius = 2, // Corner radius for the actual image
// Vintage filter effects parameters
sepia = 0.20, // Sepia amount (0 to 1, e.g., 0.2 for 20%)
contrast = 0.90, // Contrast (0 to 2+, 1 is original, e.g., 0.9 for 90%)
brightness = 1.10, // Brightness (0 to 2+, 1 is original, e.g., 1.1 for 110%)
saturation = 0.90, // Saturation (0 to 2+, 1 is original, e.g., 0.9 for 90%)
// Shadow effects parameters
addShadow = 1, // 0 for no shadow, 1 for shadow
shadowColor = "rgba(0,0,0,0.25)", // Color of the shadow
shadowBlur = 15, // Blur radius for the shadow
shadowOffsetX = 5, // Horizontal offset of the shadow
shadowOffsetY = 7 // Vertical offset of the shadow
) {
// Helper function to draw a rounded rectangle
function _drawRoundedRect(ctx, x, y, width, height, radius) {
radius = Number(radius); // Ensure radius is a number
radius = Math.max(0, radius); // Ensure radius is not negative
// Clamp radius to half of the shortest side if necessary
if (width < 2 * radius) radius = width / 2;
if (height < 2 * radius) radius = height / 2;
// Prevent issues if width/height are 0 or negative
if (width <=0 || height <= 0) {
ctx.beginPath(); // create an empty path
ctx.rect(x,y,width,height); // This will draw nothing or a line if one dim is 0
ctx.closePath();
return;
}
ctx.beginPath();
ctx.moveTo(x + radius, y);
ctx.arcTo(x + width, y, x + width, y + height, radius);
ctx.arcTo(x + width, y + height, x, y + height, radius);
ctx.arcTo(x, y + height, x, y, radius);
ctx.arcTo(x, y, x + width, y, radius);
ctx.closePath();
}
if (!originalImg || typeof originalImg.width === 'undefined' || originalImg.width === 0 || originalImg.height === 0) {
console.error("processImage: Invalid image input. Ensure the image is loaded and has dimensions.");
const errorCanvas = document.createElement('canvas');
errorCanvas.width = 200;
errorCanvas.height = 100;
const errCtx = errorCanvas.getContext('2d');
errCtx.fillStyle = '#dddddd'; // Light grey background for error message
errCtx.fillRect(0,0,200,100);
errCtx.fillStyle = 'red';
errCtx.textAlign = 'center';
errCtx.textBaseline = 'middle';
errCtx.font = '12px Arial';
errCtx.fillText('Error: Invalid Image Input', 100, 50);
return errorCanvas;
}
const imgW = originalImg.width;
const imgH = originalImg.height;
// Ensure critical numeric parameters are numbers
const numPadding = Number(padding);
const numBottomPaddingFactor = Number(bottomPaddingFactor);
const pT = numPadding;
const pL = numPadding;
const pR = numPadding;
const pB = numPadding * numBottomPaddingFactor;
const frameWidth = imgW + pL + pR;
const frameHeight = imgH + pT + pB;
const actualAddShadow = (Number(addShadow) === 1);
const sOffsetX = actualAddShadow ? Number(shadowOffsetX) : 0;
const sOffsetY = actualAddShadow ? Number(shadowOffsetY) : 0;
const sBlur = actualAddShadow ? Math.max(0, Number(shadowBlur)) : 0; // Blur must be non-negative
let overall_min_x = 0, overall_max_x = frameWidth;
let overall_min_y = 0, overall_max_y = frameHeight;
if (actualAddShadow) {
// Calculate bounding box including shadow
overall_min_x = Math.min(0, sOffsetX - sBlur);
overall_max_x = Math.max(frameWidth, frameWidth + sOffsetX + sBlur);
overall_min_y = Math.min(0, sOffsetY - sBlur);
overall_max_y = Math.max(frameHeight, frameHeight + sOffsetY + sBlur);
}
const canvasWidth = overall_max_x - overall_min_x;
const canvasHeight = overall_max_y - overall_min_y;
// Frame's top-left drawing position on the canvas
const frameActualDrawX = -overall_min_x;
const frameActualDrawY = -overall_min_y;
const canvas = document.createElement('canvas');
canvas.width = Math.max(1, canvasWidth); // Ensure canvas has at least 1x1 size
canvas.height = Math.max(1, canvasHeight);
const ctx = canvas.getContext('2d');
// Draw shadow for the frame
if (actualAddShadow) {
ctx.shadowColor = String(shadowColor);
ctx.shadowBlur = sBlur;
ctx.shadowOffsetX = sOffsetX;
ctx.shadowOffsetY = sOffsetY;
}
// Draw the frame
ctx.fillStyle = String(frameColor);
const fcr = Number(frameCornerRadius);
if (fcr > 0 && frameWidth > 0 && frameHeight > 0) { // Only draw rounded rect if dimensions are positive
_drawRoundedRect(ctx, frameActualDrawX, frameActualDrawY, frameWidth, frameHeight, fcr);
ctx.fill();
} else {
ctx.fillRect(frameActualDrawX, frameActualDrawY, frameWidth, frameHeight);
}
// Clear shadow for drawing the image and subsequent operations
if (actualAddShadow) {
ctx.shadowColor = 'transparent'; // More robust than setting all to 0
ctx.shadowBlur = 0;
ctx.shadowOffsetX = 0;
ctx.shadowOffsetY = 0;
}
// Prepare image filters
let filterValues = [];
const numSepia = Number(sepia);
const numContrast = Number(contrast);
const numBrightness = Number(brightness);
const numSaturation = Number(saturation);
if (numSepia !== 0) filterValues.push(`sepia(${numSepia})`);
if (numContrast !== 1) filterValues.push(`contrast(${numContrast})`);
if (numBrightness !== 1) filterValues.push(`brightness(${numBrightness})`);
if (numSaturation !== 1) filterValues.push(`saturate(${numSaturation})`);
if (filterValues.length > 0) {
ctx.filter = filterValues.join(' ');
}
// Calculate image drawing position
const imgDrawX = frameActualDrawX + pL;
const imgDrawY = frameActualDrawY + pT;
// Draw the image, potentially clipped with rounded corners
// Ensure image dimensions are positive before attempting to draw or clip
if (imgW > 0 && imgH > 0) {
const icr = Number(imageCornerRadius);
if (icr > 0) {
ctx.save();
_drawRoundedRect(ctx, imgDrawX, imgDrawY, imgW, imgH, icr);
ctx.clip();
ctx.drawImage(originalImg, imgDrawX, imgDrawY, imgW, imgH);
ctx.restore();
} else {
ctx.drawImage(originalImg, imgDrawX, imgDrawY, imgW, imgH);
}
}
// Reset filter to prevent affecting other drawings if canvas is reused
ctx.filter = 'none';
return canvas;
}
Apply Changes