Generate CSS sprites
Generate a map of existing images to a bigger one, and then using css to decide what icon to show for the user. Sounds like a plan! Doing it by hand takes a lot of time. Generating them, takes a little less time and is more flexible when adding new icons.
A good explanation of css sprites is found at [http://www.alistapart.com/articles/sprites/]
The following script generates a big image of all png files found in a specific directory, and converts the individual file paths to a cssrule referring to the big image.
$ php g_css_sprite.php ../path/to/images/ css_file.css png_file.png
Please note! A problem I noted is that the quality of the “copied” icons degrades a bit to much to make it usable for the moment. I’ve been looking at a few solutions for this, but its not there yet.
/** * Accept some simple input parameters */ $image_path = isset($_SERVER['argv'][1])?$_SERVER['argv'][1]:''; $css_output = isset($_SERVER['argv'][1])?$_SERVER['argv'][2]:''; $png_output = isset($_SERVER['argv'][1])?$_SERVER['argv'][3]:''; if( empty($image_path) || empty($css_output) || empty($png_output) ) exit("Usage: ".__FILE__." <imagepath> <cssoutput> <pngoutput>\n"); /** * Traverse a file tree and find png files only. * Exclude any images that are larger than 100x60 **/ function traverseFiles($path) { $files = array(); if( !is_dir($path) ) return $files; $dir = opendir($path); while( $f = readdir($dir) ) { if( ereg("png$", $f) ) { $im = getimagesize($path.$f); if( $im[0]<60 && $im[1]<100 ) $files[$path.$f] = array('width' => $im[0], 'height' => $im[1]); }elseif( is_dir($path.$f) && !ereg("^[\.]", $f) ) { $files = array_merge($files, traverseFiles($path.$f.'/')); } } return $files; } /** * Transform the path to a similar css rule. **/ function transform_path_to_css($path) { global $image_path; $p = str_replace($image_path, "", $path); $p = str_replace(".png", "", $p); $p = str_replace("-", "", $p); $p = str_replace("/", "_", $p); $p = 'images_'.$p; return $p; } /* Find all the pngs */ $png_files = traverseFiles($image_path); /** * Distribute the images on multiple rows in the new larger image. * Since we arent doing anything intelligent to sort images with the same height, * we try to keep in the array whats the max height for the row, so we can * start the next line below the previous one. */ $i = 0; $max_width = 0; $max_height = 0; $images_rows = array(); foreach( $png_files as $file => $size ) { if( !isset($images_rows[$i]) ) { /* Create a new "empty" row of images, if it doesnt exist. */ $images_rows[$i] = array('height' => 0, 'width' => 0, 'files' => array()); } $images_rows[$i]['height'] = max($images_rows[$i]['height'], $size['height']); $images_rows[$i]['files'][] = array( 'file' => $file, 'x' => $images_rows[$i]['width'] ); $images_rows[$i]['width']+=$size['width']; /* Create a new line after 600px */ if( $images_rows[$i]['width']>600 ) { $max_width = max($images_rows[$i]['width'], $max_width); $max_height+=$images_rows[$i]['height']; $i++; } } /* Create a new empty, transparent image with the calculated max height and width. */ $im = imagecreatetruecolor($max_width, $max_height); $transparent = imagecolorallocate($im, 0, 0, 0); imagecolortransparent($im, $transparent); /** * Walk through the image rows * and create a css structure. **/ $css = ''; $y = 0; foreach( $images_rows as $icon_rows ) { foreach( $icon_rows['files'] as $f ) { $c_im = imagecreatefrompng($f['file']); $new_position_x = $f['x']; $new_position_y = $y; $clip_x = ($f['x']*-1); $clip_y = ($y*-1); imagecopy($im, $c_im, $new_position_x, $new_position_y, 0, 0, $png_files[$f['file']]['width'], $png_files[$f['file']]['height']); $css.='.'.transform_path_to_css($f['file']).' { display: block; background: url('.$png_output.') '.$clip_x.'px '.$clip_y.'px no-repeat; width: '.$png_files[$f['file']]['width'].'px; height: '.$png_files[$f['file']]['height'].'px; }'.chr(10); } $y+=$icon_rows['height']; } imagepng($im, $png_output, 0, PNG_NO_FILTER); file_put_contents($css_output, $css); echo "Found ".sizeof($png_files)." png images..\n"; echo "Png filesize ".filesize($png_output)." bytes..\n"; echo "CSS filesize ".filesize($css_output)." bytes..\n";
blog comments powered by Disqus
© 1997 - 2010 | Part of the PTM Network