Codeigniter Image_lib convert() v1.3 JPG to GIF to PNG

I recently performed some code-fixing for a library extension I found over in CodeIgniter’s forum. The mod provided a convert() method for the Image_lib library. It lets you to convert (duh) the original image from/to JPG (default), GIF or PNG and optionally delete the original image.

When I first added this extension into my CI distribution, everything still worked without throwing errors so I started calling the new function. Then…

Problem #1: If you tell convert() to delete the original, the missing file reference would making the rest of the Image_lib functions choke

Problem #2: If you swap the order of the functions (in my case, i was originally using convert before resize), the convert function “double-resized” the original image.

Solution: Remove any reference to resizing functions in the convert() methods and update the source path if the original file was deleted during the conversion process. I also removed the check for a configuration array in the class extending constructor since that is handed by another function in the main library.

The update code for the CodeIgniter Image_lib convert() function/method is provided below.

<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

/**
 * CodeIgniter Image Manipulation Class extended with function
 * for converting images
 * Usage:
 *   $config['source_image'] = './uploads/my_pic.png';
 *   $this->image_lib->initialize($config);
 *   $this->image_lib->convert('jpg', TRUE);
 *
 *
 * @package CodeIgniter
 * @subpackage MY_Image_lib
 * @license GPLv3 <http://www.gnu.org/licenses/gpl-3.0.txt>
 * @link http://codeigniter.com/forums/viewthread/145527/
 * @version 1.3
 * @author Ripe <http://codeigniter.com/forums/member/119227/>
 * @modified waldmeister <http://codeigniter.com/forums/member/57608/>
 * @modified ebspromo <http://www.robertmullaney.com/>
 */
class MY_Image_lib extends CI_Image_lib
{
 function MY_Image_lib()
 {
  parent::CI_Image_lib();
 }

 /**
 * converts images
 *
 * @access public
 * @param string
 * @param bool
 * @return bool
 */
 function convert($type = 'jpg', $delete_orig = FALSE)
 {
  $this->full_dst_path = $this->dest_folder . end($this->explode_name($this->dest_image)) . '.' . $type;

  if (!($src_img = $this->image_create_gd()))
  {
   return FALSE;
  }

  if ($this->image_library == 'gd2' AND function_exists('imagecreatetruecolor'))
  {
   $create = 'imagecreatetruecolor';
  }
  else
  {
   $create = 'imagecreate';
  }
  $copy = 'imagecopy';

  $props = $this->get_image_properties($this->full_src_path, TRUE);
  $dst_img = $create($props['width'], $props['height']);
  $copy($dst_img, $src_img, 0, 0, 0, 0, $props['width'], $props['height']);

  $types = array('gif' => 1, 'jpg' => 2, 'jpeg' => 2, 'png' => 3);

  $this->image_type = $types[$type];

  if ($delete_orig)
  {
   unlink($this->full_src_path);
   $this->full_src_path = $this->full_dst_path;
  }

  if ($this->dynamic_output == TRUE)
  {
   $this->image_display_gd($dst_img);
  }
  else
  {
   if (!$this->image_save_gd($dst_img))
   {
    return FALSE;
   }
  }

  imagedestroy($dst_img);
  imagedestroy($src_img);

  @chmod($this->full_dst_path, DIR_WRITE_MODE);

  return TRUE;
 }
}

/* End of file MY_Image_lib.php */
/* Location: ./application/libraries/MY_Image_lib.php */

13 thoughts on “Codeigniter Image_lib convert() v1.3 JPG to GIF to PNG

  1. rotinpain

    i’ve read the whole topic on C.I. forums, the code seems very interesting and reply to the a non existing image conversion method, I’ll give it a try ! big thanks!

    Reply
  2. Robert Mullaney Post author

    Let me know if you run into any issues. I wrote this code to satisfy my own needs and don’t know if anyone else has tried to use it. I’ll be glad to assist with debugging if it doesn’t do what you expect.

    Reply
  3. Nicholas Morgan

    Robert, thanks for this awesome extension. I am using it now for my current PHP application. I was wondering if this function can somehow allow you to pick the filename that you want it to be converted to, like in the initialization array? My usage of your function currently looks like this:

    Picture::convert(array(
    ‘source_image’ => ‘usermedia/pictures/currently_processing/’ . $uploaded[‘file_name’],
    ));

    So, I upload the image first into the directory called “currently_processing”, and then I convert it to .JPG using your function. I was hoping I’d be able to rename the converted version to the ID of the user, concatenated with an underscore, concatenated with the current UNIX timestamp, concatenated with “.jpg”, which would look something like this: “7442_1319280674.jpg”.

    However, I am unsure how this would be done using your function.

    Reply
  4. Robert Mullaney Post author

    My method/function does not process the ‘new_image’ config variable. I generally performed additional processing after the conversion (eg: resize original, make a thumbnail, etc).

    The following methods natively support $config[‘new_image’]

    $this->image_lib->resize()
    $this->image_lib->crop()
    $this->image_lib->rotate()
    $this->image_lib->watermark()

    Feel free to modify the convert() method to ‘new_image’ by examining it’s usage in the above methods.

    Note: I can revisit the code and add renaming support, but it will have to be when I have some more free time.

    Reply
  5. Robert Mullaney Post author

    I looked at the Image_lib code real quick and it should already support renaming.

    Try it like this…

    $config = array(
        'source_image' => 'usermedia/pictures/currently_processing/' . $uploaded['file_name'],
        'new_image' => $userid . '_' . time() . '.jpg'
    );
    $this->load->library('image_lib', $config);
    $this->image_lib->convert();
    Reply
  6. Dacus

    Thanks for code, but I found bug. You should change these lines to be able to use other functions, like resize, before convert properly:

    // $props = $this->get_image_properties($this->full_src_path, TRUE);
    // $dst_img = $create($props[‘width’], $props[‘height’]);
    // $copy($dst_img, $src_img, 0, 0, 0, 0, $props[‘width’], $props[‘height’]);
    $dst_img = $create($this->width, $this->height);
    $copy($dst_img, $src_img, 0, 0, 0, 0, $this->width, $this->height);

    Reply
    1. admin Post author

      No. You’re probably better off checking out Imagick’s “convert” function. With that you can do image/pdf and vice versa.

      Reply
  7. Francis

    Your style is so unique in comparison to other folks I have read stuff from.
    Thanks for posting when you’ve got the opportunity, Guess I will just bookmark this blog.

    Reply
  8. Peter Drinnan

    This is good. There is a minor update needed for the latest version of CI. In the constgructor change:

    parent::CI_Image_lib();
    to
    parent::__construct();

    You will also need Dacus’s patch:

    // $props = $this->get_image_properties($this->full_src_path, TRUE);
    // $dst_img = $create($props[‘width’], $props[‘height’]);
    // $copy($dst_img, $src_img, 0, 0, 0, 0, $props[‘width’], $props[‘height’]);
    $dst_img = $create($this->width, $this->height);
    $copy($dst_img, $src_img, 0, 0, 0, 0, $this->width, $this->height);

    Reply
    1. admin Post author

      I don’t consider Dacus’s idea a patch, just a shortcut for a specific situation. If you need to convert() then resize() or vice-versa just call them in the desired order (see #2 below).

      1. Originally written around CI 1.7 which still supported php4. Even though the code is not php5 spec, it should work until support is removed in php6.

      PHP: Constructors and Destructors
      For backwards compatibility, if PHP 5 cannot find a __construct() function for a given class, and the class did not inherit one from a parent class, it will search for the old-style constructor function, by the name of the class. Effectively, it means that the only case that would have compatibility issues is if the class had a method named __construct() which was used for different semantics.

      2. My method does not resize because that is already built into Image_lib.

      Not trying to reinvent the wheel, just add some new rubber to it 😉

      I underlined the original text where it stated the intentional removal of resize references in my revision

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *