Aug 18

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.

Dowload edited timthumb.php

Demo of all positions

demo link

16 Responses to “Timthumb cropping MOD”

  1. rafael Says:

    Perfect! I was looking much for some like this. Tks guys

  2. PSD to HTML Says:

    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.

  3. Indicar la posición del Crop con Timthumb | Summarg Says:

    [...] 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 [...]

  4. Gustavo Says:

    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!

  5. johan Says:

    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.

  6. johan Says:

    I can’t seem to set the filetype of the thumbs to JPEG. Which lines do I have to change?

  7. TimThumb, script PHP para redimensionar y optimizar imágenes | Nosolocodigo Says:

    [...] 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 [...]

  8. Todd Says:

    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.

  9. cj Says:

    any way to change the default thumbnail size like change it to 200×200 instead of 15×150 ?

    thanks

  10. TimThumb, script PHP para redimensionar y optimizar imágenes | {WebProgramo.com} Says:

    [...] 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 [...]

  11. Jonny Says:

    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

  12. Saree Says:

    I was looking for this code for last few days. Thanks and keep it up.

  13. joanie Says:

    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

  14. Xakep Says:

    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=…)

  15. krishna Says:

    <?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);

    }
    ?>

  16. krishna Says:

    /* 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 */

Leave a Reply

Notify me of follow-up comments via email.