2

I'm using Imagick and like to scale an image to a maximum file size of 2.5MB

I had a look to this SOF question: ImageMagick: scale JPEG image with a maximum file-size which is exactly what I want to do but the extent() method from Imagick does not have the size parameter: http://www.php.net/manual/en/imagick.extentimage.php

Anyone knows how I could to it? At the moment I'm trying to calculate a coefficient between the original file size and the target file size to calculate a new resolution but found out that the resolution is not proportional to the file size.

Update - The output format is always JPEG so if there is a way to calculate the size before to save it that would be great

Thanks in advance, Maxime

Community
  • 1
  • 1
maxwell2022
  • 2,698
  • 4
  • 38
  • 57

1 Answers1

3

The extent function you're calling is just to set the size of an image.

The function to set the jpeg extent option is:

$imagick->setOption('jpeg:extent', '2500kb');

Interestingly, the function $imagick->getImageBlob() seems to crash after setting this option. You are forced to write the file to disk, rather than being able to get it's bytes directly.

The output format is always JPEG so if there is a way to calculate the size before to save it that would be great

There isn't. The amount of detail that is in each image determines what size the image will be after compression, for a given image quality. So it's not possible to calculate the quality level that will give a final size.

The C code from the underlying Image Magick library that limits the file size is:

maximum=101;
for (minimum=2; minimum < maximum; )
{
    jpeg_image->quality=minimum+(maximum-minimum+1)/2;
    status=WriteJPEGImage(jpeg_info,jpeg_image);
    if (GetBlobSize(jpeg_image) <= extent)
      minimum=jpeg_image->quality+1;
    else
      maximum=jpeg_image->quality-1;
    }
}

I.e. it just recompresses the file at different image quality levels, until it finds the level that gives the acceptable file size for the given value.

Danack
  • 23,022
  • 14
  • 78
  • 112
  • Thanks Danack, id `WriteJPEGImage` and `GetBlobSize` are PHP functions? Or was it just additional information on how Imagick is handling the `$imagick->setOption('jpeg:extent', '2500kb');` ? – maxwell2022 Oct 29 '13 at 02:49
  • @maxwell2022 That's from the Image Magick library that Imagick allows you to use in PHP - so that's C code. The Imagick function would be `Imagick::writeImage($filename);` and then filesize($filename). – Danack Oct 29 '13 at 03:23
  • That's potentially a lot of disk access to save one image. Is there a way to estimate the quality according the 2 first writes. ie. `q:100 = fs:3000Kb` and `q:99 = fs:2900kb` so try `q:95` and you should have a `fs:2500kb`, if `fs` still too high keep estimating the quality according the new result...? – maxwell2022 Oct 29 '13 at 04:02
  • You're certainly free to make you own algorithm, but I don't think it's possible to predict with any accuracy how data a certain quality level of compression will take. – Danack Oct 29 '13 at 04:14
  • Thanks for your help, I'll have implement something in the coming days and I'll update my question with it. – maxwell2022 Oct 29 '13 at 04:34