Image Color Extractor with Python

Building an Image Color Extractor with Flask and JavaScript Preview

Introduction

Have you ever wanted to extract colors from an image using Python? In this tutorial, we'll build a simple Flask-based web app that allows users to upload an image, preview it instantly, and extract its dominant colors using extcolors.

This project will include:
Instant Image Preview using JavaScript
Flask Backend for Image Processing
Dynamic Color Extraction from Images
A Stylish UI with TailwindCSS

By the end, you'll have a fully functional Flask app that extracts colors from an image and displays them in real time.

📌 GitHub Repository: LEO-MAhendra/leo-color007


1. Setting Up the Project

Install Dependencies

First, create a virtual environment and install the required libraries:

pip install flask pillow extcolors

2. Creating the Flask Backend

We'll use Flask to handle image uploads and process the colors using extcolors.

Flask Application (app.py)

import os
import PIL
import extcolors
from flask import Flask, render_template, request

app = Flask(__name__)

UPLOAD_DIRECTORY = "./static/images/"


def get_color(name):
    img = PIL.Image.open(name)
    colors, pixel_count = extcolors.extract_from_image(img)
    rbgvalues = [color[0] for color in colors if isinstance(color, tuple)]
    return rbgvalues


@app.route("/")
def index():
    return render_template("index.html")


@app.route("/upload", methods=["POST"])
def upload():
    if "image" not in request.files:
        return "No file uploaded", 400

    image = request.files["image"]
    allowed_extensions = {"jpg", "jpeg", "png"}
    if image.filename.split(".")[-1].lower() not in allowed_extensions:
        return "Invalid file extension", 400
    if not os.path.exists(UPLOAD_DIRECTORY):
        os.makedirs(UPLOAD_DIRECTORY)
    tempfile = f"temp.{image.filename.split('.')[-1].lower()}"
    fileloc = os.path.join(UPLOAD_DIRECTORY, tempfile)

    image.save(fileloc)
    colors = get_color(fileloc)
    return render_template("index.html", filename=fileloc, values=colors)


if __name__ == "__main__":
    app.run()


3. Building the Frontend

We’ll use TailwindCSS for styling and JavaScript for real-time image preview.

HTML File (templates/index.html)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Color Extractor</title>
    <script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-black text-white min-h-screen flex flex-col">

    <!-- Navbar -->
    <nav class="bg-gray-900 p-6 text-white shadow-lg">
        <h1 class="text-3xl font-extrabold text-center tracking-wide">Color Extractor</h1>
    </nav>

    <div class="container mx-auto mt-8 p-6">
        <div class="mb-6">
            {% with messages = get_flashed_messages(with_categories=true) %}
                {% if messages %}
                    {% for category, message in messages %}
                        <div class="p-4 mb-3 text-white bg-gray-800 rounded-lg shadow-md text-center font-medium">
                            {{ message }}
                        </div>
                    {% endfor %}
                {% endif %}
            {% endwith %}
        </div>

        <!-- Image Preview Box -->
        <div class="flex flex-col items-center L30">
            <div
                id="preview"
                class="w-96 h-60 bg-gray-800 flex items-center justify-center text-gray-400 text-xl rounded-xl shadow-lg border-4 border-gray-700 overflow-hidden transform hover:scale-105 transition duration-300"
                style="background-size: contain; background-repeat: no-repeat; background-position: center;"
            >
                {% if filename %}
                    <script>
                        document.addEventListener("DOMContentLoaded", function () {
                            document.getElementById("preview").style.backgroundImage = "url('{{ filename }}')";
                            document.getElementById("preview").innerHTML = "";
                        });
                    </script>
                {% else %}
                    No Image Uploaded
                {% endif %}
            </div>
        </div>

        <!-- File Upload Form -->
        <div class="mt-8 flex flex-col items-center">
            <form action="/upload" method="POST" enctype="multipart/form-data" class="bg-gray-900 p-8 rounded-xl shadow-lg w-full max-w-md border border-gray-700">
                <input id="imageInput" type="file" name="image" accept="image/jpeg, image/png" class="block w-full p-3 border border-gray-700 rounded-lg mb-4 bg-gray-800 text-white focus:ring-2 focus:ring-white" />
                <input type="submit" value="Upload" class="w-full bg-gray-700 text-white p-3 rounded-lg cursor-pointer hover:bg-gray-600 transition font-semibold" />
            </form>
        </div>

        <!-- RGB Values Display -->
        <div class="mt-8 text-center">
            <h1 class="text-3xl font-bold mb-6 text-white">Extracted RGB Values</h1>
            <div class="grid grid-cols-2 md:grid-cols-4 gap-6">
                {% for val in values %}
                    <div
                        class="p-5 rounded-lg text-white text-center shadow-md font-semibold transform hover:scale-105 transition duration-300 border border-gray-700"
                        style="background-color: rgb{{ val }};"
                    >
                        {{ val }}
                    </div>
                {% endfor %}
            </div>
        </div>
    </div>

    <!-- Footer -->
    <footer class="bg-gray-900 text-white text-center p-6 mt-8 shadow-md L30">
        <h1 class="text-lg font-bold tracking-wider">Developed by LeoMahendra</h1>
    </footer>

    <!-- JavaScript to Handle Image Preview -->
    <script>
        document.addEventListener("DOMContentLoaded", function () {
            const imageInput = document.getElementById("imageInput");
            const previewDiv = document.getElementById("preview");

            imageInput.addEventListener("change", function (event) {
                let file = event.target.files[0];
                if (file) {
                    let reader = new FileReader();
                    reader.onload = function (e) {
                        previewDiv.style.backgroundImage = `url('${e.target.result}')`;
                        previewDiv.style.backgroundSize = "contain";
                        previewDiv.style.backgroundRepeat = "no-repeat";
                        previewDiv.style.backgroundPosition = "center";
                        previewDiv.innerHTML = "";
                    };
                    reader.readAsDataURL(file);
                } else {
                    previewDiv.style.backgroundImage = "none";
                    previewDiv.innerHTML = "No Image Uploaded";
                }
            });
        });
    </script>

</body>
</html>

4. Running the Project

Here's an updated blog post section with Poetry setup, requirements.txt installation, and a reference to your Django environment setup blog.


4. Setting Up the Environment

Before running the Flask app, we need to set up the Python environment.

Option 1: Using Poetry (Recommended)

Since we use Poetry for dependency management, you can install the required dependencies using:

poetry install

If you haven’t set up the environment yet, follow these steps:

poetry init  # Initialize a new Poetry environment
poetry add flask pillow extcolors  # Install required dependencies
poetry shell  # Activate the virtual environment

Option 2: Using a Virtual Environment and requirements.txt

If you prefer a traditional virtual environment, follow these steps:

python -m venv venv  # Create a virtual environment
source venv/bin/activate  # Activate (Mac/Linux)
venv\Scripts\activate  # Activate (Windows)
pip install -r requirements.txt  # Install dependencies

Your requirements.txt should include:

blinker==1.6.2
click==8.1.3
colorama==0.4.6
convcolors==2.2.0
extcolors==1.0.0
Flask==2.3.2
itsdangerous==2.1.2
Jinja2==3.1.2
MarkupSafe==2.1.3
Pillow==9.5.0
Werkzeug==2.3.6
gunicornOnce the environment is set up, start your Flask app with:
python app.py

Then open http://127.0.0.1:5000/ in your browser and test the upload functionality.


Django Environment Setup (For Future Reference)

If you are also working with Django, you can follow my blog on setting up the Django environment with Poetry:
🔗 Django Commands and Environment Setup                

In this tutorial, we built a Flask web app that extracts colors from an image using extcolors.
We also added instant preview functionality using JavaScript, ensuring a smooth user experience. 🚀

🔗 GitHub Repository: LEO-MAhendra/leo-color007

Post a Comment

0 Comments