You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(originalImg, searchTopic = "City", themeColor = "#2a52be", backgroundColor = "#efefef") {
const canvas = document.createElement('canvas');
canvas.width = 840;
canvas.height = 750;
const ctx = canvas.getContext('2d');
// Background
ctx.fillStyle = backgroundColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
// Context Header
ctx.fillStyle = themeColor;
ctx.fillRect(0, 0, canvas.width, 100);
// Header hamburger menu icon
ctx.fillStyle = "#ffffff";
ctx.fillRect(30, 42, 24, 3);
ctx.fillRect(30, 49, 24, 3);
ctx.fillRect(30, 56, 24, 3);
// Helper to draw a rounded rectangle for standard browser support safely
function drawRoundedRect(context, x, y, width, height, radius) {
context.beginPath();
context.moveTo(x + radius, y);
context.lineTo(x + width - radius, y);
context.quadraticCurveTo(x + width, y, x + width, y + radius);
context.lineTo(x + width, y + height - radius);
context.quadraticCurveTo(x + width, y + height, x + width - radius, y + height);
context.lineTo(x + radius, y + height);
context.quadraticCurveTo(x, y + height, x, y + height - radius);
context.lineTo(x, y + radius);
context.quadraticCurveTo(x, y, x + radius, y);
context.closePath();
context.fill();
}
// Search Bar Body
ctx.fillStyle = "#ffffff";
drawRoundedRect(ctx, 100, 25, 640, 50, 25);
// Magnifying Glass
ctx.strokeStyle = "#888";
ctx.lineWidth = 3;
ctx.beginPath();
ctx.arc(135, 50, 8, 0, Math.PI * 2);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(141, 56);
ctx.lineTo(149, 64);
ctx.stroke();
// Search Text Content
ctx.fillStyle = "#333";
ctx.font = "bold 20px Arial, sans-serif";
ctx.textAlign = "left";
ctx.textBaseline = "middle";
ctx.fillText(searchTopic + " skyline themes", 165, 50);
// Generic default user Avatar
ctx.fillStyle = "#ffffff";
ctx.beginPath();
ctx.arc(790, 50, 18, 0, Math.PI * 2);
ctx.fill();
ctx.fillStyle = themeColor;
ctx.beginPath();
ctx.arc(790, 45, 7, 0, Math.PI * 2);
ctx.fill();
ctx.beginPath();
ctx.arc(790, 61, 10, Math.PI, 0);
ctx.fill();
// Simulated "Results" Header Info
ctx.fillStyle = "#666";
ctx.font = "16px Arial, sans-serif";
ctx.textBaseline = "alphabetic";
ctx.fillText("Showing interpreted image search results for topic: " + searchTopic, 30, 140);
// Pre-defined city visual interpretations
const filters = [
{ title: "Standard Origin", col: 0, row: 0 },
{ title: "Metropolis Nightscape", col: 1, row: 0 },
{ title: "Neon Cyberpunk City", col: 2, row: 0 },
{ title: "Architectural Blueprint", col: 0, row: 1 },
{ title: "Sunset Skyline", col: 1, row: 1 },
{ title: "Urban Thermal Map", col: 2, row: 1 }
];
// Applies city-genre manipulations to an offscreen canvas
function processFilter(octx, w, h, index) {
if (index === 0) return; // Keeps unmodified standard image
const imgData = octx.getImageData(0, 0, w, h);
const d = imgData.data;
if (index === 1) { // Nightscape
for(let i = 0; i < d.length; i += 4) {
d[i] = d[i] * 0.2;
d[i+1] = d[i+1] * 0.3 + 10;
d[i+2] = d[i+2] * 0.6 + 40;
}
octx.putImageData(imgData, 0, 0);
octx.fillStyle = "rgba(255, 240, 100, 0.8)";
for(let k = 0; k < (w * h) / 300; k++) {
let wx = Math.random() * w;
let wy = Math.random() * h;
if (Math.random() > 0.5) octx.fillRect(wx, wy, Math.random() * 2 + 1, Math.random() * 2 + 1);
}
} else if (index === 2) { // Neon Cyberpunk
for(let i = 0; i < d.length; i += 4) {
let r = d[i], g = d[i+1], b = d[i+2];
let lum = r * 0.3 + g * 0.59 + b * 0.11;
if (lum < 85) {
let pct = lum / 85;
d[i] = 15 * pct; d[i+1] = 15 * pct; d[i+2] = 61 * pct;
} else if (lum < 170) {
let pct = (lum - 85) / 85;
d[i] = 15 + 240 * pct; d[i+1] = 15 - 15 * pct; d[i+2] = 61 + 194 * pct;
} else {
let pct = (lum - 170) / 85;
d[i] = 255 - 255 * pct; d[i+1] = 255 * pct; d[i+2] = 255;
}
}
octx.putImageData(imgData, 0, 0);
} else if (index === 3) { // Architectural blueprint
const copy = new Uint8ClampedArray(d);
for(let i = 0; i < d.length; i += 4) {
d[i] = 10; d[i+1] = 61; d[i+2] = 145;
}
for(let y = 0; y < h - 1; y++) {
for(let x = 0; x < w - 1; x++) {
let i = (y * w + x) * 4;
let right = (y * w + x + 1) * 4;
let bottom = ((y + 1) * w + x) * 4;
let diff = Math.abs(copy[i]-copy[right]) + Math.abs(copy[i]-copy[bottom]) +
Math.abs(copy[i+1]-copy[right+1]) + Math.abs(copy[i+1]-copy[bottom+1]) +
Math.abs(copy[i+2]-copy[right+2]) + Math.abs(copy[i+2]-copy[bottom+2]);
if(diff > 40) {
d[i] = 255; d[i+1] = 255; d[i+2] = 255;
}
}
}
octx.putImageData(imgData, 0, 0);
} else if (index === 4) { // Sunset skyline addition
for(let i = 0; i < d.length; i += 4) {
d[i] = Math.min(255, d[i] * 1.2 + 20);
d[i+1] = Math.min(255, d[i+1] * 0.9 + 10);
d[i+2] = d[i+2] * 0.6;
}
octx.putImageData(imgData, 0, 0);
octx.fillStyle = "#1a0f14";
let currentX = 0;
while(currentX < w) {
let bWidth = 10 + Math.random() * 25;
let bHeight = h * 0.15 + Math.random() * (h * 0.35);
octx.fillRect(currentX, h - bHeight, bWidth, bHeight);
// Add sporadic spires
if(Math.random() > 0.6) octx.fillRect(currentX + bWidth/2 - 1.5, h - bHeight - 20, 3, 20);
currentX += bWidth + (Math.random() > 0.7 ? 3 : 0);
}
} else if (index === 5) { // Urban Heatmap
for(let i = 0; i < d.length; i += 4) {
let v = d[i]*0.3 + d[i+1]*0.59 + d[i+2]*0.11;
if(v < 64) {
d[i] = 0; d[i+1] = v*4; d[i+2] = 255;
} else if (v < 128) {
d[i] = 0; d[i+1] = 255; d[i+2] = 255 - (v-64)*4;
} else if (v < 192) {
d[i] = (v-128)*4; d[i+1] = 255; d[i+2] = 0;
} else {
d[i] = 255; d[i+1] = 255 - (v-192)*4; d[i+2] = 0;
}
}
octx.putImageData(imgData, 0, 0);
}
}
// Process and draw each cell into the simulated image search grid
filters.forEach((filter, index) => {
const cx = 30 + filter.col * 260;
const cy = 160 + filter.row * 290;
// Dynamically scale image resolving aspect ratio bounds 230x230
const aspect = originalImg.width / originalImg.height;
let w = 230, h = 230;
if (aspect > 1) {
h = w / aspect;
} else {
w = h * aspect;
}
const offsetX = cx + (230 - w) / 2;
const offsetY = cy + (230 - h) / 2;
const off = document.createElement('canvas');
off.width = w;
off.height = h;
const octx = off.getContext('2d');
octx.drawImage(originalImg, 0, 0, w, h);
// Form the stylistic view
processFilter(octx, w, h, index);
// Draw frame with dropshadow
ctx.shadowColor = "rgba(0,0,0,0.15)";
ctx.shadowBlur = 10;
ctx.shadowOffsetY = 5;
ctx.fillStyle = "#fff";
ctx.fillRect(offsetX - 5, offsetY - 5, w + 10, h + 10);
// Clean drop shadow payload so it doesn't leak further down
ctx.shadowColor = "transparent";
ctx.shadowBlur = 0;
ctx.shadowOffsetY = 0;
// Draw altered image
ctx.drawImage(off, offsetX, offsetY);
// Annotate image
ctx.fillStyle = "#444";
ctx.font = "bold 13px Arial, sans-serif";
ctx.textAlign = "center";
ctx.fillText(filter.title, cx + 115, cy + 230 + 25);
});
return canvas;
}
Apply Changes