By default timthumb offers a cropping starting from center middle. Sometimes you may need some flexibility with a script so we used our knowledge to modify it a bit and make it more functionak for our needs. There are approx. 30 lines of code to add to make it work (see below). This supposed to make the use of plugins based on timthumb more flexible.By default timthumb offers a cropping starting from center middle. Sometimes you may need some flexibility with a script so we used our knowledge to modify it a bit and make it more functionak for our needs. There are approx. 30 lines of code to add to make it work (see below). This supposed to make the use of plugins based on timthumb more flexible.
Also an edited version is available for download.
Added “cropfrom” filter, accepted are values:
1. middle,
2. middleleft,
3. middleright,
4. topleft,
5. topright,
6. topcenter,
7. bottomleft,
8. bottomright,
9. bottomcenter,
simple modification done in 1 place on timthumb.php – easy for any level.

If you want to edit an original timthumb code:
1. Download recent timthumb version.
Read all about it and it’s usage if you not familiar with it yet.
2. Open it in text editor, and:
find: (line 59)
$quality = preg_replace(“/[^0-9]+/”, “”, get_request(“q”, 80));
$filters = get_request(“f”, “”);
add below:
// get crop position – added by studio-xl.com
$crop_from = get_request( ‘cropfrom’, ‘middle’ ) ;
// get crop position – added by studio-xl.com
find: (line 160)
imagecopyresampled( $canvas, $image, 0, 0, $src_x, $src_y, $new_width, $new_height, $src_w, $src_h );
REPLACE with:
// Crop position – modification by Studi-XL.com
if($crop_from ==”middle” )
// crop from center
{ imagecopyresampled( $canvas, $image, 0, 0, $src_x, $src_y, $new_width, $new_height, $src_w, $src_h ); }
// crop from middle left
elseif ($crop_from ==”middleleft” )
// crop from middle right
{ imagecopyresampled( $canvas, $image, 0, 0, 0, $src_y, $new_width, $new_height, $src_w, $src_h ); }
elseif ($crop_from ==”middleright” )
// crop from top center
{ imagecopyresampled( $canvas, $image, 0, 0, 2*$src_x, $src_y, $new_width, $new_height, $src_w, $src_h ); }
elseif ($crop_from ==”topcenter” )
// crop from top center
{ imagecopyresampled( $canvas, $image, 0, 0, $src_x, 0, $new_width, $new_height, $src_w, $src_h ); }
elseif ($crop_from ==”topleft” )
// crop from top left
{ imagecopyresampled( $canvas, $image, 0, 0, 0, 0, $new_width, $new_height, $src_w, $src_h ); }
elseif ($crop_from ==”topright” )
// crop from top center
{ imagecopyresampled( $canvas, $image, 0, 0, 2*$src_x, 0, $new_width, $new_height, $src_w, $src_h ); }
elseif ($crop_from ==”bottomcenter” )
// crop from bottom center
{ imagecopyresampled( $canvas, $image, 0, 0, $src_x, 2*$src_y, $new_width, $new_height, $src_w, $src_h ); }
elseif ($crop_from ==”bottomleft” )
// crop from bottom left
{ imagecopyresampled( $canvas, $image, 0, 0, 0, 2*$src_y, $new_width, $new_height, $src_w, $src_h ); }
elseif ($crop_from ==”bottomright” )
// crop from bottom center
{ imagecopyresampled( $canvas, $image, 0, 0, 2*$src_x, 2*$src_y, $new_width, $new_height, $src_w, $src_h ); }
elseif (!$crop_from)
// no data
{ imagecopyresampled( $canvas, $image, 0, 0, $src_x, $src_y, $new_width, $new_height, $src_w, $src_h ); }
// Crop position – modification by Studi-XL.com
* You may delete any block that you don’t need or leave it all for a max. flexibility.
3. Usage:
by default timthumb query string looks something like this:
src=/images/whatever.jpg&h=150&w=150&zc=1
we added 1 more filter which tells timthumb where to position cropping, you need to add &cropfrom=[position] to it, for example:
src=/images/whatever.jpg&h=150&w=150&zc=1&cropfrom=topleft
If you want an already updated file
You may download a modified ver. This one is fully working and used in our WP blogs.

Loading...
September 2nd, 2009 at 7:10 pm
Perfect! I was looking much for some like this. Tks guys
September 17th, 2009 at 12:56 am
Very nice! I had been looking for anything on how to change the cropping feature of TT and you’ve done it!! AWESOME WORK!! Greatly appreciated.
September 28th, 2009 at 5:47 pm
[...] fotografías de plano americano, por ejemplo, nos decapitará al objetivo. Por ello la gente de Studio-XL desarrolló una modificación para indicarle a Timthumb cómo debe [...]
September 29th, 2009 at 6:52 am
Thanks a lot for this mod, I was looking for such options, witch actually make it easy to be modified into what can then be controlled from the admin to choose the crop option. I just manually applied your mod to the timthumb script I was using, per your instructions and tested it, and works like a charm ..and thanks for the clear instructions of “find this”…replace with”. Mad props!
October 12th, 2009 at 10:38 pm
Awesome! Please note that the thumbnails in the downloadable version become PNG’s instead of JPG’s. Might not look the same in different browsers and the filesize is a little havier.
October 13th, 2009 at 12:36 am
I can’t seem to set the filetype of the thumbs to JPEG. Which lines do I have to change?
October 25th, 2009 at 7:22 am
[...] la imagen menos apropiada. Para evitar esto Studio-XL ha desarrollado una modificación del script. Se puede descargar desde su sitio. Su script funciona exactamente igual, pero añade la opción de especificar el parametro [...]
October 27th, 2009 at 12:56 am
Hi, after uploading the new .php file, where to I go to add the modifiers to the imgsrc? I tried adding it in the thumbnail field in wordpress, and that worked, but it broke the lightbox popup.
October 30th, 2009 at 7:36 am
any way to change the default thumbnail size like change it to 200×200 instead of 15×150 ?
thanks
November 4th, 2009 at 3:44 pm
[...] la imagen menos apropiada. Para evitar esto Studio-XL ha desarrollado una modificación del script. Se puede descargar desde su sitio. Su script funciona exactamente igual, pero añade la opción de especificar el parámetro [...]
November 5th, 2009 at 5:26 pm
Hi,
I installed as per the instructions however it still doesn’t work. Do I need to change the custom field “post_thumb” as well? I have edited all mentions of the “src=/images/whatever.jpg&h=150&w=150&zc=1″ part of the code in all of the php files of my template and added the “&cropfrom=topleft” to each of these mentions, but it still doesn’t seem to work…
Any idea?
Thanks,
Jonny
November 29th, 2009 at 8:08 am
I was looking for this code for last few days. Thanks and keep it up.
December 12th, 2009 at 3:39 am
Hi there
Thanks for the modified code. I uploaded it and everything looks the same. At least nothing broke, that’s progress! BUT i want to have all the images cropped TOP CENTER, and don’t know what to do with this line from your example above:
src=/images/whatever.jpg&h=150&w=150&zc=1&cropfrom=topleft
Where do i put that bit of code modified to
src=/images/whatever.jpg&h=150&w=150&zc=1&cropfrom=topcenter
???
Is there a diff php file i need to change?
Thanks sooo much!
J
December 12th, 2009 at 4:22 pm
joanie, hi
Yes, you need to download the updated php file for timthumb above, or update your existing as shown in article.
And you put this code:
src=/images/whatever.jpg&h=150&w=150&zc=1&cropfrom=topcenter
whenever and wherever you call to the image (img src=…)
February 20th, 2010 at 8:30 am
<?php
/*
TimThumb script created by Tim McDaniels and Darren Hoyt with tweaks by Ben Gillbanks
http://code.google.com/p/timthumb/
MIT License: http://www.opensource.org/licenses/mit-license.php
Paramters
———
w: width
h: height
zc: zoom crop (0 or 1)
q: quality (default is 75 and max is 100)
HTML example:
*/
/*
$sizeLimits = array(
“100×100″,
“150×150″,
);
error_reporting(E_ALL);
ini_set(“display_errors”, 1);
*/
// check to see if GD function exist
if(!function_exists(‘imagecreatetruecolor’)) {
displayError(‘GD Library Error: imagecreatetruecolor does not exist – please contact your webhost and ask them to install the GD library’);
}
define (‘CACHE_SIZE’, 250); // number of files to store before clearing cache
define (‘CACHE_CLEAR’, 5); // maximum number of files to delete on each cache clear
define (‘VERSION’, ‘1.12′); // version number (to force a cache refresh
if (function_exists(‘imagefilter’) && defined(‘IMG_FILTER_NEGATE’)) {
$imageFilters = array(
“1″ => array(IMG_FILTER_NEGATE, 0),
“2″ => array(IMG_FILTER_GRAYSCALE, 0),
“3″ => array(IMG_FILTER_BRIGHTNESS, 1),
“4″ => array(IMG_FILTER_CONTRAST, 1),
“5″ => array(IMG_FILTER_COLORIZE, 4),
“6″ => array(IMG_FILTER_EDGEDETECT, 0),
“7″ => array(IMG_FILTER_EMBOSS, 0),
“8″ => array(IMG_FILTER_GAUSSIAN_BLUR, 0),
“9″ => array(IMG_FILTER_SELECTIVE_BLUR, 0),
“10″ => array(IMG_FILTER_MEAN_REMOVAL, 0),
“11″ => array(IMG_FILTER_SMOOTH, 0),
);
}
// sort out image source
$src = get_request(“src”, “”);
if($src == ” || strlen($src) $cmp_y ) {
$src_w = round( ( $width / $cmp_x * $cmp_y ) );
$src_x = round( ( $width – ( $width / $cmp_x * $cmp_y ) ) / 2 );
} elseif ( $cmp_y > $cmp_x ) {
$src_h = round( ( $height / $cmp_y * $cmp_x ) );
$src_y = round( ( $height – ( $height / $cmp_y * $cmp_x ) ) / 2 );
}
// Crop position – modification by Studi-XL.com
if($crop_from ==”middle” )
// crop from center
{ imagecopyresampled( $canvas, $image, 0, 0, $src_x, $src_y, $new_width, $new_height, $src_w, $src_h );
}
// crop from middle left
elseif ($crop_from ==”middleleft” )
// crop from middle right
{ imagecopyresampled( $canvas, $image, 0, 0, 0, $src_y, $new_width, $new_height, $src_w, $src_h ); }
elseif ($crop_from ==”middleright” )
// crop from top center
{ imagecopyresampled( $canvas, $image, 0, 0, 2*$src_x, $src_y, $new_width, $new_height, $src_w, $src_h ); }
elseif ($crop_from ==”topcenter” )
// crop from top center
{ imagecopyresampled( $canvas, $image, 0, 0, $src_x, 0, $new_width, $new_height, $src_w, $src_h ); }
elseif ($crop_from ==”topleft” )
// crop from top left
{ imagecopyresampled( $canvas, $image, 0, 0, 0, 0, $new_width, $new_height, $src_w, $src_h ); }
elseif ($crop_from ==”topright” )
// crop from top center
{ imagecopyresampled( $canvas, $image, 0, 0, 2*$src_x, 0, $new_width, $new_height, $src_w, $src_h ); }
elseif ($crop_from ==”bottomcenter” )
// crop from bottom center
{ imagecopyresampled( $canvas, $image, 0, 0, $src_x, 2*$src_y, $new_width, $new_height, $src_w, $src_h ); }
elseif ($crop_from ==”bottomleft” )
// crop from bottom left
{ imagecopyresampled( $canvas, $image, 0, 0, 0, 2*$src_y, $new_width, $new_height, $src_w, $src_h ); }
elseif ($crop_from ==”bottomright” )
// crop from bottom center
{ imagecopyresampled( $canvas, $image, 0, 0, 2*$src_x, 2*$src_y, $new_width, $new_height, $src_w, $src_h ); }
elseif (!$crop_from)
// no data
{ imagecopyresampled( $canvas, $image, 0, 0, $src_x, $src_y, $new_width, $new_height, $src_w, $src_h ); }
// Crop position – modification by Studi-XL.com
} else {
// copy and resize part of an image with resampling
imagecopyresampled( $canvas, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height );
}
if ($filters != ” && function_exists(‘imagefilter’) && defined(‘IMG_FILTER_NEGATE’)) {
// apply filters to image
$filterList = explode(“|”, $filters);
foreach($filterList as $fl) {
$filterSettings = explode(“,”, $fl);
if(isset($imageFilters[$filterSettings[0]])) {
for($i = 0; $i 0) {
$yesterday = time() – (24 * 60 * 60);
usort($files, ‘filemtime_compare’);
$i = 0;
if (count($files) > CACHE_SIZE) {
foreach ($files as $file) {
$i ++;
if ($i >= CACHE_CLEAR) {
return;
}
if (@filemtime($file) > $yesterday) {
return;
}
if (file_exists($file)) {
unlink($file);
}
}
}
}
}
/**
* compare the file time of two files
*/
function filemtime_compare($a, $b) {
return filemtime($a) – filemtime($b);
}
/**
* determine the file mime type
*/
function mime_type($file) {
if (stristr(PHP_OS, ‘WIN’)) {
$os = ‘WIN’;
} else {
$os = PHP_OS;
}
$mime_type = ”;
if (function_exists(‘mime_content_type’)) {
$mime_type = mime_content_type($file);
}
// use PECL fileinfo to determine mime type
if (!valid_src_mime_type($mime_type)) {
if (function_exists(‘finfo_open’)) {
$finfo = @finfo_open(FILEINFO_MIME);
if ($finfo != ”) {
$mime_type = finfo_file($finfo, $file);
finfo_close($finfo);
}
}
}
// try to determine mime type by using unix file command
// this should not be executed on windows
if (!valid_src_mime_type($mime_type) && $os != “WIN”) {
if (preg_match(“/FREEBSD|LINUX/”, $os)) {
$mime_type = trim(@shell_exec(‘file -bi ‘ . escapeshellarg($file)));
}
}
// use file’s extension to determine mime type
if (!valid_src_mime_type($mime_type)) {
// set defaults
$mime_type = ‘image/png’;
// file details
$fileDetails = pathinfo($file);
$ext = strtolower($fileDetails["extension"]);
// mime types
$types = array(
‘jpg’ => ‘image/jpeg’,
‘jpeg’ => ‘image/jpeg’,
‘png’ => ‘image/png’,
‘gif’ => ‘image/gif’
);
if (strlen($ext) && strlen($types[$ext])) {
$mime_type = $types[$ext];
}
}
return $mime_type;
}
/**
*
*/
function valid_src_mime_type($mime_type) {
if (preg_match(“/jpg|jpeg|gif|png/i”, $mime_type)) {
return true;
}
return false;
}
/**
*
*/
function check_cache ($cache_dir, $mime_type) {
// make sure cache dir exists
if (!file_exists($cache_dir)) {
// give 777 permissions so that developer can overwrite
// files created by web server user
mkdir($cache_dir);
chmod($cache_dir, 0777);
}
show_cache_file ($cache_dir, $mime_type);
}
/**
*
*/
function show_cache_file ($cache_dir, $mime_type) {
$cache_file = $cache_dir . ‘/’ . get_cache_file();
if (file_exists($cache_file)) {
$gmdate_mod = gmdate(“D, d M Y H:i:s”, filemtime($cache_file));
if(! strstr($gmdate_mod, “GMT”)) {
$gmdate_mod .= ” GMT”;
}
if (isset($_SERVER["HTTP_IF_MODIFIED_SINCE"])) {
// check for updates
$if_modified_since = preg_replace (“/;.*$/”, “”, $_SERVER["HTTP_IF_MODIFIED_SINCE"]);
if ($if_modified_since == $gmdate_mod) {
header(“HTTP/1.1 304 Not Modified”);
die();
}
}
$fileSize = filesize ($cache_file);
// send headers then display image
header (‘Content-Type: ‘ . $mime_type);
header (‘Accept-Ranges: bytes’);
header (‘Last-Modified: ‘ . $gmdate_mod);
header (‘Content-Length: ‘ . $fileSize);
header (‘Cache-Control: max-age=9999, must-revalidate’);
header (‘Expires: ‘ . $gmdate_mod);
readfile ($cache_file);
die();
}
}
/**
*
*/
function get_cache_file() {
global $lastModified;
static $cache_file;
if (!$cache_file) {
$cachename = $_SERVER['QUERY_STRING'] . VERSION . $lastModified;
$cache_file = md5($cachename) . ‘.png’;
}
return $cache_file;
}
/**
* check to if the url is valid or not
*/
function valid_extension ($ext) {
if (preg_match(“/jpg|jpeg|png|gif/i”, $ext)) {
return TRUE;
} else {
return FALSE;
}
}
/**
*
*/
function checkExternal ($src) {
$allowedSites = array(
‘flickr.com’,
‘picasa.com’,
‘blogger.com’,
‘wordpress.com’,
‘img.youtube.com’,
);
if (ereg(‘http://’, $src) == true) {
$url_info = parse_url ($src);
$isAllowedSite = false;
foreach ($allowedSites as $site) {
if (ereg($site, $url_info['host']) == true) {
$isAllowedSite = true;
}
}
if ($isAllowedSite) {
$fileDetails = pathinfo($src);
$ext = strtolower($fileDetails['extension']);
$filename = md5($src);
$local_filepath = ‘temp/’ . $filename . ‘.’ . $ext;
if (!file_exists($local_filepath)) {
if (function_exists(‘curl_init’)) {
$fh = fopen($local_filepath, ‘w’);
$ch = curl_init($src);
curl_setopt($ch, CURLOPT_URL, $src);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_USERAGENT, ‘Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.5) Gecko/20041107 Firefox/1.0′);
curl_setopt($ch, CURLOPT_FILE, $fh);
if (curl_exec($ch) === FALSE) {
if (file_exists($local_filepath)) {
unlink($local_filepath);
}
displayError(‘error reading file ‘ . $src . ‘ from remote host: ‘ . curl_error($ch));
}
curl_close($ch);
fclose($fh);
} else {
if (!$img = file_get_contents($src)) {
displayError(‘remote file for ‘ . $src . ‘ can not be accessed. It is likely that the file permissions are restricted’);
}
if (file_put_contents($local_filepath, $img) == FALSE) {
displayError(‘error writing temporary file’);
}
}
if (!file_exists($local_filepath)) {
displayError(‘local file for ‘ . $src . ‘ can not be created’);
}
}
$src = $local_filepath;
} else {
displayError(‘remote host “‘ . $url_info['host'] . ‘” not allowed’);
}
}
return $src;
}
/**
* tidy up the image source url
*/
function cleanSource($src) {
$host = str_replace(‘www.’, ”, $_SERVER['HTTP_HOST']);
$regex = “/^((ht|f)tp(s|):\/\/)(www\.|)” . $host . “/i”;
$src = preg_replace ($regex, ”, $src);
$src = htmlentities ($src);
$src = checkExternal ($src);
// remove slash from start of string
if (strpos($src, ‘/’) === 0) {
$src = substr ($src, -(strlen($src) – 1));
}
// don’t allow users the ability to use ‘../’
// in order to gain access to files below document root
$src = preg_replace(“/\.\.+\//”, “”, $src);
// get path to image on file system
$src = get_document_root($src) . ‘/’ . $src;
return $src;
}
/**
*
*/
function get_document_root ($src) {
// check for unix servers
if(file_exists($_SERVER['DOCUMENT_ROOT'] . ‘/’ . $src)) {
return $_SERVER['DOCUMENT_ROOT'];
}
// check from script filename (to get all directories to timthumb location)
$parts = array_diff(explode(‘/’, $_SERVER['SCRIPT_FILENAME']), explode(‘/’, $_SERVER['DOCUMENT_ROOT']));
$path = $_SERVER['DOCUMENT_ROOT'];
foreach ($parts as $part) {
$path .= ‘/’ . $part;
if (file_exists($path . ‘/’ . $src)) {
return $path;
}
}
// the relative paths below are useful if timthumb is moved outside of document root
// specifically if installed in wordpress themes like mimbo pro:
// /wp-content/themes/mimbopro/scripts/timthumb.php
$paths = array(
“.”,
“..”,
“../..”,
“../../..”,
“../../../..”,
“../../../../..”
);
foreach ($paths as $path) {
if(file_exists($path . ‘/’ . $src)) {
return $path;
}
}
// special check for microsoft servers
if (!isset($_SERVER['DOCUMENT_ROOT'])) {
$path = str_replace(“/”, “\\”, $_SERVER['ORIG_PATH_INFO']);
$path = str_replace($path, “”, $_SERVER['SCRIPT_FILENAME']);
if (file_exists($path . ‘/’ . $src)) {
return $path;
}
}
displayError(‘file not found ‘ . $src);
}
/**
* generic error message
*/
function displayError($errorString = ”) {
header(‘HTTP/1.1 400 Bad Request’);
die($errorString);
}
?>
February 20th, 2010 at 8:33 am
/* This is for wordpress */
<img src="/timthumb.php?src=ID, $key, true); ?>&h=175&w=189&zc=1&cropfrom=topcenter&” style=”border: none;” />
/* This is for wordpress */