Grabs the dominant color or a representative color palette from an image. Uses PHP and GD, Imagick or Gmagick.

Overview

Color Thief PHP

Latest Stable Version Build Status GitHub issues HHVM Packagist License

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.

See examples

Requirements

  • PHP >= 5.4 or >= PHP 7.0
  • One or more PHP extensions for image processing:
    • GD >= 2.0
    • Imagick >= 2.0 (but >= 3.0 for CMYK images)
    • Gmagick >= 1.0
  • Supports JPEG, PNG and GIF images.

How to use

Install via Composer

The recommended way to install Color Thief is through Composer:

composer require ksubileau/color-thief-php

Get the dominant color from an image

require_once 'vendor/autoload.php';
use ColorThief\ColorThief;
$dominantColor = ColorThief::getColor($sourceImage);

The $sourceImage variable must contain either the absolute path of the image on the server, a URL to the image, a GD resource containing the image, an Imagick image instance, a Gmagick image instance, or an image in binary string format.

ColorThief::getColor($sourceImage[, $quality=10, $area=null])
returns array(r: num, g: num, b: num)

This function returns an array of three integer values, corresponding to the RGB values (Red, Green & Blue) of the dominant color.

You can pass an additional argument ($quality) to adjust the calculation accuracy of the dominant color. 1 is the highest quality settings, 10 is the default. But be aware that there is a trade-off between quality and speed/memory consumption ! If the quality settings are too high (close to 1) relative to the image size (pixel counts), it may exceed the memory limit set in the PHP configuration (and computation will be slow).

You can also pass another additional argument ($area) to specify a rectangular area in the image in order to get dominant colors only inside this area. This argument must be an associative array with the following keys :

  • $area['x'] : The x-coordinate of the top left corner of the area. Default to 0.
  • $area['y'] : The y-coordinate of the top left corner of the area. Default to 0.
  • $area['w'] : The width of the area. Default to the width of the image minus x-coordinate.
  • $area['h'] : The height of the area. Default to the height of the image minus y-coordinate.

Build a color palette from an image

In this example, we build an 8 color palette.

require_once 'vendor/autoload.php';
use ColorThief\ColorThief;
$palette = ColorThief::getPalette($sourceImage, 8);

Again, the $sourceImage variable must contain either the absolute path of the image on the server, a URL to the image, a GD resource containing the image, an Imagick image instance, a Gmagick image instance, or an image in binary string format.

ColorThief::getPalette($sourceImage[, $colorCount=10, $quality=10, $area=null])
returns array(array(num, num, num), array(num, num, num), ... )

The $colorCount argument determines the size of the palette; the number of colors returned. If not set, it defaults to 10.

The $quality and $area arguments work as in the previous function.

Credits and license

Author

by Kevin Subileau kevinsubileau.fr

Based on the fabulous work done by Lokesh Dhakar lokeshdhakar.com twitter.com/lokesh

Thanks

  • Lokesh Dhakar - For creating the original project.
  • Nick Rabinowitz - For creating quantize.js.

License

Licensed under the Creative Commons Attribution 2.5 License

  • Free for use in both personal and commercial projects.
  • Attribution requires leaving author name, author homepage link, and the license info intact.
Comments
  • Clearly dominant color is not extracted

    Clearly dominant color is not extracted

    Consider the following image:

    margrethe-hjort-hay-2018-margrethes-perler-indbundet-bog

    A visual inspection leads me to believe that the dominant color is yellow:

    image

    However, this color is not among the dominant colors extracted by ColorThief:

    image

    At first I thought the bright yellow was misidentified as white-ish and thus discarded. However, in a test case, isNonWhite returns true for (253, 230, 44)...

    bug 
    opened by crishoj 10
  • Handle GD warnings on loading corrupted images in GDImageAdapter

    Handle GD warnings on loading corrupted images in GDImageAdapter

    a sliMpd user reported an error caused by color-thief-php. Unfortunately i was not able to reproduce it but in theory this changes should do the trick!?

    bug 
    opened by othmar52 6
  • leaking memory while processing many files

    leaking memory while processing many files

    Have encountered many memory errors while processing a directory of many files (3188 jpegs total). Memory usage steadily increases when ColorThief::getPalette is called until a large file causes a memory error. Profiling using pecl memprof shows that the most memory usage is occuring within color thief.

    On my machine, adding the following appears to have improved the ability for PHP to garbage collect:

    • static::getPalette $pixelArray = null;
    • static::quantize $histo = null;

    See below for placement. Still testing to confirm.

    public static function getPalette($sourceImage, $colorCount = 10, $quality = 10, array $area = null)
    {
        // short-circuit
        if ($colorCount < 2 || $colorCount > 256) {
            throw new \InvalidArgumentException("The number of palette colors must be between 2 and 256 inclusive.");
        }
        // short-circuit
        if ($quality < 1) {
            throw new \InvalidArgumentException("The quality argument must be an integer greater than one.");
        }
    
        $pixelArray = static::loadImage($sourceImage, $quality, $area);
        if (!count($pixelArray)) {
            throw new \RuntimeException("Unable to compute the color palette of a blank or transparent image.", 1);
        }
    
        // Send array to quantize function which clusters values
        // using median cut algorithm
        $cmap = static::quantize($pixelArray, $colorCount);
        $palette = $cmap->palette();
    
        $pixelArray = null;
        return $palette;
    }
    
    private static function quantize($pixels, $maxcolors)
    {
        // short-circuit
        if (! count($pixels) || $maxcolors < 2 || $maxcolors > 256) {
            // echo 'wrong number of maxcolors'."\n";
            return false;
        }
    
        $histo = static::getHisto($pixels);
    
        // check that we aren't below maxcolors already
        //if (count($histo) <= $maxcolors) {
            // XXX: generate the new colors from the histo and return
        //}
    
        $vbox = static::vboxFromHistogram($histo);
    
        $pq = new PQueue(function ($a, $b) {
            return ColorThief::naturalOrder($a->count(), $b->count());
        });
        $pq->push($vbox);
    
        // first set of colors, sorted by population
        static::quantizeIter($pq, self::FRACT_BY_POPULATIONS * $maxcolors, $histo);
    
        // Re-sort by the product of pixel occupancy times the size in color space.
        $pq->setComparator(function ($a, $b) {
            return ColorThief::naturalOrder($a->count() * $a->volume(), $b->count() * $b->volume());
        });
    
        // next set - generate the median cuts using the (npix * vol) sorting.
        static::quantizeIter($pq, $maxcolors - $pq->size(), $histo);
    
        // calculate the actual colors
        $cmap = new CMap();
    
        for ($i = $pq->size(); $i > 0; $i--) {
            $cmap->push($pq->pop());
        }
        $histo = null;
    
        return $cmap;
    }
    
    opened by patsplat 6
  • Performance improvements.

    Performance improvements.

    Speeds things up considerably and uses quite a bit less memory when testing the vegetables_1500x995.png test image.

    Basic Symfony stopwatch testing says this is faster than the javascript version. While I hesitate to compare numbers since the hardware and OS is different between my laptop and my dev server, it is much improved. I think the original timing was around 1000ms. The javascript version gets about 490ms on their drag-and-drop demo and this is now getting around 110ms when timing ColorThief::getPalette($thiefImage, 10, 10) which I think is a fair comparison at comparing a quality of every 10 pixels. Using a quality of 1 pixel and timing ColorThief::getPalette($thiefImage, 10, 1) averages about 520ms.

    Memory usage is also drastically improved with stopwatch reporting 2MB and the symfony dev toolbar shows the page using 8MB. I think this was over 20MB previously.

    opened by mreiden 5
  • calling `getColor()` runs forever

    calling `getColor()` runs forever

    first of all: thank you for this lib!
    i experienced a freezing in one of my applictions when calling \ColorThief\ColorThief::getColor($absolutePath, $quality)
    after some debugging i found out that ColorThief did never exit a while loop
    this fixed the issue for me

    --- ksubileau/color-thief-php/src/ColorThief/ColorThief.php     2022-08-21 17:16:32.600014736 +0200
    +++ "ksubileau/color-thief-php/src/ColorThief/ColorThief copy.php"      2022-08-21 17:14:31.940025874 +0200
    @@ -448,6 +448,7 @@
             $nIterations = 0;
     
             while ($nIterations < self::MAX_ITERATIONS) {
    +            ++$nIterations;
                 if ($nColors >= $target) {
                     return;
                 }
    @@ -460,7 +461,6 @@
     
                 if (!$vBox->count()) { /* just put it back */
                     $priorityQueue->push($vBox);
    -                ++$nIterations;
                     continue;
                 }
                 // do the cut
    

    EDIT
    i did not try to reproduce this in a vanilla scenario but the problematic file seems to be this one (extracted from id3 tags)
    c48c2e39121_0__raw0853bcccddde5b5b44b64239219c17bd_par52b4fbd9e2256843fcdbe9d1f35f2875

    bug 
    opened by othmar52 4
  • Simplify color storage to always use 8 bits per color.

    Simplify color storage to always use 8 bits per color.

    It doesn't save memory to use fewer bits since they're stored as integers anyway. Zero the least significant bits (keep 5 most significant bits) for everything other than pixelArray. I found it confusing to get the original color back where you needed to know to shift things by the least significant bits dropped.

    This way you decide how many significant bits to keep when calling getColorIndex and don't need to remember when you want the colors back via getColorsFromIndex.

    opened by mreiden 4
  • fatal error on solid white image

    fatal error on solid white image

    Hi, I'm getting a crash when getting the color of an pure white image

    I've tried other solid colors and had no seen any problems so far.

    The test image is here

    Fatal error: Call to a member function palette() on a non-object in .../color-thief-php/ColorThiefPHP.php on line 380
    
    Call Stack:
        0.0002     331608   1. {main}() .../color_dominant_cron.php:0
        0.0055     707948   2. ColorThiefPHP::getColor() .../color_dominant_cron.php:20
        0.0055     708036   3. ColorThiefPHP::getPalette() .../color-thief-php/ColorThiefPHP.php:288
    
    bug 
    opened by ceap80 4
  • Performance improvements

    Performance improvements

    Currently, it seems unfortunately that the Javascript version is quite a lot faster and more efficient than this PHP port.

    As I'm not a PHP optimization specialist, any proposal (comment or pull request) in order to improve performance (memory consumption and/or computation time) is welcomed !

    feature-request 
    opened by ksubileau 4
  • Image with single histogram bucket causes invalid VBox->volume

    Image with single histogram bucket causes invalid VBox->volume

    An image that fits in a single histogram bucket (single color image) causes VBox->volume to be invalid and negative (instead of 1) due to not setting rgbMax in addition to rgbMax. This leaves rgbMax at 0 causing VBox to compute a negative and incorrect volume when calculated as $this->volume = (($this->r2 - $this->r1 + 1) * ($this->g2 - $this->g1 + 1) * ($this->b2 - $this->b1 + 1));

    bug 
    opened by mreiden 3
  • Load images from binary string

    Load images from binary string

    Hi Devs,

    I would like to use Color-Thief to analyse image colors. My pictures are based on remote CDN(s) furthermore a few of them are protected. So I can't reach them with getImageSize. I am able to grab them with CURL, but I don't want to copy-paste them.

    It would be nice if I can load images from binary string.

    It's hard to extend the whole codebase, because ImageLoader functions are protected and hardcoded into the logic.

    What do you think?

    feature-request 
    opened by kisPocok 3
  • How i can use this class in my page?

    How i can use this class in my page?

    Hi,

    Sorry for the noob question, but how i can use this class in my project? i did create an php file and added these lines in to it:

    require_once 'ColorThief.php';
    
    $sourceImage = '1.jpg';
    
    use ColorThief\ColorThief;
    $palette = ColorThief::getPalette($sourceImage, 8);
    

    then i got this error:

    Fatal error: Class 'ColorThief\Image\ImageLoader' not found in C:\UwAmp\www\ColorThief\ColorThief.php on line 182
    --
    
    
    1 | 0.0013 | 133520 | {main}( ) | ...\show.php:0
    2 | 0.0033 | 198184 | ColorThief\ColorThief::getPalette( ) | ...\show.php:8
    3 | 0.0033 | 198392 | ColorThief\ColorThief::loadImage( ) | ...\ColorThief.php:140
    

    Could you please help me to get this fixed?

    question 
    opened by IMPGTX 2
  • PHP Exploit Warning

    PHP Exploit Warning

    Our hosting provider scans their servers for known exploits from time to time. warned us about a know exploit and blocked access to the following file within color-thief-php:

    src/ColorThief/Image/Adapter/AbstractAdapter.php

    The reason given is

    # Known exploit = [Fingerprint Match (fp)] [PHP Exploit [P2128]]

    Did anyone else noticed this as well? Anything we can do? Or can this be updated/fixed in the lib?

    Cheers.

    question 
    opened by superflausch 1
  • Why disregarding bright colors?

    Why disregarding bright colors?

    Current implementation disregards all the colors that are rgb(250, 250, 250) or brighter (see THRESHOLD_WHITE variable).

    This can be useful for some users. Let's say you want to get a dominant color of a dress for an online shop and all the pictures are on white background.

    But why this is default behaviour? Why this can't be changed? Why there's nothing about it in the description?

    I wish by default all the bright colors also would be considered by algorithm, but user can explicitly add a parameter like $threshhold_white to exclude them.

    opened by skripnik 0
  • Add libvips support

    Add libvips support

    Feature: Add libvips support for image processing. https://github.com/libvips/libvips https://github.com/libvips/php-vips

    It would be convenient, because now I have to use GD or Imagick to work with Color Thief PHP, while the rest of the processing is done by the libvips.

    feature-request 
    opened by romanzks 2
  • Different colours returned per-machine

    Different colours returned per-machine

    • PHP: 7.3
    • OS: Comparing MacOS vs Ubuntu Docker Image

    Given this image:

    image

    I'm getting different colours between running locally and in our testing environment.

    On my Mac, the colours I get are:

    • #8B849F
    • #273647
    • #EBB6B4
    • #4E3C3E
    • #987132

    Whereas on our testing environment (which is a Ubuntu Docker image, running from CircleCI) I get:

    • #F7ACB3
    • #9AA7C7
    • #B9752E
    • #FDD58D
    • #353A71

    If we visualise these colours, we can see that they look okay. On the right, I've ordered colours to where they're most similar.

    image

    What would be the reason for seeing different colours?

    opened by jbrooksuk 0
  • Can get the color ratio

    Can get the color ratio

    Update file CMap.php:28

    public function palette() {

    $total = array_sum($this->vboxes->map(function ($x) {
        return $x['vbox']->count();
    }));
    
    return $this->vboxes->map(function ($vb) use ($total) {
        return array($vb['color'], intval($vb['vbox']->count() / floatval($total) * 100));
    });
    

    }

    opened by songyongshuo 0
  • Get dominance percentages for the palette?

    Get dominance percentages for the palette?

    Would it be possible to get some sort of dominance percentage for each color returned in the palette, so I can choose the second most dominant color for example?

    feature-request 
    opened by SeBsZ 2
Releases(v2.0.1)
  • v2.0.1(Nov 12, 2022)

  • v2.0.0(Mar 12, 2022)

    New features

    • PHP 8 compatibility (see #48 and #50, thank @Agapanthus).
    • Add support for reading WebP images (see #45, thank @mreiden).
    • Add support for multiple output color formats (RGB, hexadecimal, integer, array or instances of ColorThief\Color class).
    • Add support for image adapter selection. You can now choose which image extension to use between GD, Imagick or Gmagick, or provide a custom image adapter.

    Bug fix

    • Fix bug where getPalette() does not always return the requested amount of colors (see #5).

    Breaking changes

    • Drop support for PHP 5.x, 7.0 and 7.1, now require 7.2+.
    • Reworked exceptions so that all exceptions now inherit from ColorThief\Exception\Exception. Migrating from 1.x may require tweaking exception handling in calling code to avoid unhandled exceptions or preserve error handling logic. See 1bf90f40 for details.

    Noticeable changes

    • Switch to MIT license.
    • Fileinfo extension is now required.
    • Reworked some internal image loading logic.
    Source code(tar.gz)
    Source code(zip)
  • v1.4.1(Oct 31, 2018)

    • Significant performance improvement. Around 30% faster and between 20 to 50% less memory usage (see #44, thank @mreiden).
    • Fix incorrect palette with single color images (see #41, thank @mreiden).
    Source code(tar.gz)
    Source code(zip)
  • v1.4.0(Aug 30, 2018)

    • Drop support for PHP 5.3, now require 5.4+.
    • Fix incorrect palette with CMYK images using Imagick or Gmagick (see #37, thank @crishoj).
    • Test against PHP 7.2
    Source code(tar.gz)
    Source code(zip)
  • v1.3.1(Dec 18, 2016)

    • Improve handling of corrupted images: throw a RuntimeException if GD fails to load image. (see #30, thank @othmar52).
    • Fix invalid color values under certain circumstances (see #24).
    • Use a PSR-4 autoloader (see #28, thank @jbboehr).
    • Test against PHP 7.1 (see #27, thank @jbboehr).
    Source code(tar.gz)
    Source code(zip)
  • v1.3.0(Jan 17, 2016)

    • Color Thief PHP now officially supports PHP 7 ! (see #19).
    • Add GMagick support (see #15).
    • Add capability to load an image from binary string (see #21).
    • Code rewriting and refactoring, improved documentation (see #22, thank @kisPocok).
    Source code(tar.gz)
    Source code(zip)
  • v1.2.0(Oct 30, 2014)

    • Add support of area targeting (see #12).
    • Fix error with remote images (see #13, thank @rewmike).
    • Fix minor syntax errors (see #14, thank @grachov).
    • Small performance improvements and code cleanup.
    Source code(tar.gz)
    Source code(zip)
  • v1.1.0(Jun 25, 2014)

    • Add support for Imagick and GD resources. In addition to the path or URL of the image, now you can also directly pass the GD resource or Imagick instance to the getColor and getPalette methods (see #10).
    • Fix fatal error whith solid white images. An exception is now thrown in this case, allowing the caller to catch it (see #11).
    • Fix possible undefined offset under certain circumstances.
    • Change error handling policy : throw exceptions in case of errors instead of return false.
    Source code(tar.gz)
    Source code(zip)
Owner
Kevin Subileau
Kevin Subileau
Image optimization / compression library. This library is able to optimize png, jpg and gif files in very easy and handy way. It uses optipng, pngquant, pngcrush, pngout, gifsicle, jpegoptim and jpegtran tools.

Image Optimizer This library is handy and very easy to use optimizer for image files. It uses optipng, pngquant, jpegoptim, svgo and few more librarie

Piotr Śliwa 879 Dec 30, 2022
Auto Image & file upload, resize and crop for Laravel eloquent model using Intervention image

Laravel ImageUp The qcod/laravel-imageup is a trait which gives you auto upload, resize and crop for image feature with tons of customization. Install

QCode.in 708 Dec 22, 2022
A Laravel Gravatar package for retrieving gravatar image URLs or checking the existance of an image.

Gravatar for Laravel 5.x, 6, 7 and 8 Installation First, pull in the package through Composer via the command line: composer require creativeorange/gr

Creativeorange 477 Dec 1, 2022
This plugin adds a new image style for the Core Image block.

This plugin adds a new image style for the Core Image block. Introduction How to use? Go to Gutenberg Editor and add a image block. e.g. Add new image

Mahesh Waghmare 3 Feb 17, 2022
PHP library to easily edit image with GD extension. Resize, crop, merge, draw, and many more options !

PHP Image Editor PHP library to easily edit image with GD extension. Resize, crop, merge, draw, and many more options ! ✨ Supporting ⭐ Star this repos

Franck Alary 17 Nov 13, 2022
image sharing site made in PHP just for fun and freetime

2bart image sharing site made in PHP just for fun and freetime To-do list: upload system [DONE] ✔️ views system [DONE] ✔️ image list system [DONE] ✔️

goom 1 Oct 22, 2021
A simple page view counter that store data as text and shows data as a PNG image

Image Counter A simple page view counter that store data as text and shows the counter as a PNG image.

Victor Ribeiro 10 Apr 19, 2022
Picasso is a Laravel Image Management and Optimization Package

Picasso is a Laravel Image Management and Optimization Package. Define image dimensions and options, store uploaded image in multiple dimensions with or without a watermark and retrieve optimized images on your website when needed.

Laravelista 82 Nov 24, 2022
The Gregwar\Image class purpose is to provide a simple object-oriented images handling and caching API

Gregwar's Image class The Gregwar\Image class purpose is to provide a simple object-oriented images handling and caching API. Installation With compos

Grégoire Passault 958 Dec 29, 2022
PHP Image Manipulation

Intervention Image Intervention Image is a PHP image handling and manipulation library providing an easier and expressive way to create, edit, and com

null 13k Jan 3, 2023
PHP 5.3 Object Oriented image manipulation library

Imagine Tweet about it using the #php_imagine hashtag. Image manipulation library for PHP 5.3 inspired by Python's PIL and other image libraries. Requ

Bulat Shakirzyanov 4.3k Jan 6, 2023
🌄 Perceptual image hashing for PHP

ImageHash A perceptual hash is a fingerprint of a multimedia file derived from various features from its content. Unlike cryptographic hash functions

Jens Segers 1.9k Dec 28, 2022
php-gd based image templates

gdaisy A highly experimental image templating system based on PHP-GD to dynamically generate image banners and covers. Installation 1. Require erikahe

Erika Heidi 67 Nov 22, 2022
This is an image manipulation REST API written in PHP Laravel Framework

Laravel Image Manipulation REST API Demo Here is fully working Demo: https://www.lobiimages.com/ You have to register first in order to generate acces

TheCodeholic 42 Dec 15, 2022
PHP Thumb is a light-weight image manipulation library aimed at thumbnail generation

PHP Thumb NOTICE - This project was recently updated to 2.0 and is PSR-0 compliant and supports Composer integration. Some parts of the documentation

Ian Selby 985 Dec 4, 2022
Image manager extension for the Yii PHP framework.

yii-imagemanager Image manager extension for the Yii PHP framework. Introduction I started this project to reduce the need for boilerplate code when w

Christoffer Niska 23 Aug 28, 2020
Wonderfully easy on-demand image manipulation library with an HTTP based API.

Glide Glide is a wonderfully easy on-demand image manipulation library written in PHP. Its straightforward API is exposed via HTTP, similar to cloud i

The League of Extraordinary Packages 2.4k Dec 19, 2022
:racehorse: find the size of an image without downloading the whole file. Supports batch requests.

FasterImage FasterImage finds the dimensions or filetype of a remote image file given its uri by fetching as little as needed, based on the excellent

Will Washburn 58 Nov 30, 2022
Extract colors from an image like a human would do.

ColorExtractor Extract colors from an image like a human would do. Install Via Composer $ composer require league/color-extractor:0.3.* Usage require

The League of Extraordinary Packages 1.2k Jan 1, 2023