Welcome Guest, Not a member yet? Register   Sign In
Real-time image manipulation and cache using class.upload.php
#1

[eluser]helmutbjorg[/eluser]
Hi Guys,

Thought i would share something as I guess this is how the whole open source thing works and I have already taken so much from this forum. I know this has been done before. I'm using the class.upload.php (if you don't know what it can do check out their samples page) because the CI image_lib doesn't handle PNG very well and I think it really is an unfinished and un-supported part of the library to be honest. And class.upload.php is amazing and thorough.

This is not recommended for BEGINNERS. You must understand how the concept works before you can really get good use out of this technique.

I wanted a way to let my clients upload an image (the biggest one they had) and then instead of manipulating that image on upload and creating various sizes to use throughout the system, I want to be able to use a script to generate an image (using a set format template) and save it to cache so that subsequent requests get the modified image. So essentially the resizing, cropping, conversion, etc only happens on the first request for the image.

For example...

A typical process (the old way)
1. A user uploads default.jpg which is 800x600
2. The system creates a thumbnail which is 100x75 and saves it as default_thumb.jpg
3. The system creates a small version which is 300x200 and saves it as default_small.jpg
4. Now the system can use those images like so...
Code:
<?php echo img('uploads/default_small.jpg'); ?>

My system
1. A user uploads default.jpg which is 800x600
2. Now the system can use it like so
Code:
<?php echo img_format('uploads/default.jpg', 'small'); ?>

The first time that tag is called the default.jpg image is modified according to the config image format set for 'small' and saved to cache. The second time the image is loaded from cache requiring no processing time.

The benefits:
1. You don't have to lock yourself in to any particular formats for images so that if requirements change you can deliver any size image or type.
2. Make a change to the format template and delete the cache and the whole site is updated.
#2

[eluser]helmutbjorg[/eluser]
How to implement

1. Download class.upload.php and save to system/application/libraries/class.upload.php

2. Create system/application/libraries/Imaging.php
Code:
<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Imaging Class
*
* A port of the class.upload.php by Colin Verot to allow you to use
* the functionality of the class through CI as a library. You can
* watermark, resize, crop all in a very memory efficient manner.
*
* Using this class instead of the CI image_lib class because it has
* better file support for PNG or GIF especially when transparent.
*
*/

// Include the main class
require_once(APPPATH.'libraries/class.upload.php');

// Extend it
class Imaging extends upload {

    function Imaging() {
        log_message('debug', get_class($this).' Class Initialized');
    }
    
}
// END Imaging Class

/* End of file Imaging.php */
/* Location: ./system/application/libraries/Imaging.php */

3. Add this function to system/application/helpers/MY_html_helper.php (create it if you have to)
Code:
/**
* Image Format
*
* Generates an image file in the specified format, or takes it from cache
* and outputs an <img /> element using Colin Verots upload class. Set different
* formats in /system/application/config/my_image_formats.php
*
*/    
if(!function_exists('img_format')) {
    function img_format($src='', $format='', $index_page=FALSE) {
        // Load a codeigniter instance
        $CI =& get_instance();
        // Get the image format configurations
        $CI->config->load('my_image_formats');
        $formats = $CI->config->item('image_formats');        
        // The cached name of the file is just a md5 hash of the src and the format
        $hash = md5($format.$src);
        // Get the file extension (if we are converting get the new extension eg. jpg->gif)
        if(isset($formats[$format]['image_convert'])) $ext = '.'.$formats[$format]['image_convert'];
        else $ext = '.'.end(explode('.', $src));
        // Get the general path to the system
        $path = str_replace(SELF,'',FCPATH);    
        // Check if the image has already been generated in the cache
        if(!file_exists($path.'cache/'.$hash.$ext)) {
            // Make sure format is valid
            if(isset($formats[$format])) {
                // Increase memory allowance
                ini_set('memory_limit','36M');  
                // Load the image manipulation library                
                $CI->load->library('imaging');
                $CI->imaging->upload($path.$src);
                if($CI->imaging->uploaded) {
                    // Some default settings
                    $CI->imaging->file_new_name_body = $hash;
                    $CI->imaging->file_auto_rename = FALSE;
                    $CI->imaging->file_overwrite = TRUE;
                    // Settings for the format as defined in the config
                    foreach($formats[$format] as $key => $value) {
                        $CI->imaging->$key = $value;
                    }
                    // Process
                    $CI->imaging->Process($path.'cache');
                    if($CI->imaging->processed) $src = 'cache/'.$hash.$ext;
                }
            }        
        } else $src = 'cache/'.$hash.$ext;
        // Pass to the normal img function
        return img($src, $index_page);
    }
}

4. Create system/application/config/my_image_formats.php
Code:
&lt;?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/*
|--------------------------------------------------------------------------
| Image Formats
|--------------------------------------------------------------------------
|
| Used by the custom html helper img_format() function where the 'format'
| parameter needs to correspond with a key in the following array of
| image formats.
|
| Key and value pairs correspond with class settings as outlined at
| http://www.verot.net/php_class_upload.htm in Colin Verots class
| upload script.
|
| Example format:
| $config['image_formats']['small_gif'] = array('image_resize'=>TRUE, 'image_convert'=>'gif', 'image_x'=>100, 'image_ratio_y'=>TRUE);
|
| Usage:
| echo img_format('upload/default.jpg', 'small_gif');
|
*/

$config['image_formats']['small_gif'] = array('image_resize'=>true, 'image_convert'=>'gif', 'image_x'=>100, 'image_ratio_y'=>true);


/* End of file my_image_formats.php */
/* Location: ./system/application/config/my_image_formats.php */

5. Create a folder outside of the above system folder called /cache/ (note NOT /system/cache/ NOT system/application/cache BUT /cache/. If you have htaccess to remove index.php don't forget to add an allowance for the cache folder.
#3

[eluser]louis w[/eluser]
Very interesting, thanks for the post. I am going to check this out. Have been very disappointed with the built in image resizing.
#4

[eluser]Colin Williams[/eluser]
I've used something very similar since CI 1.3. It does use the CI image_lib class, and has a different system for caching (something more natural, utilizing mod_rewrite rules). I have a rough draft of a tutorial started for it. Will have it out one of these days...
#5

[eluser]helmutbjorg[/eluser]
@Colin - would you care to elaborate on the mod_rewrite bit?
@Louis - No problems. Even if you do not use the real-time cache bit the class.upload.php is great for general use anyway.
#6

[eluser]Colin Williams[/eluser]
There's no quick explanation of it Smile I'll try to remember to post a link to the tut if/when I get around to polishing it
#7

[eluser]longlostcousin[/eluser]
hi. thanks for this library! i have set it up on a development site and i am looping through an array of images in a view and it turns them all into the same image. it seems to only access the image library once. not sure what is going on. any ideas? thanks!

mark
#8

[eluser]helmutbjorg[/eluser]
Problem solved. I have updated the original post...

Update the Imaging.php library and also the html helper function. The problem was that codeigniter was only running the class.upload.php constructor once (as is codeigniters excellent way!) but that class requires the constructor to be hit for each file. All I needed to change in the helper was
Code:
// From
$CI->load->library('imaging', array('file'=>$path.$src));
// To
$CI->load->library('imaging');
$CI->imaging->upload($path.$src)
// Notice how i have moved the constructor to it's own function

Cheers
#9

[eluser]helmutbjorg[/eluser]
Don't forget to empty the cache directory before you try again.
#10

[eluser]roj[/eluser]
I know the topic is kind of closed — given that the problem is solved — but I still don't quite understand the problem. Surely this just adds to server loads when caches expire and adds irritation to the end user who tries to load the file the first time and has to wait that little bit longer?

Perhaps I just don't get it but the benefits listed don't make much sense to me:
1. if you have the original image you're not really tied to anything as they can all be resized.
2. how is this any different to changing the format template and then a having a simple to script to resize the various templates to the new size in a single batch?

As I said I just don't get the benefits, but I'm willing to learn....




Theme © iAndrew 2016 - Forum software by © MyBB