* @license http://opensource.org/licenses/gpl-license.php GNU Public License * @link https://github.com/ivuorinen/palette */ namespace ivuorinen\Palette; /** * Palette * * @category Default * @package Palette * @author Ismo Vuorinen * @license http://opensource.org/licenses/gpl-license.php GNU Public License * @link https://github.com/ivuorinen/palette * @since 0.1.0 **/ class Palette { /** * Precision of palette, higher is more precise * @var int */ public $precision; /** * Number of colors to return * @var int */ public $returnColors; /** * Array of colors we use internally * @var array */ public $colorsArray; /** * Full path to image file name * @var string */ public $filename; /** * Destination for .json-file, full path and filename * * @var string **/ public $destination; /** * Constructor * * @param string $filename Full path to image * * @return null * **/ public function __construct($filename = null) { // Define shortcut to directory separator if (! defined('DS')) { define("DS", DIRECTORY_SEPARATOR); } $this->precision = 10; $this->returnColors = 10; $this->colorsArray = array(); $this->filename = $filename; $this->destination = dirname(__FILE__) . DS . 'datafiles' . DS . basename($filename) . '.json'; if (! empty($this->filename)) { $this->run(); } } /** * run the process * * if you want to change parameters you can init new Palette, then change * settings and after that run the palette generation and saving * * @return bool Returns true always */ public function run() { if (empty($this->destination)) { throw new Exception("No destination provided, can't save."); } $this->getPalette(); $this->save(); return true; } /** * getPalette * Returns colors used in an image specified in $filename * * @return array|bool If we get array that has colors return the array **/ public function getPalette() { // We check for input try { if (empty($this->filename)) { return false; } } catch (\Exception $e) { throw new \Exception("Image was not provided"); } // We check for readability try { if (! is_readable($this->filename)) { throw new \Exception("Image {$this->filename} is not readable"); return false; } } catch (\Exception $e) { user_error($e->getMessage(), E_USER_ERROR); } $this->colorsArray = $this->countColors(); if (! empty($this->colorsArray) and is_array($this->colorsArray)) { return $this->colorsArray; } else { return false; } } /** * countColors returns an array of colors in the image * @return array Array of colors sorted by times used */ private function countColors() { $this->precision = max(1, abs((int) $this->precision)); $colors = array(); $size = @getimagesize($this->filename); if ($size === false) { user_error("Unable to get image size data", E_USER_ERROR); return false; } $img = $this->imageTypeToResource(); if (! $img && $img !== null) { user_error("Unable to open: {$this->filename}", E_USER_ERROR); return false; } for ($x = 0; $x < $size[0]; $x += $this->precision) { for ($y = 0; $y < $size[1]; $y += $this->precision) { $thisColor = imagecolorat($img, $x, $y); $rgb = imagecolorsforindex($img, $thisColor); $red = round(round(($rgb['red'] / 0x33)) * 0x33); $green = round(round(($rgb['green'] / 0x33)) * 0x33); $blue = round(round(($rgb['blue'] / 0x33)) * 0x33); $thisRGB = sprintf('%02X%02X%02X', $red, $green, $blue); if (array_key_exists($thisRGB, $colors)) { $colors[$thisRGB]++; } else { $colors[$thisRGB] = 1; } } } arsort($colors); return array_slice($colors, 0, $this->returnColors, true); } /** * save * Get array of colors, json_encode it and save to destination * * @param string $destination Where to save json-file * * @return false **/ public function save() { try { if (empty($this->destination)) { throw new \Exception("No destination given for save"); } } catch (\Exception $e) { user_error($e->getMessage(), E_USER_ERROR); } try { $destination_dir = dirname($this->destination); if (! is_writable($destination_dir)) { throw new \Exception("Destination directory not writable: {$destination_dir}"); } } catch (\Exception $e) { user_error($e->getMessage(), E_USER_ERROR); } try { if (empty($this->colorsArray)) { throw new \Exception("Couldn't detect colors from image"); } } catch (\Exception $e) { user_error($e->getMessage(), E_USER_ERROR); } // Encode for saving $colorsData = json_encode($this->colorsArray); // Save and return the result of save operation file_put_contents($this->destination, $colorsData); if (is_readable($this->destination)) { return true; } else { return false; } } /** * imageTypeToResource returns image resource * * Function takes $this->filename and returns * imagecreatefrom{gif|jpeg|png} for further processing * * @return resource Image resource based on content */ private function imageTypeToResource() { $type = exif_imagetype($this->filename); switch ($type) { case '1': // IMAGETYPE_GIF $img = @imagecreatefromgif($this->filename); break; case '2': // IMAGETYPE_JPEG $img = @imagecreatefromjpeg($this->filename); break; case '3': // IMAGETYPE_PNG $img = @imagecreatefrompng($this->filename); break; default: $image_type_code = image_type_to_mime_type($type); user_error("Unknown image type: {$image_type_code} ({$type}): {$this->filename}"); return false; break; } return $img; } }