Introduction :
The AI Image Generator project is a web application that allows users to generate images based on textual descriptions. It utilizes the OpenAI API to convert user input into images. The interface is built using HTML, CSS, and JavaScript, offering a seamless user experience where users can input a prompt, select the number of images they want, and view the generated images in a gallery. The application also provides download options for the generated images.
Explanation :
HTML Structure
The HTML defines the layout of the web page, including:
- A section for the image generator form, where users can enter a prompt and select the number of images.
- A section for displaying the generated images in a gallery format.
- A script tag to link the JavaScript file responsible for the functionality.
CSS Styling
The CSS styles enhance the visual appeal and usability of the application:
- It sets a background image and style for the image generator section.
- It styles the input form, buttons, and image gallery for a clean and modern look.
- It includes responsive design elements to ensure the application works well on different screen sizes.
JavaScript Logic
The JavaScript code handles the core functionality of the application:
- Form Submission Handling: Captures user input when the form is submitted and prevents the default form submission behavior.
- API Interaction: Sends a request to the OpenAI API with the user’s prompt and the desired number of images. It handles the API response and processes the image data.
- Dynamic Image Card Creation: Generates HTML markup for image cards, including a loading state while waiting for the API response.
- Image Display and Download: Updates the image cards with the generated images and provides download links for each image.
Key Functions and Their Purpose
generateAiImages(userPrompt, userImageQuantity):
- Sends a POST request to the OpenAI API with the user’s prompt and the number of images to generate.
- Processes the API response, updating the image gallery with the generated images.
updateImageCard(imgDataArray):
- Updates the image cards in the gallery with the actual images generated by the API.
- Removes the loading state from the image cards and sets up the download links.
Form Submission Event Listener:
- Captures the user’s input prompt and the selected number of images.
- Generates the initial HTML for the image cards with a loading indicator.
- Calls the
generateAiImages
function to fetch and display the generated images.
Error Handling
The JavaScript includes error handling to alert users if the image generation process fails. This ensures users are informed of issues such as network errors or invalid API responses, enhancing the robustness of the application.
Purpose and Benefits
The purpose of the AI Image Generator is to provide an intuitive and efficient tool for generating images based on textual descriptions. This can be useful for a variety of applications, including:
- Content creation for blogs and social media.
- Generating visual aids for educational materials.
- Providing creative visualizations for design projects.
By integrating with the OpenAI API, the application leverages advanced AI capabilities to produce high-quality images, making the tool both powerful and user-friendly.
SOURCE CODE:
HTML (index.html)
CSS (style.css)
/* Importing Google font - Poppins */
@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap");
* {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: "Poppins", sans-serif;
}
.image-generator {
height: 40vh;
display: flex;
align-items: center;
justify-content: center;
position: relative;
background-color: #565656;
background-size: cover;
background-position: center;
}
.image-generator::before {
content: "";
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
opacity: 0.5;
background: #121212;
}
.image-generator .content {
position: relative;
color: #fff;
padding: 0 15px;
max-width: 760px;
text-align: center;
}
.image-generator h1 {
font-size: 2.5rem;
font-weight: 700;
}
.image-generator p {
margin-top: 10px;
font-size: 1.35rem;
}
.image-generator .generate-form {
height: 56px;
padding: 6px;
display: flex;
margin-bottom: 15px;
background: #fff;
align-items: center;
border-radius: 30px;
margin-top: 45px;
justify-content: space-between;
}
.generate-form .prompt-input {
width: 100%;
height: 100%;
outline: none;
padding: 0 17px;
border: none;
background: none;
font-size: 1rem;
border-radius: 30px;
}
.generate-form .controls {
display: flex;
height: 100%;
gap: 15px;
}
.generate-form .img-quantity {
outline: none;
border: none;
height: 44px;
background: none;
font-size: 1rem;
}
.generate-form .generate-btn {
font-size: 1rem;
outline: none;
border: none;
font-weight: 500;
color: #fff;
cursor: pointer;
height: 100%;
padding: 0 25px;
border-radius: 30px;
background: #4949E7;
}
.generate-form .generate-btn[disabled] {
opacity: 0.6;
pointer-events: none;
}
.generate-form button:hover {
background: #1d1de2;
}
.image-gallery {
display: flex;
gap: 15px;
padding: 0 15px;
flex-wrap: wrap;
justify-content: center;
margin: 50px auto;
max-width: 1250px;
}
.image-gallery .img-card {
display: flex;
position: relative;
align-items: center;
justify-content: center;
background: #f2f2f2;
border-radius: 4px;
overflow: hidden;
aspect-ratio: 1 / 1;
width: 285px;
}
.image-gallery .img-card img {
height: 100%;
width: 100%;
object-fit: cover;
}
.image-gallery .img-card.loading img {
width: 80px;
height: 80px;
}
.image-gallery .img-card .download-btn {
bottom: 15px;
right: 15px;
height: 36px;
width: 36px;
display: flex;
align-items: center;
justify-content: center;
text-decoration: none;
background: #fff;
border-radius: 50%;
position: absolute;
opacity: 0;
pointer-events: none;
transition: 0.2s ease;
}
.image-gallery .img-card .download-btn img {
width: 14px;
height: 14px;
}
.image-gallery .img-card:not(.loading):hover .download-btn {
opacity: 1;
pointer-events: auto;
}
@media screen and (max-width: 760px) {
.image-generator {
height: 45vh;
padding-top: 30px;
align-items: flex-start;
}
.image-generator h1 {
font-size: 1.8rem;
}
.image-generator p {
font-size: 1rem;
}
.image-generator .generate-form {
margin-top: 30px;
height: 52px;
display: block;
}
.generate-form .controls {
height: 40px;
margin-top: 15px;
justify-content: end;
align-items: center;
}
.generate-form .generate-btn[disabled] {
opacity: 1;
}
.generate-form .img-quantity {
color: #fff;
}
.generate-form .img-quantity option {
color: #000;
}
.image-gallery {
margin-top: 20px;
}
.image-gallery .img-card:not(.loading) .download-btn {
opacity: 1;
pointer-events: auto;
}
}
@media screen and (max-width: 500px) {
.image-gallery .img-card {
width: 100%;
}
}
JavaScript (app.js)
const generateForm = document.querySelector(".generate-form");
const ImageGallery = document.querySelector(".image-gallery");
const OPENAI_API_KEY = "ENTER YOUR API KEY HERE FROM OPENAI API SITE"
async function generateAiImages(userPrompt, userImageQuantity) {
function updateImageCard(imgDataArray) {
imgDataArray.forEach((imgObject, index) => {
const imgCard = ImageGallery.querySelectorAll(".img-card")[index];
const imgElement = imgCard.querySelector("img");
const downloadBtn = imgCard.querySelector(".download-btn");
const aiGeneratedImg = `data:image/jpeg;base64,${imgObject.b64_json}`;
imgElement.src = aiGeneratedImg;
imgElement.onload = () => {
imgCard.classList.remove("loading");
downloadBtn.setAttribute("href", aiGeneratedImg);
downloadBtn.setAttribute("download", `${userPrompt}.jpg`);
}
});
}
try {
const response = await fetch("https://api.openai.com/v1/images/generations", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${OPENAI_API_KEY}`
},
body: JSON.stringify({
prompt: userPrompt,
n: parseInt(userImageQuantity),
size: "512x512",
response_format: "b64_json"
})
});
if (!response.ok) throw new Error("Failed to generate Images")
const { data } = await response.json();
console.log(data);
updateImageCard([...data])
} catch (error) {
alert(error.message)
}
}
generateForm.addEventListener("submit", function (event) {
// user input and image quantity values from the form
event.preventDefault()
const userPrompt = event.srcElement[0].value;
const userImageQuantity = event.srcElement[1].value;
// creating HTML markup for image cars with loading state
const imgCardMarkup = Array.from({ length: userImageQuantity }, function () {
return (
` `
)
}
).join("");
// console.log(imgCardMarkup)
ImageGallery.innerHTML = imgCardMarkup;
generateAiImages(userPrompt, userImageQuantity);
})