How to resize an image with ActionScript (update)

imageResizeLanczos

If you need to resize an image on client side, I mean real bitmapData resize (not just showing scaled), feel free to use ImageResizer class. This class takes bitmapData of source image, new width and height and resize method (defined by ResizeMath class), and returns new bitmapData of resized image.

Update: It seems that bitmapData.draw() method uses bilinear algorithm when scaling via Matrix. Bilinear algorithm gives you fine results when downscaling no more than 2 times (400px -> 200px). So, I added bilinearIterative() method into ImageResizer class that creates resized bitmapData by multiple steps achieving much smoother results!

Source of sk.yoz.image.ImageResizer class:

package sk.yoz.image
{
    import flash.display.BitmapData;
    import flash.geom.Matrix;
    import flash.geom.Point;

    import sk.yoz.math.ResizeMath;

    public class ImageResizer extends Object
    {
        public function ImageResizer()
        {
        }

        public static function bilinear(source:BitmapData, width:uint,
            height:uint, method:String, allowEnlarging:Boolean=true):BitmapData
        {
            var scale:Point = ResizeMath.scale(
                new Point(source.width, source.height),
                new Point(width, height), method, allowEnlarging);
            var result:BitmapData = new BitmapData(width, height, true, 0x0);
            var matrix:Matrix = new Matrix();
            matrix.scale(scale.x, scale.y);
            matrix.tx = (width - source.width * scale.x) / 2;
            matrix.ty = (height - source.height * scale.y) / 2;
            result.draw(source, matrix, null, null, null, true);
            return result;
        }

        public static function bilinearIterative(source:BitmapData, width:uint,
            height:uint, method:String, allowEnlarging:Boolean = true,
            iterationMultiplier:Number = 2):BitmapData
        {
            var w:uint = source.width;
            var h:uint = source.height;
            var result:BitmapData;
            while(!result || w != width || h != height)
            {
                w = source.width > width
                    ? Math.max(w / iterationMultiplier, width)
                    : Math.min(w * iterationMultiplier, width);
                h = source.height > height
                    ? Math.max(h / iterationMultiplier, height)
                    : Math.min(h * iterationMultiplier, height);
                result = bilinear(result || source, w, h, method,
                    allowEnlarging);
            }
            return result;
        }
    }
}

Usage is pretty simple. You also gonna need sk.yoz.math.ResizeMath class.

var result:BitmapData = ImageResizer.bilinearIterative(sourceBitmapData, 100, 100,
    ResizeMath.METHOD_PAN_AND_SCAN);

Alternatives & Benchmarking

There are also another possible methods to resize/resample images. Read more about bilinear resampling and bicubic resampling methods using pixel bender. I benchamrked all methods and here are the results:

source    | result  | ImageResizer | ImageResizer        | Bilinear PB | Bicubic PB
          |         | bilinear()   | bilinearIterative() |             |
4x4       | 200x200 |         0 ms |                3 ms |       16 ms |      31 ms
946x946   | 200x200 |         0 ms |                7 ms |       16 ms |      47 ms
1200x1200 | 200x200 |         0 ms |                9 ms |       32 ms |      47 ms

Comparing ImageResizer.bilinear() method with bilinear and bicubic pixel bender resizing. Even though, all methods are pretty fast, the results are far from beeing as good as Lanczos algorithm results (e.g. used in IrfanView):

resizingMethodBenchmark

Comparing ImageResizer.bilinear(), ImageResizer.bilinearIterative() and Lanczos algorithm:

imageResizeLanczos

If you are looking for transformation between BitmapData, Bitmap, ByteArray, read this article.

2 comments so far

  1. [...] you won’t be able to get nice results when downscaling more than 2 times. Inspired by ImageResizer class I have also created SmoothImage Class. This object extends mx.Image and uses [...]

  2. Frank March 6, 2010 00:37

    You saved my life ;-)

    Since days I was looking for a solution to scale large bitmapData to small ones. Thank you very much!

Leave a comment

Please be polite and on topic. Your e-mail will never be published.

Get Adobe Flash playerPlugin by wpburn.com wordpress themes