You can edit the below JavaScript code to customize the image tool.
Apply Changes
function processImage(
originalImg,
apiKey = "",
prompt = "Analyze this image in detail like Google NotebookLM would. Extract key summaries, entities, structural information, and actionable insights. Provide your response in a well-structured markdown format."
) {
// 1. Create the Main UI Container
const container = document.createElement("div");
container.style.fontFamily = "system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif";
container.style.padding = "24px";
container.style.border = "1px solid #dadce0";
container.style.borderRadius = "12px";
container.style.backgroundColor = "#ffffff";
container.style.color = "#202124";
container.style.maxWidth = "850px";
container.style.boxShadow = "0 4px 6px rgba(0,0,0,0.05), 0 1px 3px rgba(0,0,0,0.03)";
container.style.lineHeight = "1.6";
container.style.margin = "0 auto";
// 2. Create the Header
const header = document.createElement("div");
header.style.display = "flex";
header.style.alignItems = "center";
header.style.borderBottom = "1px solid #e8eaed";
header.style.paddingBottom = "16px";
header.style.marginBottom = "20px";
const title = document.createElement("h2");
// Using a simple embedded SVG for a NotebookLM / AI sparkle vibe
title.innerHTML = `
<svg style="width: 24px; height: 24px; margin-right: 8px; vertical-align: middle; fill: #1a73e8;" viewBox="0 0 24 24">
<path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-9 14l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>
</svg>
Gemini NotebookLM Analysis
`;
title.style.marginTop = "0";
title.style.marginBottom = "0";
title.style.color = "#1a73e8";
title.style.fontSize = "1.4em";
title.style.fontWeight = "600";
header.appendChild(title);
container.appendChild(header);
// 3. Create Content Area (Initial Loading State)
const content = document.createElement("div");
content.innerHTML = `
<div style="display: flex; align-items: center; justify-content: center; padding: 40px 0; color: #5f6368;">
<svg class="spin-icon" style="width: 24px; height: 24px; margin-right: 12px; fill: #1a73e8;" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path d="M12 4V2C6.48 2 2 6.48 2 12h2c0-4.41 3.59-8 8-8zm8 8c0-4.41-3.59-8-8-8v2c4.41 0 8 3.59 8 8h2c0 5.52-4.48 10-10 10V22c5.52 0 10-4.48 10-10z"/>
</svg>
<span style="font-size: 1.1em; font-weight: 500;">Synthesizing image data with Gemini...</span>
<style>
@keyframes spin { 100% { transform: rotate(360deg); } }
.spin-icon { animation: spin 1s linear infinite; }
</style>
</div>
`;
container.appendChild(content);
// 4. Validate API Key
if (!apiKey || apiKey.trim() === "") {
content.innerHTML = `
<div style="color: #b3261e; background-color: #f9dedc; padding: 16px; border-radius: 8px; font-weight: 500;">
<span style="font-size: 1.2em; display:block; margin-bottom: 4px;">⚠️ Missing API Key</span>
Please provide a valid Google Gemini API Key as the second parameter to use the NotebookLM Image Analysis Tool.
</div>
`;
return container;
}
// 5. Prepare Image Data (Resize to avoid massive payload errors)
let base64Data = "";
try {
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
let w = originalImg.width;
let h = originalImg.height;
const maxDim = 1024; // Restrict max dimension to 1024px
if (w > maxDim || h > maxDim) {
if (w > h) {
h = Math.round((h * maxDim) / w);
w = maxDim;
} else {
w = Math.round((w * maxDim) / h);
h = maxDim;
}
}
canvas.width = w;
canvas.height = h;
ctx.fillStyle = "#ffffff"; // Flat background for transparency issues
ctx.fillRect(0, 0, w, h);
ctx.drawImage(originalImg, 0, 0, w, h);
const dataUrl = canvas.toDataURL("image/jpeg", 0.85);
base64Data = dataUrl.split(",")[1];
} catch (e) {
content.innerHTML = `
<div style="color: #b3261e; background-color: #f9dedc; padding: 16px; border-radius: 8px;">
<strong>Image Processing Error:</strong> Could not extract image data. Ensure the image is not tainted by cross-origin (CORS) restrictions.
</div>
`;
return container;
}
// 6. Call Google Gemini API
const url = `https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash:generateContent?key=${apiKey.trim()}`;
const payload = {
contents: [
{
parts: [
{ text: prompt },
{ inline_data: { mime_type: "image/jpeg", data: base64Data } }
]
}
],
generationConfig: {
temperature: 0.4,
topK: 32,
topP: 1,
maxOutputTokens: 8192,
}
};
fetch(url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload)
})
.then(async response => {
if (!response.ok) {
const errText = await response.text();
throw new Error(`Error ${response.status}: ${errText}`);
}
return response.json();
})
.then(data => {
if (data.candidates && data.candidates[0].content.parts[0].text) {
let mdText = data.candidates[0].content.parts[0].text;
// Minimal Markdown formatting matching NotebookLM style requirements
mdText = mdText.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
// Code Blocks and Inline Code (Fixed regex missing "/" error and completed formatting)
mdText = mdText.replace(/
Apply Changes