<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Jozef Chúťka&#039;s blog &#187; ResizeMath</title>
	<atom:link href="http://blog.yoz.sk/tag/resizemath/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.yoz.sk</link>
	<description>My life, my work</description>
	<lastBuildDate>Thu, 09 Sep 2010 14:00:43 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>SmoothImage Class (update)</title>
		<link>http://blog.yoz.sk/2010/01/smoothimage-class/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=smoothimage-class</link>
		<comments>http://blog.yoz.sk/2010/01/smoothimage-class/#comments</comments>
		<pubDate>Wed, 27 Jan 2010 15:54:28 +0000</pubDate>
		<dc:creator>Jozef Chúťka</dc:creator>
				<category><![CDATA[ActionScript]]></category>
		<category><![CDATA[Flash / Flex]]></category>
		<category><![CDATA[Bitmap]]></category>
		<category><![CDATA[BitmapData]]></category>
		<category><![CDATA[ImageResizer]]></category>
		<category><![CDATA[ResizeEvent]]></category>
		<category><![CDATA[ResizeMath]]></category>
		<category><![CDATA[SmoothImage]]></category>

		<guid isPermaLink="false">http://blog.yoz.sk/?p=955</guid>
		<description><![CDATA[While Flex uses bilinear resizing method when scaling images (event for Bitmap.smoothing() method), you won&#8217;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 ImageResizer.bilinearIterative() class in order to generate smoother resized results. In following example [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://blog.yoz.sk/wp-content/uploads/smoothImage1-200x101.jpg" alt="" title="smoothImage" width="200" height="101" class="alignleft size-medium wp-image-963" /></p>
<p>While Flex uses bilinear resizing method when scaling images (event for Bitmap.smoothing() method), you won&#8217;t be able to get nice results when downscaling more than 2 times. Inspired by <a href="http://blog.yoz.sk/2010/01/how-to-resize-an-image-with-actionscript/">ImageResizer class</a> I have also created SmoothImage Class. This object extends mx.Image and uses ImageResizer.bilinearIterative() class in order to generate smoother resized results.</p>
<p><span id="more-955"></span></p>
<p style="clear:both;">In following example mx.Image, <a href="http://cookbooks.adobe.com/post_A_better_smooth_Image_control-9409.html">SmoothImage</a> and <a href="http://classes.yoz.sk/sk/yoz/image/SmoothImage.as">sk.yoz.image.SmoothImage</a> used to demonstrate resizing original 1024x679px image.</p>
<p><iframe src="http://blog.yoz.sk/examples/smoothImage/" width="100%" height="300" style="border:none;"></iframe></p>
<p><a href="http://classes.yoz.sk/sk/yoz/image/SmoothImage.as">sk.yoz.image.SmoothImage</a> class:</p>
<pre class="brush: as3;">package sk.yoz.image
{
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.geom.Matrix;
    import flash.geom.Point;

    import mx.controls.Image;

    import sk.yoz.math.ResizeMath;

    public class SmoothImage extends Image
    {
        protected var _resizeFunction:String = &quot;bilinearIterative&quot;;
        protected var _iterationMultiplier:Number = 2;
        protected var resizedBitmap:Bitmap;

        public function SmoothImage()
        {
            super();
        }

        [Bindable(event=&quot;resizeFunctionChanged&quot;)]
        [Inspectable(category=&quot;Other&quot;, defaultValue=&quot;bilinearIterative&quot;,
            enumeration=&quot;bilinear,bilinearIterative&quot;)]
        public function set resizeFunction(value:String):void
        {
            if(value == resizeFunction)
                return;
            _resizeFunction = value;
            resizeBitmap();
        }

        public function get resizeFunction():String
        {
            return _resizeFunction;
        }

        [Bindable(event=&quot;iterationMultiplierChanged&quot;)]
        public function set iterationMultiplier(value:Number):void
        {
            if(value == iterationMultiplier)
                return;

            _iterationMultiplier = value;
            resizeBitmap();
        }

        public function get iterationMultiplier():Number
        {
            return _iterationMultiplier;
        }

        override protected function updateDisplayList(unscaledWidth:Number,
            unscaledHeight:Number):void
        {
            super.updateDisplayList(unscaledWidth, unscaledHeight);
            resizeBitmap();
        }

        protected function resizeBitmap(... rest):void
        {
            if(!width || !height || !content)
                return;

            if(resizedBitmap &amp;&amp; resizedBitmap.parent)
                resizedBitmap.parent.removeChild(resizedBitmap);

            resizedBitmap = new Bitmap(resizedBitmapData);
            addChild(resizedBitmap);
            content.visible = false;
        }

        protected function get resizeMethod():String
        {
            return maintainAspectRatio ? ResizeMath.METHOD_LETTERBOX
                : ResizeMath.METHOD_RAW;
        }

        protected function get resizedBitmapData():BitmapData
        {
            var bitmapData:BitmapData;

            if(content is Bitmap)
            {
                bitmapData = Bitmap(content).bitmapData
            }
            else
            {
                bitmapData = new BitmapData(content.width / content.scaleX,
                    content.height / content.scaleY, true, 0);
                bitmapData.draw(content);
            }

            var dimensions:Point = ResizeMath.newDimensions(
                new Point(bitmapData.width, bitmapData.height),
                new Point(width, height), resizeMethod, true);

            return ImageResizer[resizeFunction](bitmapData, dimensions.x,
                dimensions.y, resizeMethod, true, iterationMultiplier);
        }
    }
}</pre>
<p>Update (Jan 27, 2010): in sk.yoz.image.SmoothImage</p>
<p>Update (Jun 14, 2010): in sk.yoz.image.SmoothImage</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yoz.sk/2010/01/smoothimage-class/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>How to resize an image with ActionScript (update)</title>
		<link>http://blog.yoz.sk/2010/01/how-to-resize-an-image-with-actionscript/?utm_source=rss&amp;utm_medium=rss&amp;utm_campaign=how-to-resize-an-image-with-actionscript</link>
		<comments>http://blog.yoz.sk/2010/01/how-to-resize-an-image-with-actionscript/#comments</comments>
		<pubDate>Fri, 08 Jan 2010 12:31:43 +0000</pubDate>
		<dc:creator>Jozef Chúťka</dc:creator>
				<category><![CDATA[ActionScript]]></category>
		<category><![CDATA[Flash / Flex]]></category>
		<category><![CDATA[benchmark]]></category>
		<category><![CDATA[BitmapData]]></category>
		<category><![CDATA[ImageResizer]]></category>
		<category><![CDATA[Matrix]]></category>
		<category><![CDATA[pixel bender]]></category>
		<category><![CDATA[Point]]></category>
		<category><![CDATA[resize]]></category>
		<category><![CDATA[ResizeMath]]></category>

		<guid isPermaLink="false">http://blog.yoz.sk/?p=792</guid>
		<description><![CDATA[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() [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.yoz.sk/wp-content/uploads/imageResizeLanczos.jpg"><img src="http://blog.yoz.sk/wp-content/uploads/imageResizeLanczos-200x153.jpg" alt="imageResizeLanczos" title="imageResizeLanczos" width="200" height="153" class="alignleft size-medium wp-image-856" /></a></p>
<p>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 <strong>source</strong> image, new <strong>width</strong> and <strong>height</strong> and <strong>resize method</strong> (defined by ResizeMath class), and returns new bitmapData of resized image.</p>
<p>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 -&gt; 200px). So, I added <strong>bilinearIterative() method</strong> into ImageResizer class that creates resized bitmapData by multiple steps achieving <strong>much smoother results</strong>!</p>
<p><span id="more-792"></span></p>
<p style="clear:both;">Source of <a href="http://classes.yoz.sk/sk/yoz/image/ImageResizer.as">sk.yoz.image.ImageResizer</a> class:</p>
<pre class="brush: as3;">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 &gt; width
                    ? Math.max(w / iterationMultiplier, width)
                    : Math.min(w * iterationMultiplier, width);
                h = source.height &gt; height
                    ? Math.max(h / iterationMultiplier, height)
                    : Math.min(h * iterationMultiplier, height);
                result = bilinear(result || source, w, h, method,
                    allowEnlarging);
            }
            return result;
        }
    }
}</pre>
<p>Usage is pretty simple. You also gonna need <a href="http://classes.yoz.sk/sk/yoz/math/ResizeMath.as">sk.yoz.math.ResizeMath</a> class.</p>
<pre class="brush: as3;">var result:BitmapData = ImageResizer.bilinearIterative(sourceBitmapData, 100, 100,
    ResizeMath.METHOD_PAN_AND_SCAN);</pre>
<h2>Alternatives &amp; Benchmarking</h2>
<p>There are also another possible methods to resize/resample images. Read more about <a href="http://www.brooksandrus.com/blog/2009/03/11/bilinear-resampling-with-flash-player-and-pixel-bender/">bilinear resampling</a> and <a href="http://blog.onthewings.net/2009/08/25/bicubic-resampling-by-pixel-bender/">bicubic resampling</a> methods using pixel bender. I benchamrked all methods and here are the results:</p>
<pre class="brush: plain;">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</pre>
<p>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 <a href="http://en.wikipedia.org/wiki/Lanczos_algorithm">Lanczos algorithm</a> results (e.g. used in <a href="http://www.irfanview.com/">IrfanView</a>):</p>
<p><a href="http://blog.yoz.sk/wp-content/uploads/resizingMethodBenchmark1.jpg"><img src="http://blog.yoz.sk/wp-content/uploads/resizingMethodBenchmark1-200x189.jpg" alt="resizingMethodBenchmark" title="resizingMethodBenchmark" width="200" height="189" class="alignnone size-medium wp-image-854" /></a></p>
<p>Comparing ImageResizer.bilinear(), ImageResizer.bilinearIterative() and <a href="http://en.wikipedia.org/wiki/Lanczos_algorithm">Lanczos algorithm</a>:</p>
<p><a href="http://blog.yoz.sk/wp-content/uploads/imageResizeLanczos.jpg"><img src="http://blog.yoz.sk/wp-content/uploads/imageResizeLanczos-200x153.jpg" alt="imageResizeLanczos" title="imageResizeLanczos" width="200" height="153" class="alignnone size-medium wp-image-856" /></a></p>
<p>If you are looking for <a href="http://blog.yoz.sk/2009/10/bitmap-bitmapdata-bytearray/">transformation between BitmapData, Bitmap, ByteArray, read this article</a>. </p>
]]></content:encoded>
			<wfw:commentRss>http://blog.yoz.sk/2010/01/how-to-resize-an-image-with-actionscript/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>
