GithubHelp home page GithubHelp logo

ksubileau / color-thief-php Goto Github PK

View Code? Open in Web Editor NEW
632.0 24.0 64.0 3.77 MB

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

License: MIT License

PHP 100.00%
php color-palette imagick gd image-processing dominant-colors

color-thief-php's Introduction

Color Thief PHP

Latest Stable Version Build Status GitHub issues Packagist License

A PHP class for grabbing the color palette from an image. Uses PHP and GD, Imagick or Gmagick 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 >= 7.2 or >= PHP 8.0
  • Fileinfo extension
  • 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, GIF and WEBP 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, $outputFormat='array', $adapter = null])

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.

By default, color is returned as an array of three integers representing red, green, and blue values. You can choose another output format by passing one of the following values to the $outputFormat argument :

  • rgb : RGB string notation (ex: rgb(253, 42, 152)).
  • hex : String of the hexadecimal representation (ex: #fd2a98).
  • int : Integer color value (ex: 16591512).
  • array : Default format (ex: array[253, 42, 152]).
  • obj : Instance of ColorThief\Color, for custom processing.

The optional $adapter argument lets you choose a preferred image adapter to use to load the image. By default, the adapter is automatically chosen based on the available extensions and the type of $sourceImage (e.g. Imagick is used if $sourceImage is an Imagick instance). You can pass one of the Imagick, Gmagick or Gd string to force the use of the corresponding underlying image extension. For advanced usage, you can even pass an instance of any class implementing the AdapterInterface interface to use a custom image loader.

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, $outputFormat='array', $adapter = null])

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

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

Credits

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.

color-thief-php's People

Contributors

chellem avatar crishoj avatar furey avatar grachov avatar jbboehr avatar kispocok avatar ksubileau avatar moerlin avatar mreiden avatar othmar52 avatar red-led avatar rewmike avatar simonschaufi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

color-thief-php's Issues

GMagick support

Would you be so kind as to support graphics magick in the future? Thank you.

Colors are differents between the PHP and the JS version of Color Thief

With some images, the dominant color or palette could be very different from the original JS version.

For exemple, with the attached image, Color Thief PHP gives rgb(180, 164, 118) as dominant color (beige), while Color Thief JS gives rgb(30, 36, 19) (dark green), a more accurate color.

bug_camera_1500x1000

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 !

How to use it outside Yii & without composer

It is not an issue, but just a question,

It is an awesome library, good job :) , but how to use this library outside Yii & without composer? I mean is it possible to use it in any kind of PHP projects and how?

Thanks.

Palette sometimes returns 256 for channels

For this image, the getPalette method returns 256 for the blue channel in colors 8 and 9

  ...
  [7]=>
  array(3) {
    [0]=>
    int(248)
    [1]=>
    int(252)
    [2]=>
    int(256)
  }
  [8]=>
  array(3) {
    [0]=>
    int(248)
    [1]=>
    int(252)
    [2]=>
    int(256)
  }
}

For this one it returns 256 in the red channel.

The channel value should always be <= 255.

limit returned colors

This work is just awesome, I got only a problem where my graphic design doesn't allow colors lighter than a defined amount. So do you have a solution that if the dominant color was returned as white or a very bright color so that I can ignore it and go for the next dominant color in a pallet?
or just passing another argument to ignore and not include colors brighter than the argument in the returned pallet.

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;
}

Transparent or blank images

Is correct to throw an error if the image is transparent or blank?

Why cannot return an empty array instead of throwing an error?

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));
});

}

Support PHP 8.x

  • Add tests against PHP 8.x
  • Update composer & README
  • Support objects instead of resources (see #48)

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?

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?

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

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

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.

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)...

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.

Server crash on Windows with relative paths

I use this library without problems 6 months ago on Codeigniter with manual includes, but now I add it to composer and server crash on loop when I try to use it on my localhost.

Server details:

  • ColorThief version 1.3.1
  • PHP Version 7.1.11 x64 Thread Safe
  • Apache/2.4.25 (Win64)

No errors showed, just crash the server when I call a function from the library:

ColorThief::getColor('assets/image/example.jpg')

Tested other composer libraries without problems.

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?

Add absolute $quality option

It would be great if the $quality could also be absolute. I'd like to set it to a static value like 10000 meaning it would take the same time and memory regardless of picture size.

Drop support for PHP 5 ?

With the recent release of PHP 8, the 5.x branch is getting really old, so it's time to embrace the cool new features of PHP>=7!

  • Stop testing against PHP 5
  • Remove code specifically dealing with PHP 5 if any
  • Add PHP 7 specific syntax features like type-hinting
  • Require PHP 7.0 or even 7.2 or higher
  • Upgrade PHPUnit

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.