This is to be the new HashRU website based on the Aaronweb.net/Kabuki CMS.
		
			
				
	
	
		
			150 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			150 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
/*****************************************************************************
 | 
						|
 * BestColor.php
 | 
						|
 * Contains key class BestColor.
 | 
						|
 *
 | 
						|
 * !!! Licensing?
 | 
						|
 *****************************************************************************/
 | 
						|
 | 
						|
class BestColor
 | 
						|
{
 | 
						|
	private $best;
 | 
						|
 | 
						|
	public function __construct(Image $asset)
 | 
						|
	{
 | 
						|
		// Set fallback color.
 | 
						|
		$this->best = ['r' => 204, 'g' => 204, 'b' => 204]; // #cccccc
 | 
						|
 | 
						|
		// We will be needing to read this...
 | 
						|
		if (!file_exists($asset->getPath()))
 | 
						|
			return;
 | 
						|
 | 
						|
		// Try the arcane stuff again.
 | 
						|
		try
 | 
						|
		{
 | 
						|
			$image = new Imagick($asset->getPath());
 | 
						|
			$width  = $image->getImageWidth();
 | 
						|
			$height = $image->getImageHeight();
 | 
						|
 | 
						|
			// Sample six points in the image: four based on the rule of thirds, as well as the horizontal and vertical centre.
 | 
						|
			$topy    = round($height / 3);
 | 
						|
			$bottomy = round(($height / 3) * 2);
 | 
						|
			$leftx   = round($width / 3);
 | 
						|
			$rightx  = round(($width / 3) * 2);
 | 
						|
			$centery = round($height / 2);
 | 
						|
			$centerx = round($width / 2);
 | 
						|
 | 
						|
			// Grab their colours.
 | 
						|
			$rgb = [
 | 
						|
				$image->getImagePixelColor($leftx, $topy)->getColor(),
 | 
						|
				$image->getImagePixelColor($rightx, $topy)->getColor(),
 | 
						|
				$image->getImagePixelColor($leftx, $bottomy)->getColor(),
 | 
						|
				$image->getImagePixelColor($rightx, $bottomy)->getColor(),
 | 
						|
				$image->getImagePixelColor($centerx, $centery)->getColor(),
 | 
						|
			];
 | 
						|
 | 
						|
			// We won't be needing this anymore, so save us some memory.
 | 
						|
			$image->clear();
 | 
						|
			$image->destroy();
 | 
						|
		}
 | 
						|
		// In case something does go wrong...
 | 
						|
		catch (ImagickException $e)
 | 
						|
		{
 | 
						|
			// Fall back to default color.
 | 
						|
			return;
 | 
						|
		}
 | 
						|
 | 
						|
		// Process rgb values into hsv values
 | 
						|
		foreach ($rgb as $i => $color)
 | 
						|
		{
 | 
						|
			$colors[$i] = $color;
 | 
						|
			list($colors[$i]['h'], $colors[$i]['s'], $colors[$i]['v']) = self::rgb2hsv($color['r'], $color['g'], $color['b']);
 | 
						|
		}
 | 
						|
 | 
						|
		// Figure out which color is the best saturated.
 | 
						|
		$best_saturation = $best_brightness = 0;
 | 
						|
		$the_best_s      = $the_best_v      = ['v' => 0];
 | 
						|
		foreach ($colors as $color)
 | 
						|
		{
 | 
						|
			if ($color['s'] > $best_saturation)
 | 
						|
			{
 | 
						|
				$best_saturation = $color['s'];
 | 
						|
				$the_best_s = $color;
 | 
						|
			}
 | 
						|
			if ($color['v'] > $best_brightness)
 | 
						|
			{
 | 
						|
				$best_brightness = $color['v'];
 | 
						|
				$the_best_v = $color;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		// Is brightest the same as most saturated?
 | 
						|
		$this->best = ($the_best_s['v'] >= ($the_best_v['v'] - ($the_best_v['v'] / 2))) ? $the_best_s : $the_best_v;
 | 
						|
	}
 | 
						|
 | 
						|
	public static function hex2rgb($hex)
 | 
						|
	{
 | 
						|
		return sscanf($hex, '%2X%2X%2X');
 | 
						|
	}
 | 
						|
 | 
						|
	public static function rgb2hex($red, $green, $blue)
 | 
						|
	{
 | 
						|
		return sprintf('%02X%02X%02X', $red, $green, $blue);
 | 
						|
	}
 | 
						|
 | 
						|
	public static function rgb2hsv($r, $g, $b)
 | 
						|
	{
 | 
						|
		$max = max($r, $g, $b);
 | 
						|
		$min = min($r, $g, $b);
 | 
						|
		$delta = $max - $min;
 | 
						|
		$v = round(($max / 255) * 100);
 | 
						|
		$s = ($max != 0) ? (round($delta / $max * 100)) : 0;
 | 
						|
		if ($s == 0)
 | 
						|
		{
 | 
						|
			$h = false;
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
			if ($r == $max)
 | 
						|
				$h = ($g - $b) / $delta;
 | 
						|
			elseif ($g == $max)
 | 
						|
				$h = 2 + ($b - $r) / $delta;
 | 
						|
			elseif ($b == $max)
 | 
						|
				$h = 4 + ($r - $g) / $delta;
 | 
						|
 | 
						|
			$h = round($h * 60);
 | 
						|
 | 
						|
			if ($h > 360)
 | 
						|
				$h = 360;
 | 
						|
 | 
						|
			if ($h < 0)
 | 
						|
				$h += 360;
 | 
						|
		}
 | 
						|
 | 
						|
		return [$h, $s, $v];
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Get a normal (light) background color as hexadecimal value (without hash prefix).
 | 
						|
	 * @return color string
 | 
						|
	 */
 | 
						|
	public function hex()
 | 
						|
	{
 | 
						|
		$c = $this->best;
 | 
						|
		return self::rgb2hex($c['r'], $c['g'], $c['b']);
 | 
						|
	}
 | 
						|
 | 
						|
	/**
 | 
						|
	 * Get a 50% darker version of the best color as string.
 | 
						|
	 * @param factor, defaults to 0.5
 | 
						|
	 * @param alpha, defaults to 0.7
 | 
						|
	 * @return rgba(r * factor, g * factor, b * factor, alpha)
 | 
						|
	 */
 | 
						|
	public function rgba($factor = 0.5, $alpha = 0.7)
 | 
						|
	{
 | 
						|
		$c = $this->best;
 | 
						|
		return 'rgba(' . round($c['r'] * $factor) . ', ' . round($c['g'] * $factor) . ', ' . round($c['b'] * $factor) . ', ' . $alpha . ')';
 | 
						|
	}
 | 
						|
 | 
						|
}
 |