You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, title = "Meme Subject", description = "This is a detailed and highly accurate summary automatically generated by Google Lens, redirecting to the official Wikipedia article.", lang = "en") {
// Standard mobile aspect ratio canvas
const canvas = document.createElement('canvas');
const width = 720;
const height = 1280;
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d');
// 1. Draw Image Background (object-fit: cover)
const imgRatio = originalImg.width / originalImg.height;
const canvasRatio = width / height;
let drawWidth, drawHeight, offsetX, offsetY;
if (imgRatio > canvasRatio) {
drawHeight = height;
drawWidth = originalImg.width * (height / originalImg.height);
offsetX = (width - drawWidth) / 2;
offsetY = 0;
} else {
drawWidth = width;
drawHeight = originalImg.height * (width / originalImg.width);
offsetX = 0;
offsetY = (height - drawHeight) / 2;
}
// Fill background with same image, blurred or scaled
ctx.drawImage(originalImg, offsetX, offsetY, drawWidth, drawHeight);
// 2. Dark Overlay for Lens Focus
ctx.fillStyle = 'rgba(0, 0, 0, 0.5)';
const scanX = 110, scanY = 290, scanSize = 500;
// Top
ctx.fillRect(0, 0, width, scanY);
// Bottom
ctx.fillRect(0, scanY + scanSize, width, height - (scanY + scanSize));
// Left
ctx.fillRect(0, scanY, scanX, scanSize);
// Right
ctx.fillRect(scanX + scanSize, scanY, width - (scanX + scanSize), scanSize);
// 3. Draw Scanner Brackets
ctx.strokeStyle = '#ffffff';
ctx.lineWidth = 6;
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
const bLen = 40;
// Top-Left
ctx.beginPath(); ctx.moveTo(scanX, scanY + bLen); ctx.lineTo(scanX, scanY); ctx.lineTo(scanX + bLen, scanY); ctx.stroke();
// Top-Right
ctx.beginPath(); ctx.moveTo(scanX + scanSize - bLen, scanY); ctx.lineTo(scanX + scanSize, scanY); ctx.lineTo(scanX + scanSize, scanY + bLen); ctx.stroke();
// Bottom-Right
ctx.beginPath(); ctx.moveTo(scanX + scanSize, scanY + scanSize - bLen); ctx.lineTo(scanX + scanSize, scanY + scanSize); ctx.lineTo(scanX + scanSize - bLen, scanY + scanSize); ctx.stroke();
// Bottom-Left
ctx.beginPath(); ctx.moveTo(scanX + bLen, scanY + scanSize); ctx.lineTo(scanX, scanY + scanSize); ctx.lineTo(scanX, scanY + scanSize - bLen); ctx.stroke();
// 4. Scanner Laser Line
ctx.fillStyle = '#4285F4'; // Google Blue
ctx.shadowColor = '#4285F4';
ctx.shadowBlur = 15;
ctx.fillRect(scanX + 10, scanY + scanSize / 2 - 2, scanSize - 20, 4);
ctx.shadowBlur = 0; // Reset shadow
// Helper to draw rounded rectangles
const drawRoundRect = (x, y, w, h, r) => {
ctx.beginPath();
ctx.moveTo(x + r, y);
ctx.lineTo(x + w - r, y);
ctx.quadraticCurveTo(x + w, y, x + w, y + r);
ctx.lineTo(x + w, y + h - r);
ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);
ctx.lineTo(x + r, y + h);
ctx.quadraticCurveTo(x, y + h, x, y + h - r);
ctx.lineTo(x, y + r);
ctx.quadraticCurveTo(x, y, x + r, y);
ctx.closePath();
};
// 5. Bottom Sheet Background
const sheetY = 880;
ctx.shadowColor = 'rgba(0,0,0,0.4)';
ctx.shadowBlur = 20;
ctx.shadowOffsetY = -5;
ctx.fillStyle = '#ffffff';
ctx.beginPath();
ctx.moveTo(0, height);
ctx.lineTo(0, sheetY + 35);
ctx.quadraticCurveTo(0, sheetY, 35, sheetY);
ctx.lineTo(width - 35, sheetY);
ctx.quadraticCurveTo(width, sheetY, width, sheetY + 35);
ctx.lineTo(width, height);
ctx.closePath();
ctx.fill();
ctx.shadowColor = 'transparent'; // Reset
// Pill (drag handle)
ctx.fillStyle = '#E8EAED';
drawRoundRect(330, sheetY + 15, 60, 6, 3);
ctx.fill();
// Wikipedia Header
ctx.fillStyle = '#202124';
ctx.font = 'bold 20px "Times New Roman", Times, serif';
ctx.fillText('W', 40, sheetY + 65);
ctx.fillStyle = '#5F6368';
ctx.font = '14px Arial, sans-serif';
ctx.fillText('Wikipedia • https://' + lang + '.wikipedia.org', 70, sheetY + 63);
// Title
ctx.fillStyle = '#202124';
ctx.font = 'normal 32px "Times New Roman", Times, serif';
// Wrap Title (allows up to 2 lines)
const titleMaxWidth = 440;
const wordsTitle = title.split(' ');
let lineT = '';
let currYT = sheetY + 115;
let titleLines = 1;
for (let n = 0; n < wordsTitle.length; n++) {
const testLine = lineT + wordsTitle[n] + ' ';
const metrics = ctx.measureText(testLine);
if (metrics.width > titleMaxWidth && n > 0) {
ctx.fillText(lineT, 40, currYT);
lineT = wordsTitle[n] + ' ';
currYT += 38;
titleLines++;
} else {
lineT = testLine;
}
}
ctx.fillText(lineT, 40, currYT);
let descY = currYT + 35;
// Word Wrap Function for Description
const wrapText = (context, text, x, y, maxWidth, lineHeight, maxLines) => {
const words = text.split(' ');
let line = '';
let linesDrawn = 0;
for(let n = 0; n < words.length; n++) {
const testLine = line + words[n] + ' ';
const metrics = context.measureText(testLine);
if (metrics.width > maxWidth && n > 0) {
if (linesDrawn >= maxLines - 1) {
line = line + '...';
break;
}
context.fillText(line, x, y);
line = words[n] + ' ';
y += lineHeight;
linesDrawn++;
} else {
line = testLine;
}
}
context.fillText(line, x, y);
};
// Description text
ctx.fillStyle = '#4D5156';
ctx.font = '20px Arial, sans-serif';
wrapText(ctx, description, 40, descY, titleMaxWidth, 28, 6);
// Right Thumbnail
const thumbSize = 160;
const thumbX = 520;
const thumbY = sheetY + 85;
ctx.save();
drawRoundRect(thumbX, thumbY, thumbSize, thumbSize, 15);
ctx.clip();
let tWidth, tHeight, tOffsetX, tOffsetY;
if (imgRatio > 1) { // 1 is thumbnail ratio since it's square
tHeight = thumbSize;
tWidth = originalImg.width * (thumbSize / originalImg.height);
tOffsetX = thumbX - (tWidth - thumbSize) / 2;
tOffsetY = thumbY;
} else {
tWidth = thumbSize;
tHeight = originalImg.height * (thumbSize / originalImg.width);
tOffsetX = thumbX;
tOffsetY = thumbY - (tHeight - thumbSize) / 2;
}
ctx.drawImage(originalImg, tOffsetX, tOffsetY, tWidth, tHeight);
ctx.restore();
// 6. Top UI Elements (Google Lens Look)
ctx.strokeStyle = '#fff';
ctx.lineWidth = 3;
// Back Arrow
ctx.beginPath();
ctx.moveTo(60, 56);
ctx.lineTo(40, 70);
ctx.lineTo(60, 84);
ctx.moveTo(40, 70);
ctx.lineTo(80, 70);
ctx.stroke();
// Three dots menu
ctx.fillStyle = '#fff';
ctx.beginPath(); ctx.arc(660, 56, 4, 0, Math.PI * 2); ctx.fill();
ctx.beginPath(); ctx.arc(660, 70, 4, 0, Math.PI * 2); ctx.fill();
ctx.beginPath(); ctx.arc(660, 84, 4, 0, Math.PI * 2); ctx.fill();
// Header Text
ctx.font = 'bold 22px Arial, sans-serif';
const headerText = "Google Lens";
const textW = ctx.measureText(headerText).width;
ctx.fillText(headerText, (width - textW) / 2, 80);
return canvas;
}
Apply Changes