EllisLab text mark
Advanced Search
1 of 2
1
   
Real-time image manipulation and cache using class.upload.php
Posted: 28 January 2009 09:06 AM   [ Ignore ]
Avatar
Joined: 2008-12-04
179 posts

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…

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

<?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.

 
Posted: 28 January 2009 09:12 AM   [ Ignore ]   [ # 1 ]   [ Rating: 0 ]
Avatar
Joined: 2008-12-04
179 posts

How to implement

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

2. Create system/application/libraries/Imaging.php

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

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

<?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.

 
Posted: 28 January 2009 02:35 PM   [ Ignore ]   [ # 2 ]   [ Rating: 0 ]
Avatar
Joined: 2008-02-04
534 posts

Very interesting, thanks for the post. I am going to check this out. Have been very disappointed with the built in image resizing.

 
Posted: 28 January 2009 03:02 PM   [ Ignore ]   [ # 3 ]   [ Rating: 0 ]
Avatar
Joined: 2006-07-27
2617 posts

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…

 Signature 

Check out the Template Library
Oh yeah, I tweet, too (regarding CodeIgniter on occassion).

 
Posted: 28 January 2009 05:29 PM   [ Ignore ]   [ # 4 ]   [ Rating: 0 ]
Avatar
Joined: 2008-12-04
179 posts

@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.

 
Posted: 28 January 2009 05:31 PM   [ Ignore ]   [ # 5 ]   [ Rating: 0 ]
Avatar
Joined: 2006-07-27
2617 posts

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

 Signature 

Check out the Template Library
Oh yeah, I tweet, too (regarding CodeIgniter on occassion).

 
Posted: 30 January 2009 01:10 PM   [ Ignore ]   [ # 6 ]   [ Rating: 0 ]
Joined: 2006-05-14
6 posts

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

 
Posted: 30 January 2009 09:19 PM   [ Ignore ]   [ # 7 ]   [ Rating: 0 ]
Avatar
Joined: 2008-12-04
179 posts

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

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

 
Posted: 30 January 2009 09:36 PM   [ Ignore ]   [ # 8 ]   [ Rating: 0 ]
Avatar
Joined: 2008-12-04
179 posts

Don’t forget to empty the cache directory before you try again.

 
Posted: 30 January 2009 10:38 PM   [ Ignore ]   [ # 9 ]   [ Rating: 0 ]
Joined: 2008-08-26
45 posts

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….

 
Posted: 30 January 2009 11:35 PM   [ Ignore ]   [ # 10 ]   [ Rating: 0 ]
Avatar
Joined: 2008-12-04
179 posts

Hi… These cached images don’t expire (they get intentionally deleted). I’m not saying this is the answer to all of your problems. It is more of a time/work saver and it may only be useful in some situations depending on server loads, frequency of new images, etc. It definitely won’t help you if you let your clients upload 4mb images and have 12 to a page. In most cases it is me (the developer) who is the first to visit the page and cop the increased load time.

1. Take this case… you have 22 images on the server. You have converted them all to small jpegs and saved them. The client wants them all to have a watermark. You have to go back and change the existing images. And then you have to edit the code to make any new images have a watermark. My way- you delete the image cache. You change the format in config.
2. Thats a nice idea! Perhaps version 2 can have this as an option too?

Cheers

 
Posted: 02 February 2009 02:27 PM   [ Ignore ]   [ # 11 ]   [ Rating: 0 ]
Joined: 2006-05-14
6 posts

thanks for the update! is working perfectly now. yeah, it’s not a perfect solution to every situation but i can see how it will be handy to have around. thanks again!

mark

 
Posted: 13 February 2009 01:19 PM   [ Ignore ]   [ # 12 ]   [ Rating: 0 ]
Joined: 2009-02-06
21 posts

The only problem i have is to be able to clear all the cache in group.

And how do i use this with imagemagick?

 
Posted: 13 February 2009 07:42 PM   [ Ignore ]   [ # 13 ]   [ Rating: 0 ]
Avatar
Joined: 2008-12-04
179 posts

Just delete the files from the cache folder. Or to delete just one image (in it’s various formats) create a function to take the filename and the format and then loop through the formats and delete from the cache directory. Sorry to be rude but if your having trouble ‘clearing the cache’ then you shouldn’t be using this script. I said at the beginning that it isn’t for beginners.

What benefits are you looking to achieve with ImageMagick?

 
Posted: 13 February 2009 08:23 PM   [ Ignore ]   [ # 14 ]   [ Rating: 0 ]
Joined: 2009-02-06
21 posts

I can deal with the cache group part. Class.upload is using GD2 how do i change it to imagemagick jw

 
Posted: 13 February 2009 08:29 PM   [ Ignore ]   [ # 15 ]   [ Rating: 0 ]
Avatar
Joined: 2008-12-04
179 posts

Not sure… Check out verot.net

 
1 of 2
1