Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to save an image with a specific filesize?

Tags:

I am building a PHP system whereby users can create a visually complex image that has the final requirement of being 50kB or less.

The user can select to have text printed onto one of 37 template images, so the result is a single flat image.

The text can be any colour and one of a number of fonts. This means the final image can be quite visually complex and unpredictable (with the exception of image dimensions).

I then have the requirement of having the final image file size no greater than 50kB (this is an external requirement and cannot be changed).

The last requirement (again, external) is the image format must be .jpeg, .png, or .gif.

I have looked through the GraphicsMagick documentation, but cannot find anywhere that mentions being able to set the filesize and have the compression automatically calculated.

I have considered doing this programatically via a compress->save->test loop, however I can imagine this would be quite processor intensive as I cannot necessarily calculate the filesize based on compression in advance. This is why I am asking to see if the problem has already been solved in GraphicsMagick.

Edit

To be clear as to why there are external requirements:

The user will utilize this system to create a flat image, which they will then save onto their PC. This image is then to be uploaded to Adroll for use in a Retargeting campaign.

Here are Adroll's requirements on the image. My system will only provide the 728x90, 300x250, and 120x600 image sizes.

Edit 27th Nov, 2010

As this does not seem to be possible with GraphicsMagick, I am willing to look into other solutions, such as directly interfacing with compression libraries (libpng, etc) which may be able to provide the functionality.

As a last resort, it my even be feasible to look at algorithms which can accomplish this and implement one myself.


As an analogy, for those who are that way inclined:

I am after what A* is to search: It has a definite starting/ending point, and finds the best possible route in the fastest time.

What I was hoping to avoid was what Breadth/Depth First is to Search: definite starting/ending points, but may not hit on the optimal solution once finding a local minimum, and has the potential to completely blow out computationally.

like image 989
Jess Telford Avatar asked Nov 23 '10 00:11

Jess Telford


People also ask

How do I reduce the filesize of a photo?

The primary way to reduce the file size of an image is by increasing the amount of compression. In most image editing applications this is done by the selections you make in the “Save As” or “Export As” dialog box when saving a PNG, JPG, or GIF.


2 Answers

Since there is no way to compress to a target size that I know of, I suggest looking into an indirect solution:

  1. Do some quick stats (possibly by compressing lots of images with different JPEG compression factors) to find out what the mean compressed size and its standard deviation is for a given quality level.
  2. When accepting an image, try to compress with a suitable quality. If the resulting file is too big, decrease the quality and try again. Optionally, if it turns out too small you can increase the quality too.
  3. Stop when the resulting image is "close" to your target size, but smaller.

To elaborate a bit on the maths in step 2:

If you choose your starting quality such that your mean calculated size + 3 * standard deviation < your target size, then 99.7% of compressions will result in a suitably small file on the first try (assuming a normal distribution of compressed sizes).

You can tweak the starting quality and the logic that increases or decreases it as you wish, balancing between less server load and files closer to your maximum size ("making better use" of your restrictions).

like image 129
Jon Avatar answered Oct 09 '22 11:10

Jon


Have a look at the following package:

http://www.phpclasses.org/package/3810-PHP-Optimize-images-to-fit-in-a-given-file-size-limit.html

Pretty cool - I'd say the author deserves a beer ;)

Example image which is actually 61081 bytes (first ever jpeg image to show file size in image?):

alt text

like image 41
zaf Avatar answered Oct 09 '22 11:10

zaf