Friday, February 22, 2008

Reduce GIF size using RMagick

If you are creating GIF images using RMagick and your application has very stringent size restrictions (i.e. mobile devices) then this post may help you get the most of RMagick.

While it is possible to control the compression of JPEG and PNG files using the quality parameter for GIF files we are left with almost no options. Fortunately a little understanding of the default, and only, compression scheme used in GIF can help you improve the compression performance of your images.

The LZW compression algorithm used in GIF images and developed by Abraham Lempel, Jakob Ziv and Terry Welch, contructs a color table for an image wherein each color value is matched to a pixel. Thus, images with large areas of one color will be compressed far better than those that those that do not have such color blocks.

So to get better compression (smaller images) we must ensure we have large contiguous blocks of the same color in our image. When creating images in ImageMagick we can use these tips to ensure small size results:

First: Make use simple graphics with flat colors (i.e. avoid using Magick::GradientFill).

Second: when using an RMagick::Draw object always make sure you call the stroke_antialias(false) method on it:



1 require "RMagick"

2

3 gc = Magick::Draw.new

4 gc.stroke_antialias(false)

5

6 # your drawing code below




Third: When writing text using the annotate method from the Magick::Draw or Magick::Image classes do not use text antialiasing:



1 require "RMagick"

2

3 gc = Magick::Draw.new

4

5 gc.annotate(img,...) {

6   self.text_antialias = false

7 }




A very simple method to reduce the image size is using the despeckle filter on the image. This will reduce the color dither making the color distribution more planar so we have larger portions of the image with the same color. By doing this the LZW algorithm can reduce the final image size up to a 20% of the original size depending on the image.



1 require "RMagick"
2     
3 small_image = big_image.despeckle
4 small_image.write("small_image.gif"){
5     self.compression = Magick::LZWCompression
6     self.dither = false
7 }




Actually calling self.compression is not needed as it is set by default by RMagick but is good just to make sure.

Resources
http://rmagick.rubyforge.org/
http://www.faqs.org/faqs/jpeg-faq/part1/section-9.html
http://rmagick.rubyforge.org/src_over.html
http://www.webdevelopersnotes.com/graphics/gifs_compression_algorithm.php3

No comments:

Post a Comment