Image resizing magic
8/11/2010 9:00 AM By Jeff BThis last one is a tip about a very useful image manipulation script, TimThumb. Go ahead and grab the source code; save it to a new document called something intelligent, like timthumb.php, and put that somewhere on your site (e.g. /scripts/). You’ll also want to ensure that the folder containing timthumb.php is writeable by the server (set it to 777 if necessary), so TimThumb can create its cache folder.
Now, normally, we’d insert an image inline like so:
<img src="/images/image.jpg" alt="My picture" width="800" height="600" />
With TimThumb, however, we can do this:
<img src="/scripts/timthumb.php?src=/images/image.jpg&h=150&w=150&zc=1" alt="My picture" width="150" height="150" />
But what does that do for us? Well, TimThumb dynamically resizes images, so we supply it with a query consisting of:
- Source (
src), which is an absolute path to the image file (meaning it starts with “/”) - Height (
h=), which is the number of pixels for the height - Width (
w=), which is the number of pixels for the width - Zoom/Crop (
zc=), which is a boolean setting which determines if the image will be resized or if it will be zoomed/cropped to achieve the size you want. This setting is most useful when you are generating thumbnails that are all an identical size, but you have source images that are various sizes and shapes.
So now, if we take our image gallery code from one of the previous posts, we can do this:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Pictures From My Trips</title>
</head>
<body>
<section id="april-pics">
<ul id="photos-list">
<?php
// the directory, where your images are stored
$imgdir = '/images/2010/04/01';
// list of filetypes you want to show
$allowed_types = array('png','jpg','jpeg','gif');
$dimg = opendir($imgdir);
while($imgfile = readdir($dimg))
{
if(in_array(strtolower(substr($imgfile,-3)),$allowed_types))
{
$a_img[] = $imgfile;
sort($a_img);
reset ($a_img);
}
}
// total image number
$totimg = count($a_img);
for($x=0; $x < $totimg; $x++)
{
echo "\t\t\t".'<li><a rel="lightbox" href="'.$imgdir.'/'.$a_img[$x].'"<img src="/scripts/timthumb.php?src='.$imgdir.'/'.$a_img[$x].'&w=250&h=250&zc=1" width="250" height="250" /></a></li>'."\r"; // Tabs & carriage return added to improve final rendered readability.
}
?>
</ul>
</section>
</body>
</html>
Now you may say, “But I can do that by just specifying the size in the img tag; why would I waste server resources like this?” And the answer is because TimThumb caches these resized images. Once at least one person asks for one of them, they become static files in TimThumb’s cache folder, and as such, consume even fewer resources than resizing an image client-side with the img tag.
We can, however, improve on TimThumb’s caching and skip TimThumb entirely when an image is cached. Before performing this step, please make sure TimThumb is working well as-is; we don’t want to hack something that’s not 100% to start with.
With that in mind, take a look at line 528 (in the current version). You’ll see this:
$cachename = $_SERVER['QUERY_STRING'] . VERSION . $lastModified;
$cache_file = md5($cachename) . '.png';
If we change how the cachename is generated, we can craft some filenames that can be more easily used in some RegEx .htaccess rules. So how about this little tidbit:
$filename = preg_replace("@http://[^/]+/(.*)\.$ext$@", "$1", get_request( 'src', 'timthumb' ));
$cachename = $filename . '-' .
get_request( 'w', 100 ) . '-' .
get_request( 'h', 100 ) . '-' .
get_request( 'zc', 1 ) . '-' .
get_request( '9', 80 );
$cache_file = $cachename . '.png';
So what’s happening here? We’re calculating the file name (from the URL) and stripping out the extension (since all of the images end up being PNGs), then adding in a dash, the width, dash, height, dash, the value of zc, and the quality value, ending with the png extension.
Now let’s craft some mod_rewrite rules to skip TimThumb whenever we can. Open up your .htaccess, and place this bit in before any of your other rewrite rules:
RewriteCond %{SCRIPT_FILENAME} timthumb\.php
RewriteCond %{QUERY_STRING} src=http:\/\/[^\/]+\/(.*)\.(png|jpe?g)&w=([0-9]+)&h=([0-9]+)&zc=([0-9]+)
RewriteCond YOUR_HOME_DIRECTORY/%1-%3-%4-%5-80.%2 -f
RewriteRule .* /%1-%3-%4-%5-80.%2 [L]
So what the heck does that do? Well, the first line keeps an eye out for any requests for TimThumb. Then the second rule figures out some GET parameters for the image file name and its extension, width, and height. If you’ve got anything else going on with your image URLs, here’s where to add them in. If you’ve never dealt with RegEx, I recommend some Googling on it, and perhaps asking a question over at StackOverflow, a great programming resource.
Then we have a line you need to modify. The YOUR_HOME_DIRECTORY bit needs to be adjusted to reflect your actual site root. If you don’t know what it is, put this:
<?php echo $_SERVER['DOCUMENT_ROOT'] ?>
Into a file at the site root and view it. Copy the path it presents you with, and replace YOUR_HOME_DIRECTORY with it. The variables (%1, %2, etc.) are being culled from the second RewriteCond. The last rule is the actual rewrite itself (which is internal, not a redirect, so the URL never changes). You may need to adjust this rule to reflect the path to your images, but a little experimentation should yield whether or not your images can be found.
If you have dedicated hosting, this is only going to result in a little bit of savings, but if you’re on shared hosting, like Media Temple’s (gs), or GoDaddy, or Dreamhost, or any of the myriad other hosts, this will dramatically improve your site’s response if you want to use TimThumb.
Tags: PHP








Subscribe by RSS