Friday, July 22, 2016

PHP script to automatically create Image + CSS Sprite (Simple & Automatic)

I needed to create CSS Sprite and Image quickly. I did not want to gather images into image editors like Photoshop. Align them properly and create CSS classes to be able to use them easily. All those steps can take at least 30 minutes just to put together a sprite of 10 images.

So I found some codes online and combine them together, and added my own logics to make this script below.

This PHP function will take several parameters and it will generate a .png image file (containing all the image sprites combined) and CSS file you can include into your webpage.

Original credits goes to http://innvo.com/1315192249-css-sprites-with-php  for writting the base function.

Here is my customized function:

<?PHP
//CLASS to CREATE SPRITE
class images_to_sprite {

function images_to_sprite($sprite_name, $source_img_path, $img_output_path, $css_output_path, $img_output_url) {
$this->sprite_name = $sprite_name;
$this->source_img_path = $source_img_path.$this->sprite_name; // path to import images into sprite
$this->filetypes = array('jpg'=>true,'png'=>true,'jpeg'=>true,'gif'=>true); // Acceptable file extensions to consider
$this->img_output_path = $img_output_path; // Output filename default: mysprite.png
$this->css_output_path = $css_output_path; // Output filename default: mysprite.css
$this->img_output_url = $img_output_url;
$this->files = array();
}

function create_sprite() {

$files = array();
$max_width = 0;
$max_height = 0;
$canvas_height = 0;

// Read through the directory for suitable images
$files_arr = array();
if($handle = opendir($this->source_img_path)) {
while (false !== ($file = readdir($handle))) {
$split = explode('.',$file);

// Ignore non-matching file extensions
if($file[0] == '.' || !isset($this->filetypes[$split[count($split)-1]]))
continue;

$files_arr[] = $file;
}
closedir($handle);
}
// echo __LINE__.':files_arr: '.print_r($files_arr, true)."\n"; exit;

if(!empty($files_arr)){
sort($files_arr);

foreach($files_arr as $file){
$split = explode('.',$file);

// Ignore non-matching file extensions
if($file[0] == '.' || !isset($this->filetypes[$split[count($split)-1]]))
continue;

// Get image size and ensure it has the correct dimensions
$img_size_arr = getimagesize($this->source_img_path.'/'.$file);
// echo __LINE__.':img_size_arr: '.print_r($img_size_arr, true)."\n";

if(!empty($img_size_arr[0]) && $max_width < $img_size_arr[0]) $max_width = $img_size_arr[0];
if(!empty($img_size_arr[1])){
$canvas_height += $img_size_arr[1];
if($max_height < $img_size_arr[1]) $max_height = $img_size_arr[1];
}

// Image will be added to sprite, add to array
$file_arr = array(
'name' => $file,
'width' => $img_size_arr[0],
'height' => $img_size_arr[1]
);
$this->files[$file] = $file_arr;

$tmp = explode(".", $file);
$tmp = end($tmp);
$tmp = basename($file,$tmp);
$tmp = substr($tmp, 0, -1);
$filenames[] = $tmp;
}
}

$im = imagecreatetruecolor($max_width, $canvas_height);

// Add alpha channel to image (transparency)
imagesavealpha($im, true);
$alpha = imagecolorallocatealpha($im, 0, 0, 0, 127);
imagefill($im, 0, 0, $alpha);

// Append images to sprite and generate CSS lines
$i = 0;
$current_top = 0;
$current_pos = 0;

$fp = fopen($this->css_output_path.$this->sprite_name.'.css', 'w');

// wrapper class
fwrite($fp,'.sprite_'.$this->sprite_name.' { width:'.$max_width.'px; height:'.$max_height.'px; background-image:url(\''.$this->img_output_url.$this->sprite_name.'.png\'); }'."\n");


//Individual sprite image
foreach($this->files as $key => $file) {
/* top, right, bottom, left  - Image position */
fwrite($fp, '.sprite_' . $filenames[$i]. ' { width:'.$file['width'].'px; height:'.($file['height']-1).'px; background-position: 0 '.$current_pos.'px; }'."\n");

$im2 = imagecreatefrompng($this->source_img_path.'/'.$file['name']);
imagecopy($im, $im2, 0, $current_top, 0, 0, $file['width'], $file['height']);
$current_top += $file['height'];
$current_pos -= $file['height'];
$i++;
}

fclose($fp);
imagepng($im, $this->img_output_path.$this->sprite_name.'.png'); // Save image to file
imagedestroy($im);

chmod($this->css_output_path.$this->sprite_name.'.css', 0777);
chmod($this->img_output_path.$this->sprite_name.'.png', 0777);
}
}


----------------------------------------------------------------

(please see instructions of how to use above)


<?php
require_once '/data_local/app/cron_php/sprite/Images_to_sprite.class.php';

$class = new images_to_sprite(
'ribbon',
'/app/www/static/shared/img/sprite/raw/', // Source Images
'/app/www/static/shared/img/sprite/',        // Image output directory and file
'/app/www/static/shared/css/sprite/',       // CSS output directory and file
'/static/shared/img/sprite/'                      // base URL for css
);
$class->create_sprite();


--------------------------------------------------------------

This script will produce a PNG image sprite like this  (ribbon.png) :



And the CSS file output will look like this   (ribbon.css) :


.sprite_ribbon { width:20px; height:58px; background-image:url('/static/shared/img/sprite/ribbon.png'); }

.sprite_ribbon_10 { width:20px; height:46px; background-position: 0 0px; }

.sprite_ribbon_20 { width:20px; height:46px; background-position: 0 -47px; }

.sprite_ribbon_21 { width:20px; height:57px; background-position: 0 -94px; }

.sprite_ribbon_70 { width:20px; height:46px; background-position: 0 -152px; }


To use the Sprite Image you do this in your HTML (to show BOGO ribbon):
(c.gif is a 1x1 clear pixel - required by img tag)

<img class="sprite_ribbon sprite_ribbon_20" src="c.gif" />


Wednesday, November 11, 2015

Failed to load Zend/Loader.php - Easy permanent solution

I encountered this error message today:

"Failed to load Zend/Loader.php"

-or some people also experienced -

"Failed to load Zend/AutoLoader.php"

What caused the issues above?  Basically a script somewhere in your PHP app is requiring Zend Framework Library, and it can not find it.

This is how I solved this issue:

1. Install Zend framework library (if it does not already exists).
   
    for Ubuntu > 9.04 use:   apt-get install zend-framework

    The above command will install Zend Framework in /usr/share/php

2.  Then you should create .ini file for PHP to include your newly install Zend extension

     nano /etc/php5/conf.d/zend-framework.ini

with the following content:

[Zend]
include_path=${include_path} ":/usr/share/php/libzend-framework-php"

3.  Restart your webserver.
   
     service apache2 restart

Your error message should now disappear.

I hope this helps someone.

Thursday, October 29, 2015

Assign values to dynamic variable in PHP without using eval()

In PHP eval() function is evil.  I try my best not to use it. The eval() function has been misused by hackers so much... that I usually scan through my (or somebody else's)  PHP scripts when I suspect some malware has been installed (infected PHP files).

Here is a quick grep command to find all files with keyword 'eval(':

grep -rn "eval(" /data_local/app 


One situation when I have the need to use eval, is when I am assigning a dynamic variable.  Okay first I should probably explain what I mean by dynamic variable.  Dynamic variable is a technique to define a variable programmatically, meaning your scripts are defining the PHP variables automatically.

Look at this code as an example:

<?php
$variable_name = 'my_variable';

$variable_value = 123;

$$variable_name = $variable_value;

echo $my_variable;
?>

The output of the above PHP codes will be:

123

 Lets examine what the code did... on line 3 ( $$variable_name = $variable_value; )

We are actually defining $my_variable with the value 123.

PHP makes this very simple with using $$ operator, which kind of makes sense.


Saturday, July 25, 2015

Remove accented character from string accents accent char characters in PHP

Here is an array of accented characters and a function to replace them to normal un-accented version


$unwanted_array = array( 'Š'=>'S', 'š'=>'s', 'Ž'=>'Z', 'ž'=>'z', 'À'=>'A', 'Á'=>'A', 'Â'=>'A', 'Ã'=>'A', 'Ä'=>'A', 'Å'=>'A', 'Æ'=>'A', 'Ç'=>'C', 'È'=>'E', 'É'=>'E',
'Ê'=>'E', 'Ë'=>'E', 'Ì'=>'I', 'Í'=>'I', 'Î'=>'I', 'Ï'=>'I', 'Ñ'=>'N', 'Ò'=>'O', 'Ó'=>'O', 'Ô'=>'O', 'Õ'=>'O', 'Ö'=>'O', 'Ø'=>'O', 'Ù'=>'U',
'Ú'=>'U', 'Û'=>'U', 'Ü'=>'U', 'Ý'=>'Y', 'Þ'=>'B', 'ß'=>'Ss', 'à'=>'a', 'á'=>'a', 'â'=>'a', 'ã'=>'a', 'ä'=>'a', 'å'=>'a', 'æ'=>'a', 'ç'=>'c',
'è'=>'e', 'é'=>'e', 'ê'=>'e', 'ë'=>'e', 'ì'=>'i', 'í'=>'i', 'î'=>'i', 'ï'=>'i', 'ð'=>'o', 'ñ'=>'n', 'ò'=>'o', 'ó'=>'o', 'ô'=>'o', 'õ'=>'o',
'ö'=>'o', 'ø'=>'o', 'ù'=>'u', 'ú'=>'u', 'û'=>'u', 'ý'=>'y', 'ý'=>'y', 'þ'=>'b', 'ÿ'=>'y' );

$str = strtr( $str, $unwanted_array );

Sunday, February 1, 2015

GEOIP pear pecl PHP extension for location IP based conversion to city country, longitude, latitude

  1. Download .dat.gz databases from maxmind: http://geolite.maxmind.com/download/geoip/database/
  2. Install geoip via yum.
    yum install GeoIP GeoIP-devel
  3. You also might want to download database with ip addresses from Maxmind website and place it in /usr/share/GeoIP (which is a default location of geoip upon installation).
  4. Install PECL extension
    pecl install geoip
  5. Add extension=geoip.so to your /etc/php.ini
  6. Restart apache /etc/init.d/httpd restart

For Ubuntu:

apt-get install libgeoip-dev libgeoip1
apt-get install php5-geoip

then you need to copy GeoLiteCity.dat.gz to /usr/share/GeoIP/ and extract it and rename it to GeoIPCity.dat
then restart your web server:

service apache2 restart

Check if PHP session already started? session_start check

Simplest way to check if PHP session has already started or not


<?php
  if (!isset ($_COOKIE[ini_get('session.name')])) {
    session_start();
  }
?>

Check if PHP script was executed from command line CLI or not

Simple and fool proof PHP code snippet to detect if the current running script was executed from command line (CLI) or not (most likely browser).



if(is_null($argc)) {
    //NOT CLI
} else {
    //FROM CLI
}