DEV Community

ficav
ficav

Posted on

3

Building an AI-Powered 'Erase and Replace' Image Tool with Next.js and React

Building an AI-Powered "Erase and Replace" Image Tool with Next.js and React

Ever wanted to remove an unwanted object from a photo or replace it entirely with something else? With advancements in AI, this is now possible. In this tutorial, we'll explore how to build an AI erase and replace image editing tool using Next.js and React. We’ll leverage AI services to manipulate images and integrate them into a web application.

Understanding AI-Powered Image Editing

AI-powered image editing tools use advanced machine learning algorithms to understand image content and manipulate it intelligently. One of these functionalities is erase and replace, where users can remove objects from an image and replace them with generated content that blends seamlessly with the surroundings.

Technologies We'll Use

Before we dive in, let's look at the technologies we'll be using:

  • Next.js: A React framework for server-rendered applications and static websites. It provides features like file-based routing, server-side rendering, and easy API creation.
  • React: A JavaScript library for building user interfaces. We'll use it to create our frontend components.
  • Webpack: Although Next.js handles bundling internally with Webpack, understanding it helps in customizing the build process if needed.

We'll also integrate with an AI service for image manipulation. For demonstration purposes, we'll use a mock API, but in a production app, you might use services like TensorFlow.js, OpenAI's API, or other AI-as-a-Service platforms.

Setting Up the Project

First, set up a new Next.js project:

npx create-next-app ai-erase-and-replace
Enter fullscreen mode Exit fullscreen mode

Navigate to the project directory:

cd ai-erase-and-replace
Enter fullscreen mode Exit fullscreen mode

Start the development server:

npm run dev
Enter fullscreen mode Exit fullscreen mode

You should now have a basic Next.js app running at http://localhost:3000.

Implementing the AI Erase and Replace Functionality

We’ll build a page where users can upload an image, select an area to erase, provide a description of what they want to replace it with, and see the AI-manipulated result.

Step 1: Creating the Upload Component

Let's create a component that allows users to upload images.

// components/ImageUpload.js
import { useState } from 'react';

export default function ImageUpload({ onUpload }) {
  const [selectedImage, setSelectedImage] = useState(null);

  const handleImageChange = (e) => {
    if (e.target.files && e.target.files[0]) {
      setSelectedImage(URL.createObjectURL(e.target.files[0]));
      onUpload(e.target.files[0]);
    }
  };

  return (
    <div>
      <input type="file" accept="image/*" onChange={handleImageChange} />
      {selectedImage && (
        <div style={{ marginTop: '1rem' }}>
          <img src={selectedImage} alt="Uploaded" width="300" />
        </div>
      )}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

This component lets the user select an image file and displays a preview. The uploaded file is passed to the parent component via the onUpload prop.

Step 2: Allowing the User to Select an Area to Erase

To let users select a portion of the image, you can use a library like react-image-crop. Install it with:

npm install react-image-crop
Enter fullscreen mode Exit fullscreen mode

Then create a crop component:

// components/ImageCrop.js
import { useState } from 'react';
import ReactCrop from 'react-image-crop';
import 'react-image-crop/dist/ReactCrop.css';

export default function ImageCrop({ src, onCropComplete }) {
  const [crop, setCrop] = useState({ aspect: 16 / 9 });

  const handleComplete = (crop) => {
    onCropComplete(crop);
  };

  return (
    <div>
      <ReactCrop
        src={src}
        crop={crop}
        onChange={(newCrop) => setCrop(newCrop)}
        onComplete={handleComplete}
      />
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

This component displays the uploaded image with a crop selection. When the user completes the crop, it sends the crop data (which you can later use as a “mask” for erasing) back via the onCropComplete callback.

Step 3: Creating the Replacement Description Form

Users need to specify what they want to replace the erased area with. Create a simple text input component:

// components/ReplacementForm.js
import { useState } from 'react';

export default function ReplacementForm({ onSubmit }) {
  const [description, setDescription] = useState('');

  const handleSubmit = (e) => {
    e.preventDefault();
    if (description.trim()) {
      onSubmit(description);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>
        Describe the replacement content:
        <input
          type="text"
          value={description}
          onChange={(e) => setDescription(e.target.value)}
          placeholder="e.g., a blue sky, a mountain landscape..."
          style={{ width: '100%', margin: '0.5rem 0' }}
        />
      </label>
      <button type="submit">Generate</button>
    </form>
  );
}
Enter fullscreen mode Exit fullscreen mode

This component collects a text description that will be sent along with the image and crop data.

Step 4: Integrating with the AI Service

For demonstration purposes, we’ll use a mock API endpoint that simulates the AI manipulation. Create an API route in Next.js at /pages/api/erase-replace.js:

// pages/api/erase-replace.js
export default async function handler(req, res) {
  if (req.method === 'POST') {
    // In a real scenario, you would process the image file, crop data,
    // and description here, then pass them to an AI service.
    // For now, we simulate a delay and return a placeholder image URL.
    await new Promise((resolve) => setTimeout(resolve, 2000));

    res.status(200).json({
      resultImageUrl: 'https://via.placeholder.com/600x400?text=AI+Generated+Image',
    });
  } else {
    res.status(405).json({ message: 'Method not allowed' });
  }
}
Enter fullscreen mode Exit fullscreen mode

This mock endpoint waits for 2 seconds and then returns a placeholder image URL. In production, replace this with your AI service integration.

Step 5: Building the Main Page

Now, tie everything together in a main page component. This page will allow the user to upload an image, select the area to erase, add a replacement description, and finally display the manipulated result.

// pages/index.js
import { useState } from 'react';
import ImageUpload from '../components/ImageUpload';
import ImageCrop from '../components/ImageCrop';
import ReplacementForm from '../components/ReplacementForm';

export default function Home() {
  const [uploadedFile, setUploadedFile] = useState(null);
  const [cropData, setCropData] = useState(null);
  const [description, setDescription] = useState('');
  const [resultUrl, setResultUrl] = useState(null);
  const [loading, setLoading] = useState(false);

  const handleUpload = (file) => {
    setUploadedFile(file);
    setResultUrl(null); // Reset previous result when a new image is uploaded
  };

  const handleCropComplete = (crop) => {
    setCropData(crop);
  };

  const handleFormSubmit = async (desc) => {
    setDescription(desc);
    setLoading(true);

    // Create form data to send the image, crop data, and description
    const formData = new FormData();
    formData.append('image', uploadedFile);
    formData.append('cropData', JSON.stringify(cropData));
    formData.append('description', desc);

    const res = await fetch('/api/erase-replace', {
      method: 'POST',
      body: formData,
    });

    const data = await res.json();
    setResultUrl(data.resultImageUrl);
    setLoading(false);
  };

  return (
    <div style={{ padding: '2rem' }}>
      <h1>AI-Powered Erase and Replace Tool</h1>

      <section style={{ marginBottom: '2rem' }}>
        <h2>1. Upload an Image</h2>
        <ImageUpload onUpload={handleUpload} />
      </section>

      {uploadedFile && (
        <section style={{ marginBottom: '2rem' }}>
          <h2>2. Select the Area to Erase</h2>
          <ImageCrop src={URL.createObjectURL(uploadedFile)} onCropComplete={handleCropComplete} />
        </section>
      )}

      {cropData && (
        <section style={{ marginBottom: '2rem' }}>
          <h2>3. Describe the Replacement</h2>
          <ReplacementForm onSubmit={handleFormSubmit} />
        </section>
      )}

      {loading && <p>Processing image...</p>}

      {resultUrl && (
        <section>
          <h2>4. AI-Generated Result</h2>
          <img src={resultUrl} alt="Result" style={{ maxWidth: '100%' }} />
        </section>
      )}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

In this main component, we:

  • Handle the image upload and display a preview.
  • Allow the user to select a crop (i.e., the region to be erased).
  • Accept a text description for the replacement.
  • Send the data to our API endpoint.
  • Display the resulting AI-manipulated image.

Final Touches and Conclusion

You now have a basic AI-powered erase and replace tool using Next.js and React! Here are a few ideas to further improve your project:

  • Improve the Masking: Instead of using a crop tool, consider integrating a drawing tool (e.g., fabric.js) for free-form selections.
  • Enhance the AI Integration: Replace the mock API with a real AI service that can process the image and generate content dynamically.
  • User Experience: Add error handling, progress indicators, and mobile responsiveness to polish the user interface.
  • Performance: Optimize image uploads and processing, possibly leveraging serverless functions or background processing.

This project demonstrates how you can blend modern web development with AI-powered image editing to create powerful creative tools. With Next.js handling both server-side operations and client-side interactivity, you can easily scale and refine this application for production use.

Happy coding!

Jetbrains image

Build Secure, Ship Fast

Discover best practices to secure CI/CD without slowing down your pipeline.

Read more

Top comments (0)

Sentry image

Make it make sense

Only the context you need to fix your broken code with Sentry.

Start debugging →

👋 Kindness is contagious

If you found this post useful, please drop a ❤️ or leave a kind comment!

Okay