Prashant Ingale

Juice of PHP, MySQL, Apache, Linux, Actionscript, Flex

Archive for October, 2008

How to create thumbnails with PHP and gd

leave a comment

How to make sure your server can generate images

This small article will explain how you create a thumbnail from an image
in PHP. Furthermore you learn how to batch process a whole folder of images and
create their thumbnails.

To create images with PHP you need to have the
gd image library installed and
activated in your PHP.

To make sure if gd is installed on your machine, simply check your php info. Create
a file that contains:

<?phpinfo()?>

and save it as "test.php" on your server. When
you open it in a browser you see a colourful table showing all the schematics
of your PHP install. In it you have to find something like this: Example of a php with gd installed

If you know for sure that there is gd on the machine but PHP does not recognise
it, it may still be commented in the php.ini.

Scan your machine for the php.ini and edit it in a text editor.
You will find loads of extensions:

;extension=php_fdf.dll
;extension=php_filepro.dll
;extension=php_gd.dll
;extension=php_gettext.dll
;extension=php_hyperwave.dl

Simply remove the “;” in front of the php_gd and restart your server.

;extension=php_fdf.dll
;extension=php_filepro.dll
extension=php_gd.dll
;extension=php_gettext.dll
;extension=php_hyperwave.dl

The logic of batch processing thumbnails

Your server is running PHP, gd support is enabled, let’s start thinking about the code.

To generate thumbnails we do the following:

  • Scan a folder for JPG and PNG files (gd does not support GIF anymore, because
    the packing algorithm in GIF is copyrighted).
  • Take each of these images, and load it.
  • Resize the image.
  • Save the image as a thumbnail.

The resizing idea is the following:

  • We assume the thumbnail should be 100 pixels, either wide or high.
  • We load the original image, and check its dimensions.
  • If the picture is higher than wide, we set the height of the thumb
    to 100 pixels.
  • The width of the thumbnail is the original width multiplied with 100 pixels
    divided by its height.
  • Thumbnail height = original width * (100 / original height)
  • This way we preserve the original aspect ratio.
  • If the original picture is wider than high, we do the same to the height of
    the thumbnail.
  • If they are the same, we simply create a 100×100 pixels image.

The PHP functions to use

PHP has a whole lot of functions

to help us with generating graphics with gd.

The ones we need to use here are:

  • imageCreateFromJPEG() to create a copy to work on of a .jpg image.
  • imageCreateFromPNG() to create a copy to work on of a .png image.
  • imageSX() to get the width of the original image.
  • imageSY() to get the height of the original image.
  • ImageCreateTrueColor() to create a new truecolour image object.
  • imageCopyResampled() to resample the image.

GD supports truecolour images from version 2.0 onwards, older versions of GD
will create JPGs and PNGs with 256 colours and need other functions. I deliberately
dropped the support here, as gd2 comes bundled with every newer install of PHP anyways.

  • imageJPEG() to create a new JPEG image.
  • imagePNG() to create a new PNG image.
  • imagedestroy() to delete the old image objects in the memory.

Furthermore I created some functions I keep using:

  • directory() reads a folder and returns all the files that apply to a certain filter.
  • ditchtn() clears the resulting array from all files starting with a filter you define, like tn_".
  • createthumb() creates a thumbnail and saves it to the server.

directory() and ditchtn() are filesystem and array functions, I will not explain them
here, they should be pretty self-explanatory.

The main thumbnail generation function

createthumb() is the main thumbnail generation function, so let’s take a closer
look:

function createthumb($name,$filename,$new_w,$new_h){
	$system=explode('.',$name);
	if (preg_match('/jpg|jpeg/',$system[1])){
		$src_img=imagecreatefromjpeg($name);
	}
	if (preg_match(’/png/’,$system[1])){
		$src_img=imagecreatefrompng($name);
	}

createthumb() is called with the following parameters: The name of the original
image (if needed with folder name), the name of the thumbnail picture, and the
dimensions.

These lines get the information if gd is at least version 2.0 and check if the
original image is a JPEG or PNG.

Accordingly, a new image object is created called src_image.

$old_x=imageSX($src_img);
$old_y=imageSY($src_img);
if ($old_x > $old_y) {
	$thumb_w=$new_w;
	$thumb_h=$old_y*($new_h/$old_x);
}
if ($old_x < $old_y) {
	$thumb_w=$old_x*($new_w/$old_y);
	$thumb_h=$new_h;
}
if ($old_x == $old_y) {
	$thumb_w=$new_w;
	$thumb_h=$new_h;
}

These lines get the dimensions of the original image by using imageSX() and imageSY(),
and calculate the dimensions of the thumbnail accordingly, keeping the correct
aspect ratio. The desired dimensions are stored in thumb_w and thumb_h.

	$dst_img=ImageCreateTrueColor($thumb_w,$thumb_h);
	imagecopyresampled($dst_img,$src_img,0,0,0,0,$thumb_w,$thumb_h,$old_x,$old_y);

These lines create the image as a true colour version using
ImageCreateTrueColor() and resize and copy the original image into
the new thumbnail image, on the top left position.


if (preg_match("/png/",$system[1]))
{
	imagepng($dst_img,$filename);
} else {
	imagejpeg($dst_img,$filename);
}
imagedestroy($dst_img);
imagedestroy($src_img);
}

These lines check the file system extension of the original image and create
the thumbnail accordingly. The thumbnail gets saved onto the server (by adding
a filename to imagejpeg() or imagepng() function)
and the two image objects get destroyed to free the memory.

How to use createthumb()

Let’s say you have an original picture called apple.jpg in a folder pics and you
want to generate the thumbnail in the folder thumbs as tn_apple.jpg 100×100 pixels big.

You can do this by calling this function with the following parameters:

createthumb('pics/apple.jpg','thumbs/tn_apple.jpg',100,100);

To batch process all the pictures in the folder pics and generate their
thumbnails in the folder thumbs you do the following:

$pics=directory('pics','jpg,JPG,JPEG,jpeg,png,PNG');
$pics=ditchtn($pics,'tn_');
if ($pics[0]!=”)
{
	foreach ($pics as $p)
	{
		createthumb(’pics/’.$p,’thumbs/tn_’.$p,100,100);
	}
}

You grab all the pictures from the pics folder via directory() and a filter for images.

Then you delete all the thumbnails by using ditchtn() and make sure that
the resulting array is not empty.

The second parameter in ditchtn() must match the name you give your
thumbnails, this is done to prevent thumbnails being generated from thumbnails.

You then loop over all images and generate the thumbnail with the desired
dimensions and names.

Caveats and download

Generating thumbnails with PHP is pretty handy and saves you a lot of time
pushing files onto your server via FTP. It also makes it easier to keep a image
gallery up to date.

Using the functions introduced here it is no problem to scan a folder for
new images and create the thumbnails when new images were uploaded.

PHP with gd can be very slow at times though, especially when the machine is
not too fast and the resample() function is used. Some servers might stop telling you
the maximum time of script execution has been not enough. You can change this in your
php.ini:

max_execution_time = 320 ; Maximum execution time of each script, in seconds

Now, try to generate some thumbnails on your own server by playing with the
thumbnail generator, a script that has
all the functions described above included.

Written by admin

October 2nd, 2008 at 1:42 pm

Posted in About

CSS Constants

leave a comment

Preface

One feature designers often wished they had with style sheets are constants - the chance to define something once and reuse it over and over in the style sheet document. This article shows some techniques how to achieve that and discusses their pros and cons.

A constant nagging

When reading CSS related forums or mailing lists, you’ll sooner or later find someone asking how they can define a “constant” in CSS - something to define once in the CSS document and reuse throughout it.

There are several reasons why there are no constants in CSS:

  • The CSS specifications didn’t plan for any constants, variables, loops or conditions simply because CSS is there to describe the visual presentation of a document, not programming logic. The same applies to HTML - there are no variables, constants, loops and conditions - its job is to describe what a certain text is, in this document, regardless of what variables were sent to it.
  • CSS is “executed” on the client - the browser. Browsers on slower computers already have problems rendering CSS properly. Fixed positioning and big background graphics can cause delays and flickering - what would happen if they had to process the “CSS logic” on top of that?
  • Any scripting on the client side is, however low, a security threat and allows for exploits. Microsoft Internet Explorer’s ability to embed Javascript in CSS files proved that.

However, CSS constants could be something very handy indeed.

Possible Uses

CSS constants would make it easier to turn style guides into CSS and allow for smaller style sheet documents without much repetition. You define the colours once and add the constant name every time you want to use it.

/* Company Colours */
$blue='#369';
$green='#363';
$lgreen='#cfc';

[…]

ul#navigation{
	background:$blue;
	color:#fff;
}
h1{
	border-bottom:1px solid $green;
}

White-labelling and redesign would be a breeze, all you need to change is the constants and all the styles comply with the new colours. No more search and replace sessions and the inevitable setting that escaped them.

Another option would be to define often used styles and keep the document shorter.

$boxstyles='background:#ccc;border-top:1px solid #eee; border-left:1px solid #eee; border-right:1px solid #aaa; border-bottom:1px solid #aaa;padding:.5em;margin:.5em 0';

h1{
	$boxstyles
	color:#000;
}
div#extras div {
	$boxstyles
	font-size:80%;
}

As CSS does not allow for that, we need to find a way around the problem. One is to use what CSS does provide us with.

The CSS standard compliant approach

CSS in itself is something like a constant. By defining the styles in classes and IDs or for the elements themselves, we spare ourselves the excruciating work of adding a lot of visual elements and attributes in the markup. In the days before CSS we had to do the following:

Foo

CSS allows us to define that as:

td {
vertical-align:top;
text-align:right;
font-size:100%;
color:blue;
font-weight:bold;
}

These constant settings are applied to each TD element. Another way:

td.special {
vertical-align:top;
text-align:right;
font-size:100%;
color:blue;
font-weight:bold;
}

The class special is a definition that can be reused for all elements, so to say a constant.

Using Classes

CSS classes could be one approach to mimic real CSS constants. Our box example above could be:

.box {
background:#ccc;
border-top:1px solid #eee;
border-left:1px solid #eee;
border-right:1px solid #aaa;
border-bottom:1px solid #aaa;
padding:.5em;
margin:.5em 0';
}

We can add this class to any element to apply its definitions. It is also perfectly valid to add several classes, separated by spaces, to one element.

<h1 class="box">
<div class="box warning">

What we should avoid doing is to name the classes according to how they look, as it can be pretty confusing to see a <div class="blue bold underline"> that is yellow, of normal weight and without an underline, after a new style guide came along and got applied.

Using ID Selectors and Descendent Selectors

Another option to maintain a certain re-use is to make the settings dependent on an ID on the BODY element. First we define the settings applying to all pages:

body{
	font-family:Arial,Sans-Serif;
	background:#fff;
	color:#333;
}
#nav{
	width:10em;
	margin:0;
	padding:.5em;
}
#nav li{
	list-style-type:none;
}
h1{
	font-size:120%;
	border-bottom:1px solid #000;
}

Then we make the colours dependent on the ID of the body:

#home h1{
	border-bottom:1px solid #363;
	background:#cfc;
}
#home #nav{
	border:1px solid #363;
	background:#cfc;
}
#contact h1{
	border-bottom:1px solid #369;
	background:#ccf;
}
#contact #nav{
 	border:1px solid #369;
	background:#ccf;
}

The higher specificity ensures that the original settings get overwritten by the “localised” ones.

Depending on which ID we set on the BODY element, the different colour settings get applied, without any need to define classes in the HTML.

While this approach means a lot of repetition in the style sheet, it still - properly commented - provides an easy way to brand different pages differently.

All we need is to add one ID to the BODY of the document - something that could be done dynamically on the server or via a content management system.

Both solutions are dependent on changes in the markup though, the classes approach painfully so. Real CSS constants shouldn’t need that, and to make that happen we have to move away from the browser to the server.

Moving server side

There are basically two ways to simulate CSS constants on the server. One is using the server software and the other is to use scripting languages on the server.

Using Server Side Includes (SSI)

Server Software, like Apache and the Microsoft IIS allow for server side includes (SSI). We can use these to simulate CSS constants.

For Apache, we define a new file extension called “sccs” for “Server Cascading Stylesheets” by adding the following to the configuration file of the server:

Options +Includes
AddType text/css .scss
AddHandler server-parsed .scss

Inside one of these new “scss” files we can use the Server Side Includes syntax to set and retrieve our constants:

<!--#set var="blue" value="#369" -->

<!--#set var="green" value="#363" -->
ul#navigation{
	background: <!--#echo var="blue" -->;
	color:#fff;
}
h1{
	border-bottom:1px solid <!--#echo var="green" -->;
}

Many web space providers won’t allow users to change the server configuration, though. What most provide are Server Side Scripting Languages, that can also be used to simulate CSS constants.

Using Server Side Scripting Languages

Server side languages, such as PHP, JSP, ASP, ASPX, Cold Fusion, ModPerl, Perl, JSP and so forth, come with the ability to send header information of the current document. Furthermore, they feature all we need - Variables, Constants, Loops, Conditions and Objects.

To tell for example a PHP script to send its output as CSS to the browser, we use the following two lines of code:

header('content-type:text/css');
header("Expires: ".gmdate("D, d M Y H:i:s", (time()+900)) . " GMT");

The first line defines the content as CSS, a style sheet. The second sets the expiry date of the document to the current time and a bit, that way the output of the script will still be cached by the browser. Without this line, the CSS would never be cached, which can be a performance problem depending on how big the resulting style sheet document is.

You can create anything with the right header information. Javascript, images, PDFs, Excel Sheets, Flash files, you name it. Header can also help us to trigger the download of files rather than the display of them in the browser.

The only important thing is that the header output has to be the first output of the script. Any output before that - including whitespace - will cause an error.

Content types can only be set once, you cannot put out Javascript and later on CSS (unless you write them out inline) in one script.

Harnessing the power of the header function, we now have the whole specification of our server side language at our disposal. We can define and reuse variables, change them according to parameters sent to the page, automatically set them according to the location on the server and so on.

Our above example in PHP would be:

<?php
header('content-type:text/css');
header("Expires: ".gmdate("D, d M Y H:i:s", (time()+900)) . " GMT");
/* Company Colours */
$blue='#369';
$green='#363';
$lgreen='#cfc';
?>

ul#navigation{
	background:<?php echo $blue;?>;
	color:#fff;
}
h1{
	border-bottom:1px solid <?php echo $green;?>;
}

If the PHP setup allows for shortcut notation we could also use:

<?php
header('content-type:text/css');
header("Expires: ".gmdate("D, d M Y H:i:s", (time()+900)) . " GMT");
/* Company Colours */
$blue='#369';
$green='#363';
$lgreen='#cfc';
?>

ul#navigation{
	background:<?=$blue;?>;
	color:#fff;
}
h1{
	border-bottom:1px solid <?=$green;?>;
}

Another way is to use the print command to output until a certain label is reached; this one does mess with the colour coding of some editors and might be - depending on the size of the CSS - straining the processor:

<?php
header('content-type:text/css');
header("Expires: ".gmdate("D, d M Y H:i:s", (time()+900)) . " GMT");
/* Company Colours */
$blue='#369';
$green='#363';
$lgreen='#cfc';

print <<<ENDCSS
ul#navigation{
	background:$blue;
	color:#fff;
}
h1{
	border-bottom:1px solid $green;
}
ENDCSS;
?>

There is no end to the usefulness of this approach. We can reuse cookie data or grab selector names from a database or a parsed document. We could allow an XML notation for the CSS and turn it into valid CSS on the fly.

An example of how to use parameters sent to the page could be to allow visitors to define a width of the content:

<?php
header('content-type:text/css');
header("Expires: ".gmdate("D, d M Y H:i:s", (time()+900)) . " GMT"); 

// grab the parameter w and set the variable w to its value
// if the parameter is not an integer, set w to 740
$w=740;
if(isset($_GET['w']))
{
	$w=preg_match(’/(\D)/’,$_GET['w'])?$w:$_GET['w'];
}
/* Company Colours */
$blue=’#369′;
$green=’#363′;
$lgreen=’#cfc’;
?>
#boundary{
	width:<?php echo $w;?>px;
}

ul#navigation{
	background:<?php echo $blue;?>;
	color:#fff;
}
h1{
	border-bottom:1px solid <?php echo $green;?>;
}

Or we apply different colour schemes according to the section:

<?php
header('content-type:text/css');
header("Expires: ".gmdate("D, d M Y H:i:s", (time()+900)) . " GMT");
$self=$_SERVER['PHP_SELF'];
/* Colour schemes */
if (preg_match(’/aboutus/’,$self))
{
// About us
	$colour1=’#369′;
	$colour2=’#69c’;
	$colour3=’#9cf’;
} 

else if (preg_match(’/clients/’,$self))
{
// Clients
	$colour1=’#963′;
	$colour2=’#c96′;
	$colour3=’#fc9′;
}
else if (preg_match(’/downloads/’,$self))
{
// Downloads
	$colour1=’#693′;
	$colour2=’#9c6′;
	$colour3=’#cf9′;
}
?>

ul#navigation{
	background:<?php echo $colour1;?>;
	color:#fff;
}
h1{
	border-bottom:1px solid <?php echo $colour3;?>;
	color:<?php echo $colour2;?>;
}

Each of these examples requires the maintainer of the site to know about PHP, and may give her the chance to break it or add unsafe code. If we want to ensure that we have something like CSS constants with a less steep learning curve and less power to the maintainer, we can parse a CSS file with PHP.

Parsing CSS with PHP

Parsing a CSS file before it gets sent to the server allows us to come up with a notation for the constants. As an example we will use $constant = ‘value’; as the definition and $constant as the implementation.

Our CSS looks something like this:

/* Demo CSS */
/* Constants 

$colour1 = '#999';
$colour2 = '#363';
$colour4 = '#696';
$colour3 = '#cfc';

*/
body{
	text-align:center;
	background:$colour2;
	font-family:"MS Trebuchet", Arial, Sans-Serif;
}
#boundary{
	font-size:90%;
	margin:1em auto;
	text-align:left;
	position:relative;
	width:40em;
	background:$colour2;
}
[…]

We apply it to the HTML document via the LINK or the style tag, like any other CSS, the only difference is that we send it to a PHP script for parsing:

<style type="text/css">
	@import 'cssconst.php?c=demo.css';
</style>

The script to parse the CSS and write out the values of the defined constants is rather simple:

<?PHP
header('content-type:text/css');
header("Expires: ".gmdate("D, d M Y H:i:s", (time()+900)) . " GMT");

// grab the c parameter and ensure that it contains .css is no slashes
// this is a safety measure to prevent XSS
$c=$_GET['c'];
if(preg_match(’/\//’,$c) or !preg_match(’/.css/’,$c))
{
	die(’only local CSS files allowed!’);
	exit;
}

// load the content of the CSS file into the variable css, end if the
// file wasn’t found.
$css=load($c);
if($css==”)
{
	die(’File not Found, sorry!’);
	exit;
}
// grab all constants and store them in the array constants
preg_match_all(”/\\$(\w+).*=.*\’(.*)\’/”,$css,$constants);
for($i=0;$i<sizeof($constants[1]);$i++)
{

// replace all occurrences of the contants with their values
	$css=preg_replace(’/\\$’.$constants[1][$i].’/',$constants[2][$i],$css);
}

// delete all constant definitions
$css=preg_replace(”/\\#.*=.*?;\s+/s”,”,$css);

// print out the style sheet
echo $css;

function load($filelocation)
{
	if (file_exists($filelocation))
	{
		$newfile = fopen($filelocation,”r”);
		$file_content = fread($newfile, filesize($filelocation));
		fclose($newfile);
		return $file_content;
	}
}
?>

To see it in action, check the demonstration page with the unparsed style sheet.

Disallowing the script to read other than local files and only CSS files are the basic safety measures we should enforce when using this technology. Allowing any script in any location to be parsed might enable visitors to spy on sections of the server they are not supposed to look into.

For basic operations, this is a slick approach to the problem, however to allow for more complex definitions we might have to amend the regular expressions - for example to allow for multi line definitions or the usage of quotation marks inside a definition.

Written by admin

October 2nd, 2008 at 1:37 pm

Posted in PHP

Scripting Enabled at @mediaAjax 2008

leave a comment

I am right now at @media Ajax 2008 getting ready to go on stage to deliver my “Scripting Enabled” talk, explaining how the main issue about accessibility is that we just don’t talk enough to each other. Technology is never really the boundary we have with accessibility, it is that we don’t understand how people work and what technology is capable of.

Links in the presentation

Written by admin

October 2nd, 2008 at 1:28 pm