How to extract prominent colors from an image in Symfony 3

How to extract prominent colors from an image in Symfony 3

The user experience is one of the most important things to consider when you build your app,they should have the option to change the UI color according to their wish, that will make your application unique and interesting for your user. An awesome feature that you should end up implementing would be, if you allow your users to upload profile pictures, to set the UI color according to the dominant color of the profile picture as Github does. You can extract the color from images easily in the browser using JavaScript too, however the implementation in the server side may be easier than dealing with it in the browser and caring about the compatibility in different browsers.

In this article you are going to learn how to extract the dominant colors from an image (or custom color palette) using 3 different PHP libraries in your Symfony 3 project.

A. Using ColorExtractor

The first library ColorExtractor is an useful library that extract the colors from an image like a human would do.

Installation

To install the Color Extractor library in your project, open a terminal, switch to the directory of your project and install it using:

composer require league/color-extractor:0.3.*

Alternatively, you can install it manually by modifying the composer.json file of your project and adding the library as a dependency:

{
    "require": {
        "league/color-extractor": "0.3.*"
    }
}

Then execute composer install and you're ready to use it. For more information about the library, please visit the official Github repository here.

Extracting most important colors

Color Extractor creates a color palette at the moment you provide an image path to the static method fromFilename. This palette contains all the colors in the image as an array with integers, every integer represents a color, therefore you need to use the fromInToHex method of the Color class:

<?php

namespace AppBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

/**
 * Import Library required classes
 */
use League\ColorExtractor\Color;
use League\ColorExtractor\ColorExtractor;
use League\ColorExtractor\Palette;

class DefaultController extends Controller
{
    /**
     * @Route("/", name="homepage")
     */
    public function indexAction(Request $request)
    {
        // The relative or absolute path to the image file
        $imagePath = $this->get('kernel')->getRootDir() . '/../web/bird.png';
        
        // Create the palette of the image
        $palette = Palette::fromFilename($imagePath);

        // Create an instance of the extractor
        $extractor = new ColorExtractor($palette);

        // Extract only the 5 representative colors in the image
        $colors = $extractor->extract(5);

        // An array to store the hexadecimal colors
        $hexColors = [];

        // Loop through the 5 representative colors (in integer format)
        foreach($colors as $color) {

            // Convert the number to its hex representation and add to the $hexColors array
            array_push($hexColors , Color::fromIntToHex($color));
        }

        // ["#FF7B16","#DFC017","#679C0C","#E60B11","#186108"]
        return new Response(json_encode($hexColors));
    }
}

Extracting all colors

You can loop through the entire palette instead to retrieve all the colors in the image (note that the size of array will be pretty huge according to the image):

<?php

namespace AppBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

/**
 * Import Library required classes
 */
use League\ColorExtractor\Color;
use League\ColorExtractor\ColorExtractor;
use League\ColorExtractor\Palette;

class DefaultController extends Controller
{
    /**
     * @Route("/", name="homepage")
     */
    public function indexAction(Request $request)
    {
        // The relative or absolute path to the image file
        $imagePath = $this->get('kernel')->getRootDir() . '/../web/bird.png';
        
        // Create the palette of the image
        $palette = Palette::fromFilename($imagePath);

        // Create an instance of the extractor
        $extractor = new ColorExtractor($palette);

        // An array to store the hexadecimal colors
        $hexColors = [];

        // Loop through the 5 representative colors (in integer format)
        foreach($palette as $color => $count) {

            // Convert the number to its hex representation and add to the $hexColors array
            array_push($hexColors , Color::fromIntToHex($color));
        }

        // ["#FF7B16","#DFC017","#679C0C","#E60B11","#186108", .......]
        return new Response(json_encode($hexColors));
    }
}

B. Using ImagePalette

ImagePalette is used to extract a color palette from a given image. Aside from being a native PHP implementation, ImagePalette differs from many palette extractors as it works off a white list color palette.

Installation

To install this library on your project, open a terminal, switch to the directory of your project and install it using:

composer require brianmcdo/image-palette

Alternatively you can modify your composer.json file and add the library as a dependency manually:

{
    "require": {
        "brianmcdo/image-palette": "^2.0"
    }
}

And then run composer install. For more information about this library, please visit the official Github repository here.

Extracting colors

The extraction of colors with this library is pretty simple, just import the ImagePalette class and then proceed to create an instance of it. The constructor expects the relative or absolute path of the file to process (it works with external URLs too). Then obtain the palette of colors by accessing the colors property of the created instance:

<?php

namespace AppBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

/**
 * Import the ImagePalette class
 */
use BrianMcdo\ImagePalette\ImagePalette;

class DefaultController extends Controller
{
    /**
     * @Route("/", name="homepage")
     */
    public function indexAction(Request $request)
    {
        // The absolute or relative path of the image
        $imagePath = $this->get('kernel')->getRootDir() . '/../web/bird.png';

        // initiate with image
        $palette = new ImagePalette($imagePath);

        // Get the prominent colors
        // That returns an array of Color objects
        $colors = $palette->colors;

        // Or if you want a specific number of colors, use the getColors method and provide
        // as first argument the number of colors that should be returned
        //$colors = $palette->getColors(7); 

        // You can print the colors in different formats
        foreach ($palette as $color) {
            // Color provides several getters/properties
            dump($color);             // '#ffffdd'
            dump($color->rgbString);  // 'rgb(255,255,221)'
            dump($color->rgbaString); // 'rgba(255,255,221,0.25)'
            dump($color->int);        // 0xffffdd
            dump($color->rgb);        // array(255,255,221)
            dump($color->rgba);       // array(255,255,221,0.25)
        }

        // Return the palette as response
        // ["#ffffdd", "#ff9900" ... ]
        return new Response($palette);
    }
}

C. Using Color Thief

A PHP class for grabbing the color palette from an image. Uses PHP and GD or Imagick libraries to make it happen. It's a PHP port of the Color Thief Javascript library, using the MMCQ (modified median cut quantization) algorithm from the Leptonica library.

Requirements

Unlike the other libraries in this article, Color Thief has some requirements that you meet some requirements:

  • PHP >= 5.3 or >= PHP 7.0
  • GD >= 2.0 and/or Imagick >= 2.0 and/or Gmagick >= 1.0
  • Support JPEG, PNG and GIF images.

If you have GD or Imagick installed on your server, then you can work with this library.

Installation

To install this library open a new terminal, switch to your project directory and install it with the following command:

composer require ksubileau/color-thief-php

Alternatively, you can install it by modifying the composer.json file of your project and adding this library as a dependency:

{
    "require": {
        "ksubileau/color-thief-php": "^1.3"
    }
}

Then run composer install. If you need more information about this library, please visit the official Github repository here.

Creating a palette of colors

You can retrieve a palette of all the dominant colors from the image by using the static getPalette method. This method expects as first argument the absolute or relative path of the image to process and as second argument the maximum numbers of colors that will be extracted:

<?php

namespace AppBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;


/**
 * Import the ColorThief class
 */
use ColorThief\ColorThief;

class DefaultController extends Controller
{
    /**
     * @Route("/", name="homepage")
     */
    public function indexAction(Request $request)
    {
        // The absolute or relative path of the image
        $imagePath = $this->get('kernel')->getRootDir() . '/../web/bird.png';

        // Extract the palette of colors of the image with max. 8 colors
        $palette = ColorThief::getPalette($imagePath, 8);

        // RGB representation of the colors
        // [[221,139,30],[60,100,16],[227,211,181],[196,48,20],[119,141,24],[226,207,32],[84,172,14]]
        return new Response(json_encode($palette));
    }
}

Extracting single color

If you want to extract a single color for example to define the color of the user interface according to the uploaded profile photo of the user, you can make it quick and simple with the static method getColor:

<?php

namespace AppBundle\Controller;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;


/**
 * Import the ColorThief class
 */
use ColorThief\ColorThief;

class DefaultController extends Controller
{
    /**
     * @Route("/", name="homepage")
     */
    public function indexAction(Request $request)
    {
        // The absolute or relative path of the image
        $imagePath = $this->get('kernel')->getRootDir() . '/../web/bird.png';

        // Extract the dominant color of the image
        $dominantColor = ColorThief::getColor($imagePath);
        
        // RGB representation of the color
        //  R         G         B
        // [0 => 196, 1 => 139, 2 => 28 ]
        return new Response(json_encode($dominantColor));
    }
}

Happy coding !

Become a more social person