Another boring blog...

Probably best you go out instead of reading this...

Vertical Padding of Images in Code Igniter

written by ajp, on Jan 11, 2010 3:00:00 PM.

There are many techniques available to make floated list items look to be the same height with different amounts of content within them. These can be used effectively in many situations, but one where I have not seen them work is where an image is the first thing in each list item:

Mock Website Design showing images of varying heights in a layout.

I've been building a site for a friend recently and the issue of how to add vertical padding to images automatically came up during this development, so I'll reproduce the changes I made to the excellent Code Igniter image library to support this.

  1. Open <CIROOT>/system/libraries/Image_lib.php in your favourite text editor.
  2. Code Igniter libraries generally extract all of the contents of their configuration array as member variables of themselfs. Not too sure this is great best practice in PHP but it makes our life easy and we can rely on $this->pad_image being in the class if we specify it in config.
  3. If maintaining aspect ratio and resizing we still may want to pad the image so we need to store the size that was originally wanted rather than what the current class does which is to change the requested sizes ($this->width, $this->height) to be the maximum bounding box with the same aspect ration as the original image that will fit inside our requested width and height. Therefore inside the initialize() function on line 276 (or directly before $this->image_reproportion();) I needed to store the requested dimensions before we loose them:
    
    $this->req_width = $this->width;
    $this->req_height = $this->height;
    
    
  4. The next thing we need to do is find the correct resize() function. In my case I'm using GD2 but I'm sure similar code could be written for the other graphics libraries supported by Image_lib.php. Replace the image_process_gd() function with the following slightly different code:
    <?php
            function image_process_gd($action = 'resize')
            {
                    $v2_override = FALSE;
    
                    // If the target width/height match the source, AND if the new file name is not equal to the old file name
                    // we'll simply make a copy of the original with the new name... assuming dynamic rendering is off.
                    if ($this->dynamic_output === FALSE)
                    {
                            if ($this->orig_width == $this->width AND $this->orig_height == $this->height)
                            {
                                    if ($this->source_image != $this->new_image)
                                    {
                                            if (@copy($this->full_src_path, $this->full_dst_path))
                                            {
                                                    @chmod($this->full_dst_path, DIR_WRITE_MODE);
                                            }
                                    }
    
                                    return TRUE;
                            }
                    }
    
                    // Let's set up our values based on the action
                    if ($action == 'crop')
                    {
                            //  Reassign the source width/height if cropping
                            $this->orig_width  = $this->width;
                            $this->orig_height = $this->height;
    
                            // GD 2.0 has a cropping bug so we'll test for it
                            if ($this->gd_version() !== FALSE)
                            {
                                    $gd_version = str_replace('0', '', $this->gd_version());
                                    $v2_override = ($gd_version == 2) ? TRUE : FALSE;
                            }
                    }
                    else
                    {
                            // If resizing the x/y axis must be zero
                            $this->x_axis = 0;
                            $this->y_axis = 0;
                    }
    
                    //  Create the image handle
                    if ( ! ($src_img = $this->image_create_gd()))
                    {
                            return FALSE;
                    }
    
                    //  Create The Image
                    //
                    //  old conditional which users report cause problems with shared GD libs who report themselves as "2.0 or greater"
                    //  it appears that this is no longer the issue that it was in 2004, so we've removed it, retaining it in the comment
                    //  below should that ever prove inaccurate.
                    //
                    //  if ($this->image_library == 'gd2' AND function_exists('imagecreatetruecolor') AND $v2_override == FALSE)
                    if ($this->image_library == 'gd2' AND function_exists('imagecreatetruecolor'))
                    {
                            $create = 'imagecreatetruecolor';
                            $copy   = 'imagecopyresampled';
                    }
                    else
                    {
                            $create = 'imagecreate';
                            $copy   = 'imagecopyresized';
                    }
    
                    $_dst_img = $create($this->width, $this->height);
                    $copy($_dst_img, $src_img, 0, 0, $this->x_axis, $this->y_axis, $this->width, $this->height, $this->orig_width, $this->orig_height);
    
                    if(!empty($this->pad_image) && $this->pad_image == TRUE)
                    {
                            // pad the top of the image if necessary 
                            $dst_x = $this->req_width - $this->width;
                            $dst_y = $this->req_height - $this->height;
    
                            // we want the image positioned at 50% if it is taller than it is wider.
                            if(abs($dst_x) > 0)
                            {
                                    $dst_x = round($dst_x/2);
                            }
    
                            // create a new image with a white background
                            $padded_dst_img = $create($this->req_width, $this->req_height);
                            $bg_color = imagecolorallocate($padded_dst_img, 255, 255, 255);
                            imagefill($padded_dst_img, 0, 0, $bg_color);
    
                            // copy the previous image over the new one.
                            $copy($padded_dst_img, $_dst_img, $dst_x, $dst_y, 0, 0, $this->width, $this->height, $this->width, $this->height);
                    }
                    $dst_img = isset($padded_dst_img) ? $padded_dst_img : $_dst_img;
    
                    //  Show the image
                    if ($this->dynamic_output == TRUE)
                    {
                            $this->image_display_gd($dst_img);
                    }
                    else
                    {
                            // Or save it
                            if ( ! $this->image_save_gd($dst_img))
                            {
                                    return FALSE;
                            }
                    }
    
                    //  Kill the file handles
                    imagedestroy($dst_img);
                    imagedestroy($src_img);
                    if(isset($padded_dst_img)) {
                            imagedestroy($padded_dst_img);
                    }
    
                    // Set the file to 777
                    @chmod($this->full_dst_path, DIR_WRITE_MODE);
    
                    return TRUE;
            }
    
Now you have images which are all the same size and consistently positioned with white space at the top. There are lots of variations on this theme that you might be able to make the code here better. It may make life easier than putting inline margins on images that come out of Image_lib in different sizes when trying to keep an image proportional.

CSS Transitions and Javascript

written by ajp, on Jan 6, 2010 12:35:00 PM.

If you are using CSS Transitions and want to provide Javascript equivalents to user agents that do not support them, this may help you:


function isCSSAnimCapable() {
    return (
        ("WebkitTransition" in document.documentElement.style) ||
        ("MozTransition" in document.documentElement.style) || 
        ("MsTransition" in document.documentElement.style) || 
        ("OTransition" in document.documentElement.style) ||
        ("Transition" in document.documentElement.style)
    );
}

It does however become a little messy trying to do animation from both Javascript and CSS. You have been warned.

All Change

written by ajp, on Oct 16, 2009 12:52:00 AM.

I have a finally published a blog and it uses Zine. It looks like a pretty impressive blogging engine written in python.

I'm looking forward to playing and configuring this machine and providing a few tutorials and updates on things I'm doing from Code Igniter, to frontend code, to breaking my new server :-D

For now that's it.