bitmapdata resize quality in Flex and Air
I had a project recently that required me to do a lot of image resizing. While the actionsript API makes it fairly straight forward to resize bitmaps the quality often leaves a lot to be desired. There isn’t the choice of interpolation algorithms the way there is in Photoshop. I was in a bit of a jam with my client, he was asking for better image quality. There wasn’t really much I could think of doing since actionscript takes care of the image resizing details and pixel manipulation isn’t my specialty.
Luckily I ran across a partial solution. Over at clevr.com they have written a bicubic and bilinear resizing algorithm to be used in actionscript. While not a complete panacea there was a noticeable improvement using their algorithms.
I found the biggest factor in determining the final image quality (with the tools available) is the difference in size between the image before resizing and after. The greater the difference the lesser the quality in resizing. While this is common sense, keeping this in mind allowed me to make some decisions about how to handle the resizing implementation in my application. I also ran some resizing tests using the same base image so that I could show my client the various factors at play.
Hopefully Adobe will add some stronger image resizing functionality in a future release but I’m sure they are trying to walk a fine line when it comes to adding graphics libraries to actionscript. After all, they don’t want somebody coming along with a program to compete with Photoshop using their own technology.
I didn’t need the entire clevr library so I took their InterpolatedBitmapData class and made some modifications for my own usage. I’ll post the code below for any who are interested but all credit for the work goes to the guys at clevr.
public static function getResizedImage(bmd:BitmapData,newWidth:int , newHeight:int):BitmapData
{
if(bmd == null)
return null;
var newBitMapData:BitmapData = new BitmapData( newWidth , newHeight,bmd.transparent);
var xFactor:Number = bmd.width / newWidth;
var yFactor:Number = bmd.height / newHeight;
for (var x:int = 0; x < newWidth; x++)
{
for (var y:int = 0; y < newHeight; y++)
{
newBitMapData.setPixel(x, y, getPixelBilinear(bmd,x * xFactor, y * yFactor));
}
}
return newBitMapData;
}
//the two methods below from http://clevrlib.riaforge.org/
/**
Computes the value of a pixel that is not on a pixel boundary.
@param theX The sub-pixel precision x-coordinate.
@param theY The sub-pixel precision y-coordinate.
*/
private static function getPixelBilinear(bmd:BitmapData,theX:Number, theY:Number): Number
{
var x:int;
var y:int;
var x_ratio:Number;
var y_ratio:Number;
var y_opposite:Number;
var x_opposite:Number;
var a:int;
var be:int;
var c:int;
var d:int;
var red:int;
var green:int;
var blue:int;
x = Math.floor(theX);
y = Math.floor(theY);
if((x < 1) || (y < 1) || ((x + 2) >= bmd.width) || ((y + 2) >= bmd.height))
return bmd.getPixel(x, y);
x_ratio = theX - x;
y_ratio = theY - y;
x_opposite = 1 - x_ratio;
y_opposite = 1 - y_ratio;
a = bmd.getPixel(x, y);
be =bmd.getPixel(x + 1, y);
c = bmd.getPixel(x, y + 1);
d = bmd.getPixel(x + 1, y + 1);
red = (r(a) * x_opposite + r(be) * x_ratio) * y_opposite + (r(c) * x_opposite + r(d) * x_ratio) * y_ratio;
green = (g(a) * x_opposite + g(be) * x_ratio) * y_opposite + (g(c) * x_opposite + g(d) * x_ratio) * y_ratio;
blue = (b(a) * x_opposite + b(be) * x_ratio) * y_opposite + (b(c) * x_opposite + b(d) * x_ratio) * y_ratio;
/*red = r(a);
green = g(a);
blue = b(a);*/
if(red < 0)
red = 0;
else if(red > 255)
red = 255;
if(green < 0)
green = 0;
else if(green > 255)
green = 255;
if(blue < 0)
blue = 0;
else if(blue > 255)
blue = 255;
return (red << 16) | (green <<
| (blue << 0);
}
/**
* RGB convenience methods
*/
private static function r(rgb:int):int {
return (rgb >> 16) & 0x0FF;
}
private static function g(rgb:int):int {
return (rgb >>
& 0x0FF;
}
private static function b(rgb:int):int {
return (rgb >> 0) & 0x0FF;
}
About this entry
You’re currently reading “bitmapdata resize quality in Flex and Air,” an entry on Cafe Silencio
- Published:
- 10.02.08 / 5pm
- Category:
- Adobe AIR, code snippets, stuff i learned
olso can aid in your development of SimpleDB applications with its intuitive graphic user interface (gui).- Cafe Silencio has created a powerful tool to explore SimpleDB. Instead you can spend your time developing your SimpleDB solution.
Easily and securely share files between you and your clients, colleagues, and friends with Kaze Cloud.- Another powerful tool from Cafe Silencio
6 Comments
Jump to comment form | comments rss [?] | trackback uri [?]