<!--
This is a self-contained HTML file that demonstrates how to generate an image
using the Google Imagen API (imagen-3.0-generate-002) via a simple web interface.
All styling is now embedded directly in the file to avoid Content Security Policy issues.
-->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Imagen Image Generator</title>
<!-- All CSS is now embedded directly in the file -->
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap');
body {
font-family: 'Inter', sans-serif;
background-color: #0f172a;
color: #e2e8f0;
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
padding: 1rem;
}
.container {
background-color: #1f2937;
padding: 2rem;
border-radius: 1.5rem;
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
max-width: 42rem; /* 672px */
width: 100%;
margin: auto;
display: flex;
flex-direction: column;
gap: 1.5rem;
}
h1 {
font-size: 1.875rem;
line-height: 2.25rem;
font-weight: 700;
text-align: center;
color: #ffffff;
}
p {
text-align: center;
color: #94a3b8;
}
textarea {
width: 100%;
background-color: #374151;
color: #ffffff;
border: none;
border-radius: 0.5rem;
padding: 1rem;
resize: none;
transition: all 0.2s ease-in-out;
}
textarea:focus {
outline: none;
box-shadow: 0 0 0 2px #4f46e5;
}
.button-container {
display: flex;
justify-content: center;
}
button {
padding: 0.75rem 2rem;
background-color: #4f46e5;
color: #ffffff;
font-weight: 600;
border-radius: 9999px; /* full rounded */
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
transition: background-color 0.3s;
cursor: pointer;
width: 100%;
}
button:hover {
background-color: #4338ca;
}
.result-container {
margin-top: 1.5rem;
min-height: 300px;
display: flex;
align-items: center;
justify-content: center;
background-color: #374151;
border-radius: 0.5rem;
overflow: hidden;
position: relative;
}
.loading-spinner {
display: none;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.spinner-svg {
animation: spin 1s linear infinite;
height: 2.5rem;
width: 2.5rem;
color: #ffffff;
}
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.message-box {
color: #94a3b8;
text-align: center;
padding: 1rem;
}
.generated-image {
display: none;
width: 100%;
height: auto;
object-fit: cover;
transition: opacity 0.5s;
}
/* Responsive adjustments */
@media (min-width: 768px) {
button {
width: auto;
}
}
</style>
</head>
<body>
<div class="container">
<h1>Imagen Image Generator</h1>
<p>Enter a detailed prompt and generate a photorealistic image using Google's Imagen API.</p>
<!-- Input for the image generation prompt -->
<div class="relative">
<textarea id="prompt-input" rows="4" placeholder="A photorealistic, highly-detailed image of a futuristic cyberpunk city street at night, with rain reflecting neon lights..."></textarea>
</div>
<!-- Button to trigger image generation -->
<div class="button-container">
<button id="generate-button">
Generate Image
</button>
</div>
<!-- Container for loading indicator and image result -->
<div class="result-container">
<!-- Loading spinner -->
<div id="loading-spinner" class="loading-spinner">
<svg class="spinner-svg" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
</svg>
</div>
<!-- Message for user feedback -->
<p id="message-box" class="message-box">
Your generated image will appear here.
</p>
<!-- Image element to display the result -->
<img id="generated-image" class="generated-image" alt="Generated Image">
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const promptInput = document.getElementById('prompt-input');
const generateButton = document.getElementById('generate-button');
const resultContainer = document.getElementById('result-container');
const generatedImage = document.getElementById('generated-image');
const loadingSpinner = document.getElementById('loading-spinner');
const messageBox = document.getElementById('message-box');
// This is the model ID for image generation
const IMAGEN_MODEL = 'imagen-3.0-generate-002';
// API key is provided by the environment, leave it as an empty string
const apiKey = "";
const apiUrl = `https://generativelanguage.googleapis.com/v1beta/models/${IMAGEN_MODEL}:predict?key=${apiKey}`;
// Function to show a message to the user
const showMessage = (message) => {
messageBox.textContent = message;
messageBox.style.display = 'block';
generatedImage.style.display = 'none';
loadingSpinner.style.display = 'none';
};
// Main function to handle the image generation process
const generateImage = async (prompt) => {
if (!prompt.trim()) {
showMessage("Please enter a prompt to generate an image.");
return;
}
// Show loading state
messageBox.style.display = 'none';
generatedImage.style.display = 'none';
loadingSpinner.style.display = 'block';
try {
const payload = {
instances: { prompt: prompt },
parameters: { "sampleCount": 1 }
};
const response = await fetch(apiUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload)
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.error.message || 'API request failed.');
}
const result = await response.json();
// Check if the response contains the image data
if (result.predictions && result.predictions.length > 0 && result.predictions[0].bytesBase64Encoded) {
const base64Data = result.predictions[0].bytesBase64Encoded;
const imageUrl = `data:image/png;base64,${base64Data}`;
// Display the generated image
generatedImage.src = imageUrl;
generatedImage.alt = prompt; // Set alt text for accessibility
generatedImage.style.display = 'block';
loadingSpinner.style.display = 'none';
} else {
showMessage('Failed to generate image. Unexpected API response format.');
console.error('Unexpected API response:', result);
}
} catch (error) {
showMessage(`Error: ${error.message}`);
console.error('Image Generation Error:', error);
}
};
// Add event listener to the button
generateButton.addEventListener('click', () => {
generateImage(promptInput.value);
});
// Allow hitting Enter key in the textarea to trigger generation
promptInput.addEventListener('keypress', (event) => {
if (event.key === 'Enter') {
event.preventDefault(); // Prevent new line
generateImage(promptInput.value);
}
});
// Set a default value to give the user an example prompt
promptInput.value = 'A photorealistic, highly-detailed image of a futuristic cyberpunk city street at night, with rain reflecting neon lights.';
});
</script>
</body>
</html>