Home

Build an AI Image Generator Using Next.js and OpenAI API

15 views

In today’s digital landscape, harnessing the power of AI for creative projects has become increasingly accessible. One exciting application is generating image variations based on user-uploaded reference images. By combining Next.js with the OpenAI API, we can build a web application that allows users to upload multiple reference images and receive a transformed version based on their prompts. Here’s how you can set this up step by step.

First, we start with our API route, which will process the uploaded images and communicate with the OpenAI API. We’ll need to install the formidable package to handle file uploads effectively. After setting this up, create a file at pages/api/generateImage.js to manage incoming requests.

In our API route, we use formidable to parse incoming form data. We allow users to upload multiple images by checking if the uploaded files are in the array format. Upon receiving the images and the accompanying prompts from the user, we read the image files and append them to a new FormData object, which is then sent to the OpenAI API for processing.

Here’s an example of the updated API route:

import formidable from 'formidable';
import fs from 'fs';
import path from 'path';
import axios from 'axios';

export const config = {
    api: {
        bodyParser: false,
    },
};

const handler = async (req, res) => {
    if (req.method === 'POST') {
        const form = new formidable.IncomingForm();

        form.parse(req, async (err, fields, files) => {
            if (err) {
                return res.status(500).json({ error: 'Failed to parse form data' });
            }

            const { prompt } = fields;
            const imageFiles = Array.isArray(files.image) ? files.image : [files.image];

            const imageBufferArray = await Promise.all(imageFiles.map(async (file) => {
                const imageBuffer = fs.readFileSync(file.filepath);
                return {
                    buffer: imageBuffer,
                    filename: file.originalFilename,
                    contentType: file.mimetype,
                };
            }));

            try {
                const formData = new FormData();
                imageBufferArray.forEach(file => {
                    formData.append('images', file.buffer, {
                        filename: file.filename,
                        contentType: file.contentType,
                    });
                });

                formData.append('prompt', prompt);

                const response = await axios.post('https://api.openai.com/v1/images/generations', formData, {
                    headers: {
                        'Authorization': `Bearer YOUR_API_KEY`,
                        ...formData.getHeaders(),
                    },
                });

                const generatedImageUrl = response.data.data[0].url;
                res.status(200).json({ url: generatedImageUrl });
            } catch (error) {
                console.error('Error generating image variation:', error.response ? error.response.data : error.message);
                res.status(500).json({ error: 'Failed to generate image' });
            }
        });
    } else {
        res.setHeader('Allow', ['POST']);
        res.status(405).end(`Method ${req.method} Not Allowed`);
    }
};

export default handler;

Now that we have our API set up, we need a user interface where users can upload their reference images and provide a descriptive prompt. We’ll create a frontend component named GenerateImage.js. This component will feature a file input that allows multiple file selections and a text area for the user’s prompt.

Here’s how to build our GenerateImage component:

import { useState } from 'react';

const GenerateImage = () => {
    const [prompt, setPrompt] = useState('');
    const [imageFiles, setImageFiles] = useState([]);
    const [imageUrl, setImageUrl] = useState('');

    const handleFileChange = (e) => {
        setImageFiles(Array.from(e.target.files));
    };

    const handleSubmit = async (e) => {
        e.preventDefault();

        const formData = new FormData();
        imageFiles.forEach((file) => {
            formData.append('image', file);
        });
        formData.append('prompt', prompt);

        const response = await fetch('/api/generateImage', {
            method: 'POST',
            body: formData,
        });

        const data = await response.json();
        if (response.ok) {
            setImageUrl(data.url);
        } else {
            console.error(data.error);
        }
    };

    return (
        <div>
            <form onSubmit={handleSubmit}>
                <input
                    type="file"
                    accept="image/*"
                    multiple
                    onChange={handleFileChange}
                    required
                />
                <textarea
                    value={prompt}
                    onChange={(e) => setPrompt(e.target.value)}
                    placeholder="Describe your image..."
                    required
                />
                <button type="submit">Generate Image</button>
            </form>
            {imageUrl && <img src={imageUrl} alt="Generated" />}
        </div>
    );
};

export default GenerateImage;

Finally, we can assemble this component into our Next.js page, such as pages/index.js, creating a seamless experience for users looking to generate creative variations based on their reference images.

The full implementation allows users to interactively upload multiple images, describe the transformations they want, and receive an output that creatively merges these attributes. This integration not only empowers the creative process but also showcases the immense possibilities that AI offers in the realm of digital art. With the right implementation, you can provide an engaging and dynamic tool for users to explore their creativity through the power of AI-enhanced image generation.