You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
const originalWidth = originalImg.naturalWidth || originalImg.width;
const originalHeight = originalImg.naturalHeight || originalImg.height;
if (originalWidth === 0 || originalHeight === 0) {
// Return an empty or minimal canvas if image dimensions are invalid
canvas.width = 1;
canvas.height = 1;
return canvas;
}
// Set canvas dimensions to match the original image
canvas.width = originalWidth;
canvas.height = originalHeight;
const W = canvas.width;
const H = canvas.height;
// Heart path coordinates are based on a 200x200 reference grid.
// Points for the SVG path: M100,175 C40,130 40,70 100,25 C160,70 160,130 100,175 Z
// Min X: 40, Max X: 160 => Natural width of heart shape on grid: 120
// Min Y: 25, Max Y: 175 => Natural height of heart shape on grid: 150
const heartRefWidth = 200; // The path is defined within a 200x200 box
const heartRefHeight = 200;
// To preserve the heart's aspect ratio, scale it uniformly
const scale = Math.min(W / heartRefWidth, H / heartRefHeight);
// Effective size of the 200x200 reference box on canvas
const scaledHeartBoxWidth = heartRefWidth * scale;
const scaledHeartBoxHeight = heartRefHeight * scale;
// Calculate offsets to center the heart's reference box on the canvas
const offsetX = (W - scaledHeartBoxWidth) / 2;
const offsetY = (H - scaledHeartBoxHeight) / 2;
// Draw the heart path, scaled and offset
ctx.beginPath();
// M 100,175
ctx.moveTo(offsetX + 100 * scale, offsetY + 175 * scale);
// C 40,130 40,70 100,25
ctx.bezierCurveTo(
offsetX + 40 * scale, offsetY + 130 * scale, // Control Point 1
offsetX + 40 * scale, offsetY + 70 * scale, // Control Point 2
offsetX + 100 * scale, offsetY + 25 * scale // End Point
);
// C 160,70 160,130 100,175
ctx.bezierCurveTo(
offsetX + 160 * scale, offsetY + 70 * scale, // Control Point 1
offsetX + 160 * scale, offsetY + 130 * scale, // Control Point 2
offsetX + 100 * scale, offsetY + 175 * scale // End Point
);
ctx.closePath();
// Set the heart path as the clipping region
ctx.clip();
// Determine the actual bounding box of the drawn heart on the canvas
// (using natural extents of the heart shape: 120 wide, 150 tall, on the 200x200 grid)
const heartActualScaledWidth = 120 * scale;
const heartActualScaledHeight = 150 * scale;
// Top-left corner of this bounding box relative to (offsetX, offsetY)
const heartActualBoxOffsetX = 40 * scale;
const heartActualBoxOffsetY = 25 * scale;
// Absolute coordinates of the heart's true bounding box on canvas
const heartDrawBoxX = offsetX + heartActualBoxOffsetX;
const heartDrawBoxY = offsetY + heartActualBoxOffsetY;
const heartDrawBoxWidth = heartActualScaledWidth;
const heartDrawBoxHeight = heartActualScaledHeight;
// Calculate how to draw the image to cover the heart's bounding box ("object-fit: cover" behavior)
const imgAspect = originalWidth / originalHeight;
const heartBoxAspect = heartDrawBoxWidth / heartDrawBoxHeight; // Approx 120/150 = 4/5
let drawX, drawY, drawWidth, drawHeight;
if (imgAspect > heartBoxAspect) {
// Image is wider or less tall than heart box relative to their aspect ratios; fit height, crop width
drawHeight = heartDrawBoxHeight;
drawWidth = drawHeight * imgAspect;
drawX = heartDrawBoxX - (drawWidth - heartDrawBoxWidth) / 2; // Center horizontally
drawY = heartDrawBoxY;
} else {
// Image is taller or less wide than heart box; fit width, crop height
drawWidth = heartDrawBoxWidth;
drawHeight = drawWidth / imgAspect;
drawX = heartDrawBoxX;
drawY = heartDrawBoxY - (drawHeight - heartDrawBoxHeight) / 2; // Center vertically
}
// Draw the original image, scaled and positioned to cover the heart shape
// The clipping path will ensure only the heart-shaped part is visible
ctx.drawImage(originalImg, drawX, drawY, drawWidth, drawHeight);
return canvas;
}
Apply Changes