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
Leave a Reply