tracerstar

This site is no longer maintained and will eventually have the articles rehosted. In the meantime, please visit my current portfolio, Benjamin Fox Studios.

Extract a color table from a gif with PHP

In early 2006 I wrote a bit of PHP code that extracted a color table from a gif. I've rewritten it here in a neat little class with example usage. At present it just converts it to HTML hex colors, but I'm going to add RGB extraction. Using the output in a flash file just requires changing the # to 0x. Try the demo to see it working.

This is a nice way of getting a large number of colors from an image quickly that can be used in other applications. Here's the code:

Class

class gifColor {
	
	private $bytes = array();
	private $header = array();
	private $lsd = array();
	private $global_c_t_flag = 0;
	private $color_resolution = null;
	private $sort_flag = null;
	private $size_of_gct = 0;
	
	public $num_of_colors = 0;
	public $html_color_table = array();
	
	function readGif($filename) {
		//file handle
		$fh = @fopen($filename, 'rb');
		if ($fh) {
			//add each byte to the array as a decimal value
			while (!feof($fh)) {
				$bit = fread($fh, 1);
				if ($bit) {//lets us ignore null bytes (end of packets)
					$byte = unpack('C', $bit);//this provides us with the decimal value we want!!! YAY
					$this->bytes[] = decbin($byte[1]);//convert it to hex
				} else {
			        $this->bytes[] = decbin(0);//convert it to hex
				}
			}
		}
	}
	
	//creates a hex value of a byte of color
	function getHex($byte) {
		$decimal = bindec($byte);
		return substr('00'.dechex($decimal),-2);
	}
	
	function extractParts() {
		//Get header / version (first 6 bytes)
		for ($i = 0; $i <= 5; $i++) {
			$this->header = $this->bytes[$i];
		}
		
		//Get logical screen descriptor (next 7 bytes)
		for ($i = 6; $i <= 12; $i++) {
			$this->lsd[] = $this->bytes[$i];
		}
		
		//extract packed fields from the 5th item in the logical screen descriptor
		$this->global_c_t_flag = substr($this->lsd[4], 0, 1); //1 char
		$this->color_resolution = substr($this->lsd[4], 1, 3); //3 chars
		$this->sort_flag = substr($this->lsd[4], 4, 5); //1 char
		$this->size_of_gct = substr($this->lsd[4], 5, 8); //3 chars
	}
	
	function buildTable() {
		
		if (!empty($this->bytes)) {
			$this->extractParts();
		}
		
		/*
		if a Global Color Table is present, parse it
		size in bytes/lines based on formula:
		3 x 2^(Size of Global Color Table+1)
		*/
		if ($this->global_c_t_flag == '1') {
			//$gct_actual_size is the number of bytes the colors are stored in
			$gct_actual_size = 3 * pow(2, (bindec($this->size_of_gct) + 1));
			
			//number of colors is the number of rgb triplets that exist
			$this->num_of_colors = $gct_actual_size/3;
			
			//transform each rgb triplet into a html
			
			//the color values are stored in lines 13 to 13+size of gtc
			$global_color_table = array();
			for ($i = 13; $i < 13 + $gct_actual_size; $i++) {
				$global_color_table[] = $this->bytes[$i];
			}
			
			$colors = array();
			$i = 0;
			$j = 0;
	
			while($i < $this->num_of_colors) {
				//build an HTML hex color string
				$color = '#';
			    $color .= $this->getHex($global_color_table[$j]);//r
		     	$color .= $this->getHex($global_color_table[$j+1]);//g
			    $color .= $this->getHex($global_color_table[$j+2]);//b
			    
			    $this->html_color_table[] = $color;
			    //increment our counters
				$j += 3;
				$i++;
			}
		}
	}
}

Usage

$colors = new gifColor;
$colors->readGif('nyc.gif');
$colors->buildTable();
if ($colors->num_of_colors > 0) {
	echo '<img src="nyc.gif" />';
	echo '<p>Total colors: '.$colors->num_of_colors.'</p>';
	foreach ($colors->html_color_table as $i => $color) {
		echo '<div style="width:40px; height:40px; background:'.$color.';float:left;">'.($i + 1).'</div>';
	}
}

What's going on the above is we instantiate the class and read in a gif. Call the buildTable method and the class examines each byte of the gif, extracting the relevant color values. This gets stored in the html_color_table property, the total number of colors in the file are contained in the num_of_colors property. Just check that for more than 0 colors and you're good to run through the table. This example just lists a bunch of div's with a bg color applied (as seen in the demo), but you could out put as XML or a simple text sring for use in another application.

0 Responses to Extract a color table from a gif with PHP