PHP Classes
elePHPant
Icontem

Improving PHP Site Speed Generating Sprites and CSS to Render Images - picStylizer package blog

Recommend this page to a friend!
  All package blogs All package blogs   picStylizer picStylizer   Blog picStylizer package blog   RSS 1.0 feed RSS 2.0 feed   Blog Improving PHP Site Sp...  
  Post a comment Post a comment   See comments See comments (3)   Trackbacks (0)  

Author: Luciano Salvino

Posted on:

Package: picStylizer

As Web sites grow they tend to use many images for representing icons, logos and other types of common images. This often leads to delays in loading pages because loading the necessary images requires additional HTTP requests.

An alternative to reduce the number of requests to load the page images is to use sprites images and CSS to load many images at once.

Read this article to learn more about CSS sprites and how you can use them in your PHP sites to improve their page loading speed using the picStylizer package.




Contents

Introduction

What is picStylizer?

Getting All Images From the Origin Folder

Creating the Sprite Image

Generating CSS Style Sheet

Conclusion


Introduction

Every Web developer knows that page loading speed is very important. For that reason newer web projects tend to use sprites instead of lot of separate images.

There are solutions in other languages to convert groups of images into sprites. However, you can do it all in PHP using the picStylizer package.

Sprites image result

What is picStylizer?

picStylizer is a simple PHP class that allows you to avoid using many images in your site and use single sprite images and css styles to display any image. Sprites are images that contain the graphics of many other images grouped in a single image.

This class scans a given image folder and append all images in just one sprite image. It also keeps track of the position of each image inside the sprite image so it can create a CSS style sheet with styles that clip each of the images and make them appear in the background of a given page element.

It also creates a HTML page example so we can see how it appears.

Getting All Images From the Origin Folder

First of all we have to configure the folder from where the class will take the original images and the folder where it will create the sprite image, the CSS style sheet and the HTML example:

<?php
/**
* @var array folders_config folder
*/
private $folders_config = array(
"origin" => array(
"images" => "origin/images"
),
"destiny" => array(
"styles" => "destiny/css/sprites.css",
"sprites" => "destiny/sprites/sprites.png",
"example" => "destiny/example/sprites.html",
"ini_path" => "../../"
)
);
/**
* @var string The sprite result resource
*/
private $im;
/**
* @var int W sprite
*/
private $im_w = 0;

/**
* @var int H sprite
*/
private $im_h = 0;
/**
* @var int X image
*/
private $im_x = 0;

/**
* @var int Y image
*/
private $im_y = 0;
/**
* @var string The image tmp result source
  */
private $temp;

/**
* @var int W temp
*/
private $temp_w = 0;

/**
* @var int H temp
*/
private $temp_h = 0;
/**
* @var int temp separation in px between images inside sprite
*/
private $temp_sep = 2;
/**
* @var string temp_css
*/
private $temp_css = '';

/**
* @var string temp_css
*/
private $temp_min_sep = "\n";
/**
* @var string temp_html
*/
private $temp_html = '';
?>

Folder structure

Now we can read the origin folder looking for images to append to sprite:

<?php
/*
* read folder looking for images
* @return: array $result 
*/
private function readFolder( $dir='', $acceptedformats = array('png')) {
$result = array(); 
$cdir = scandir($dir); 
// read origin dir
foreach ($cdir as $key => $value) 

// exclude non files
if (!in_array($value,array(".",".."))) 

// if have sub folders loop on the same function
if (is_dir($dir . DIRECTORY_SEPARATOR . $value)) 

$result[$value] = $this->readFolder( $dir . DIRECTORY_SEPARATOR . $value); 

else 

// exclude files with extentions not accepted
$ext = strtolower( substr( $value, strrpos($value, '.') + 1));
if( in_array( $ext, $acceptedformats )) {
$result[] = $value; 
}



  
return $result; 
}
?>

You can define the acceptable image formats. In this case we only accept PNG format. We will have an array of images. In this case the array is $arrImages.

Creating the Sprite Image

If the readFolder function finds any image we can proceed to get the information of each image:
<?php
/*
* get the images info from array
* $dir is an array of images captured from readFolder
* $subdir is the subfolder path (if origin have subfolders)
*/
private function getImageInfoFromDir($dir,$subdir='') {

foreach($dir as $key => $value){
if(!is_int($key)) {
$this->getImageInfoFromDir( $value, $subdir . $key . DIRECTORY_SEPARATOR);
} else {
$this->calculateSpriteWidthHeight( $this->folders_config[ "origin" ]["images"] . DIRECTORY_SEPARATOR . $subdir . $value);
}
}
}
?>
The function calculateSpriteWidthHeight() gets the sprite measures:
<?php
/*
* calculate sprite w & h
* @param: string $image
* @return: object $this->temp 
*/
private function calculateSpriteWidthHeight( $image ) {
if(is_file($image)) {
  $arrImage = @getimagesize( $image );
$this->im_w += $arrImage[0] + $this->temp_sep;
$this->im_h += $arrImage[1] + $this->temp_sep;
}
}
?>

Now we can create the sprite based on the quantity of images we have.

<?php
// calculate sprite width and height
$this->getImageInfoFromDir( $arrImages ); 
// create the empty sprite 
$this->im = imagecreatetruecolor( $this->im_w, $this->im_h);
imagealphablending($this->im, false);
$transparency = imagecolorallocatealpha( $this->im, 0, 0, 0, 127);
imagefill( $this->im, 0, 0, $transparency);
imagesavealpha( $this->im, true);
?>

Now we get all images retrieved with the readFolder() function and proccess them to append to the sprite image.

<?php
/*
* get the images info from array
*/
private function getImagesFromDir( $dir, $subdir='') {
foreach($dir as $key => $value){
if(!is_int($key)) {
$this->getImagesFromDir( $value, $subdir . $key . DIRECTORY_SEPARATOR);
} else {
$this->processMedia( $this->folders_config[ "origin" ][ "images" ] . DIRECTORY_SEPARATOR . $subdir . $value);
}
}
}
/*
* proccess media
* @param: string $image
* @return: object $this->temp 
*/
private function processMedia($image) {
if(is_file($image)) {
  $arrImage = @getimagesize($image);
$this->temp_w = $arrImage[0];
$this->temp_h = $arrImage[1];

$tmp = ImageCreateTrueColor( $this->im_w, $this->im_h);
imagealphablending( $tmp, false);
$col = imagecolorallocatealpha( $tmp, 255, 255, 255, 0);
imagefilledrectangle( $tmp, 0, 0, $this->im_w, $this->im_h,$col);
imagealphablending($tmp,true);

$gd_ext = substr($image, -3);

if(strtolower($gd_ext) == "gif") {
  if (!$this->temp = imagecreatefromgif($image)) {
exit;
  }
  } else if(strtolower($gd_ext) == "jpg") {
  if (!$this->temp = imagecreatefromjpeg( $image )) {
    exit;
  }
  } else if( strtolower( $gd_ext) == "png") {
  if (!$this->temp = imagecreatefrompng( $image )) {
    exit;
  }
  } else {
  die;
  }
imagecopyresampled( $tmp, $this->im, 0, 0, 0, 0, $this->im_w, $this->im_h, $this->im_w, $this->im_h);
imagealphablending($tmp,true);

// add each image to sprite

imagecopyresampled( $this->im, $this->temp, $this->im_x, $this->im_y, 0, 0, $this->temp_w, $this->temp_h, $this->temp_w, $this->temp_h);
imagealphablending($this->im,true);

$ext = substr($image, strrpos($image, '.'));

$filename = basename($image,$ext);

// add piece of script to css
$this->genCssPieceCode( $filename );

$this->im_x += $this->temp_w+$this->temp_sep;
$this->im_y += $this->temp_h+$this->temp_sep;

} else {
 die;
}
}
?>

And then save the sprite image.

<?php
$x = 0;
$y = 0;
// proccess the images an append to sprite
$this->getImagesFromDir( $arrImages );
// save sprite
imagepng( $this->im, $this->folders_config['destiny']['sprites'],3); 
?>

Destiny folder structure

Generating CSS Style Sheet

While the function getImagesFromDir() processes the media it keeps the information to generate the CSS stylesheet and save on temp_css variable using the following function: 
<?php
/*
* Gen Css code
*/
private function genCssPieceCode( $name ) {
// if filename contain "_hover" add the part of code
if(strpos( $name, "_hover")!==false ) $name = substr( $name, 0, -6).':hover';
$temp_css_detail = "background: url('". $this->folders_config[ 'destiny' ][ 'ini_path' ].$this->folders_config[ 'destiny' ][ 'sprites' ]."') -". $this->im_x."px -". $this->im_y. "px no-repeat;". $this->temp_min_sep;
$temp_css_detail .= "width: ". $this->temp_w. "px; height: ". $this->temp_h. "px;".$this->temp_min_sep;
$temp_css = ".".$name." {".$temp_css_detail."}".$this->temp_min_sep;
$this->temp_css .= $temp_css;
}
?>
Now we just have to create the CSS file:
<?php
$css_path = $this->folders_config[ 'destiny' ][ 'styles' ];
file_put_contents( $css_path, $this->temp_css);

?>

Conclusion

You can use the picStylizer class to minimize the part of your CSS code that uses images and icons. You have to run just one time to create 2 simple files: sprites.png and sprites.css.

If you liked this article or you have questions or suggestions on how to improve this package, just post comment here.



You need to be a registered user or login to post a comment

Login Immediately with your account on:

FacebookGmail
HotmailStackOverflow
GitHubYahoo


Comments:

3. Improving the Speed of PHP programming - Protonbits Softwares (2016-02-09 12:50)
There are several ways to improve your PHP programming.... - 0 replies
Read the whole comment and replies

2. improve a php site easily - Patrick Bennett (2016-01-10 15:03)
hosting is the most important factor to improve a php site... - 0 replies
Read the whole comment and replies

1. sprites images today? - Mateusz Kaminski (2016-01-06 06:43)
Not recommend for HTTP 2... - 0 replies
Read the whole comment and replies




  Post a comment Post a comment   See comments See comments (3)   Trackbacks (0)  
  All package blogs All package blogs   picStylizer picStylizer   Blog picStylizer package blog   RSS 1.0 feed RSS 2.0 feed   Blog Improving PHP Site Sp...