With HTML, CSS, and JavaScript, an AI image generator was created for this project. It lets users enter a text description, which is then used to generate a set of images via the OpenAI API. Users can download the photographs from a gallery format in which the created images are presented. The application begins with an image-generation portion with a clear heading outlining the tool’s function. The features are detailed, and users are encouraged to turn their written instructions into eye-catching pictures. Users can add their chosen image description through a well-designed form.

Additionally, a dropdown option on the form lets customers choose how many photos they want to create. Users are guided on the type of input requested by clear and simple placeholder language. Interactive controls are included in the form, such as a submit button that starts the image production process. During the creation process, a visually intuitive loading state is integrated to give consumers instantaneous feedback. The gallery part is where the created photographs are tastefully displayed. Every image is contained on a unique card that has a download button for convenience in addition to the generated image.

Clarification:

HTML Structure:

The image gallery and the image-generating form are the two primary elements of the HTML structure. User input is gathered via the form, which includes the image’s description and the number of photos to be generated. The created photographs are shown in the gallery along with download buttons.

Logic in JavaScript:

The functionality for creating images using the OpenAI API is handled by JavaScript code. It sends a POST request to OpenAI’s image creation endpoint via the Fetch API.
After processing the API response, picture data is extracted and the gallery is updated appropriately. The OPENAI_API_KEY constant contains the OpenAI API key. For added protection, make sure your API key is kept safe and think about handling API requests with server-side logic.

The function for creating images (generateAiImages):

This asynchronous function sends a request to the OpenAI API after receiving input from the user (prompt and image quantity).After that, the gallery’s picture cards are updated by processing the API response.

Update Function for Image Card (updateImageCard):

The gallery’s picture cards are updated by means of this function. It takes an array of picture objects, modifies the download button and image source attributes, and extracts the base64-encoded image data.

Event Listener for Form Submission:

It is prohibited that the default behaviour (page reloading) is triggered by the form submission. Form fields are used to collect user input, and while photos are being created, a loading state is shown in the gallery. The process of creating images is started by using the generateAiImages method.

Source Code

Index(index.html)

<title>AI Image Generator </title>




<section class="image-generator">
    <div class="content">
        <h1>AI Image Generator Tool JavaScript</h1>
        <p>Convert your text into an image within a second using this JavaScript powered AI Image Generator</p>


            <div class="controls">

                    1 Image
                    2 Images
                    3 Images
                    4 Images

                <button type="submit" class="generate-btn">Generate</button>
            </div>

    </div>
</section>

<section class="image-gallery">
    <div class="img-card ">
        <noscript><img decoding="async" src="images/img-1.jpg" alt="img"></noscript><img class="lazy"  decoding="async" src='data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%20%20%22%3E%3C/svg%3E' data-src="images/img-1.jpg" alt="img">
        <a href="images/img-1.jpg" class="download-btn" download>
            <noscript><img decoding="async" src="images/download.svg" alt="download-icon"></noscript><img class="lazy"  decoding="async" src='data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%20%20%22%3E%3C/svg%3E' data-src="images/download.svg" alt="download-icon">
        </a>
    </div>
    <div class="img-card">
        <noscript><img decoding="async" src="images/img-2.jpg" alt="img"></noscript><img class="lazy"  decoding="async" src='data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%20%20%22%3E%3C/svg%3E' data-src="images/img-2.jpg" alt="img">
        <a href="images/img-2.jpg" class="download-btn" download>
            <noscript><img decoding="async" src="images/download.svg" alt="download-icon"></noscript><img class="lazy"  decoding="async" src='data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%20%20%22%3E%3C/svg%3E' data-src="images/download.svg" alt="download-icon">
        </a>
    </div>
    <div class="img-card">
        <noscript><img decoding="async" src="images/img-3.jpg" alt="img"></noscript><img class="lazy"  decoding="async" src='data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%20%20%22%3E%3C/svg%3E' data-src="images/img-3.jpg" alt="img">
        <a href="images/img-3.jpg" class="download-btn" download <noscript><img decoding="async" src="images/download.svg" alt="download-icon"></noscript><img class="lazy"  decoding="async" src='data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%20%20%22%3E%3C/svg%3E' data-src="images/download.svg" alt="download-icon">
        </a>
    </div>
    <div class="img-card">
        <noscript><img decoding="async" src="images/img-4.jpg" alt="img"></noscript><img class="lazy"  decoding="async" src='data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%20%20%22%3E%3C/svg%3E' data-src="images/img-4.jpg" alt="img">
        <a href="images/img-4.jpg" class="download-btn" download>
            <noscript><img decoding="async" src="images/download.svg" alt="download-icon"></noscript><img class="lazy"  decoding="async" src='data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%20%20%22%3E%3C/svg%3E' data-src="images/download.svg" alt="download-icon">
        </a>
    </div>

</section>

Style (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 (
            `  <div class="img-card loading">
            <noscript><img decoding="async" src="images/loader.svg" alt="img"></noscript><img class="lazy"  decoding="async" src='data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%20%20%22%3E%3C/svg%3E' data-src="images/loader.svg" alt="img">
            <a href="#" class="download-btn">
                <noscript><img decoding="async" src="images/download.svg" alt="download-icon"></noscript><img class="lazy"  decoding="async" src='data:image/svg+xml,%3Csvg%20xmlns=%22http://www.w3.org/2000/svg%22%20viewBox=%220%200%20%20%22%3E%3C/svg%3E' data-src="images/download.svg" alt="download-icon">
            </a>
            </div>`
        )
    }


    ).join("");

    // console.log(imgCardMarkup)

    ImageGallery.innerHTML = imgCardMarkup;
    generateAiImages(userPrompt, userImageQuantity);





})

Output

output

Conclusion

it can be concluded that the AI image generator project effectively utilizes HTML, CSS, and JavaScript to create a user-friendly tool. The project allows users to input text descriptions, which are then used to generate images via the OpenAI API. The application features a well-designed interface with clear headings and detailed instructions, encouraging users to turn their text descriptions into visually appealing images.

Additionally, the inclusion of a gallery format for image presentation and the ability for users to download the generated photographs enhances the usability and functionality of the tool. Overall, the project demonstrates effective implementation of web technologies to facilitate image generation based on user input.

Categorized in:

AI, HTML Projects,

Last Update: February 17, 2024