views:

354

answers:

1

I have a site where users can upload images. I process these images directly and resize them into 5 additional formats using the CodeIgniter Image Manipulation class. I do this quite efficiently as follow:

  • I always resize from the previous format, instead of from the original
  • I resize using an image quality of 90% which about halves the file size of jpegs

The above way of doing things I implemented after advise I got from another question I asked. My test case is a 1.6MB JPEG in RGB mode with a high resolution of 3872 x 2592. For that image, which is kind of borderline case, the resize process in total takes about 2 secs, which is acceptable to me.

Now, only one challenge remains. I want the original file to be compressed using that 90% quality but without resizing it. The idea being that that file too will take half the file size. I figured I could simply resize it to its' current dimensions, but that doesn't seem to do anything to the file or its size. Here's my code, somewhat simplified:

$sourceimage = "test.jpg";
$resize_settings['image_library'] = 'gd2';
$resize_settings['source_image'] = $sourceimage;
$resize_settings['maintain_ratio'] = false;
$resize_settings['quality'] = '90%';
$this->load->library('image_lib', $resize_settings);

$resize_settings['width'] = $imagefile['width'];
$resize_settings['height'] = $imagefile['height'];
$resize_settings['new_image'] = $filename;
$this->image_lib->initialize($resize_settings);
$this->image_lib->resize();

The above code works fine for all formats except the original. I tried debugging into the CI class to see why nothing happens and I noticed that the script detects that the dimensions did not change. Next, it simply makes a copy of that file without processing it at all. I commented that piece of code to force it to resize but now still nothing happens.

Does anybody know how to compress an image (any image, not just jpegs) to 90% using the CI class without changing the dimensions?

+1  A: 

I guess you could do something like this:

$original_size = getimagesize('/path/to/original.jpg');

And then set the following options like this:

$resize_settings['width'] = $original_size[0];
$resize_settings['height'] = $original_size[1];

Ok, so that doesn't work due to CI trying to be smart, the way I see it you've three possible options:

  • Rotate the Image by 360º
  • Watermark the Image (with a 1x1 Transparent Image)
  • Do It Yourself

The DIY approach is really simple, I know you don't want to use "custom" functions but take a look:

ImageJPEG(ImageCreateFromString(file_get_contents('/path/to/original.jpg')), '/where/to/save/optimized.jpg', 90);

As you can see, it's even more simpler than using CI.


PS: The snippet above can open any type of image (GIF, PNG and JPEG) and it always saves the image as JPEG with 90% of quality, I believe this is what you're trying to archive.

Alix Axel
Thank you for responding. Well, that is in fact what I'm already doing. The $imagefile array holds the original width and height which I use to configure the resize class.
Ferdy
Oh, I'm sorry. I didn't read your question till the end. Check my edit in a couple of minutes.
Alix Axel
No problem, thank you for helping out again. Alright, I did a few tests. Rotating is not supported by GD2, at least that is what CI gives back as an error. I can rotate by switching to imagemagick, but that increases the file size instead of decreasing it. I can see how your code would be easy to use and I have no problem stepping out the CI class for this, but I need something that works with GIF and PNG too.
Ferdy
My code snippet **does work for GIF, PNG and JPEG** images, try it! All you need to do is change the file extensions. BTW, CI image library is really bad, rotating an image **is** supported by GD (bundled), check http://php.net/manual/en/function.imagerotate.php.
Alix Axel
Cool, I was going to say that I want the original file type to be preserved but then I saw that there is also a imagepng and imagegif function. I will try these out tomorrow and report back. Thanks once again!
Ferdy
You can't actually compress GIF images and PNG images should always be compressed to the highest level (9).
Alix Axel
Thanks, I now detected the file extension, if it's a JPEG I use the function you mention, otherwise I just keep the original. It works quite well. I did notice some unexpected behavior, when resizing using CI and using a quality setting of 90%, its cuts the file size between a factor of 2 and 3. If I use the function you mention with a setting of 90% on the original it only takes of about 30%. I have to lower the quality to 70% to halve the file size of the original. I assume this has to do with the image, not the functioned used. Either way, thank you very much for all the help!
Ferdy
@Ferdy: There is no reason why this method should compress less than CI image library since they both use the same functions, try testing both methods with the same source image.
Alix Axel
On a second though I think it can compress a little more if you use the `ImageInterlace` function, but that would make the image incompatible with Adobe Flash.
Alix Axel
I cannot compare the compression rate of the original using CI and the function you suggested since CI does not compress if the dimensions stay the same. Still, for the smaller formats CI does resize and at 90% that reduces the file size by a factor 2 to 3, much more than compressing the original. I also noticed some strange behavior, viewing the file in explorer it says it is 212KB, checking its properties says its 0.99MB on disk. By the way, tried the imageinterlace bit, doesn't decrease the file size in my testing but does fix the strange file size bug in file explorer.
Ferdy