Dynamically loading bitmaps with smoothing in Flash Player 8
We have gotten a bunch of feedback on this oversight in Flash Player 8. Well oversight might be an understatement, it's really a bug. When you dynamically load a bitmap in a Flash 8 file, smoothing is always turned off and rotating or scaling an image will yield ugly artifacts. Originally I made this choice for performance reasons, as smoothed display is much slower than the standard 'nearest neighbour' scaling method. Little did I know that there would be an uproar among users :-)
Now, there is some good news. Flash Player 8.5 will fix this for AS3.0 and we will even add a new property to the AS2.0 MovieClip class which will allow you to turn this on and off dynamically. The current name of that boolean property is MovieClip.forceSmoothing, which subject for change though. This property will be enabled for version 8 Flash content also, not only 8.5. Once we update the Flash Player 8.5 alpha on the labs site (I can't tell you when/how/if this will happen since I do not know) you should definitely check it out and give us feedback on it.
In the meantime there is a workaround using BitmapData which has been floating around already. For those of you who have not played with the BitmapData object yet and feel left out, let me post a little snippet which will do the job:
To use this snippet simple paste the function into your code and then load a bitmap this way f.ex.:
This leaves you with a movie clip which contains the smoothed bitmap. Here is a sample .fla and .swf. Obviously this snippet might not be exactly suitable for your needs, especially if you need to handle loading events, but it should give you an idea how it generally works.
Now, there is some good news. Flash Player 8.5 will fix this for AS3.0 and we will even add a new property to the AS2.0 MovieClip class which will allow you to turn this on and off dynamically. The current name of that boolean property is MovieClip.forceSmoothing, which subject for change though. This property will be enabled for version 8 Flash content also, not only 8.5. Once we update the Flash Player 8.5 alpha on the labs site (I can't tell you when/how/if this will happen since I do not know) you should definitely check it out and give us feedback on it.
In the meantime there is a workaround using BitmapData which has been floating around already. For those of you who have not played with the BitmapData object yet and feel left out, let me post a little snippet which will do the job:
import flash.display.*;
function loadBitmapSmoothed(url:String, target:MovieClip) {
// Create a movie clip which will contain our
// unsmoothed bitmap
var bmc:MovieClip = target.createEmptyMovieClip(
"bmc",
target.getNextHighestDepth());
// Create a listener which will notify us when
// the bitmap loaded successfully
var listener:Object = new Object();
// Track the target
listener.tmc = target;
// If the bitmap loaded successfully we redraw the
// movie into a BitmapData object and then attach
// that BitmapData to the target movie clip with
// the smoothing flag turned on.
listener.onLoadInit = function(mc:MovieClip) {
mc._visible = false;
var bitmap:BitmapData = new BitmapData(
mc._width,
mc._height,
true);
this.tmc.attachBitmap(
bitmap,
this.tmc.getNextHighestDepth(),
"auto",
true);
bitmap.draw(mc);
};
// Do it, load the bitmap now
var loader:MovieClipLoader = new MovieClipLoader();
loader.addListener(listener);
loader.loadClip(url, bmc);
}
To use this snippet simple paste the function into your code and then load a bitmap this way f.ex.:
createEmptyMovieClip("myMC",getNextHighestDepth());
loadBitmapSmoothed("mypic.jpg",myMC);
This leaves you with a movie clip which contains the smoothed bitmap. Here is a sample .fla and .swf. Obviously this snippet might not be exactly suitable for your needs, especially if you need to handle loading events, but it should give you an idea how it generally works.

67 Comments:
I'm not quite clear, will this only be fixed in 8.5 player, or will there also be an update to the 8 player that will fix this?
I wonder what happens with the original movie that you have loaded? As I understand it that one will still eat up some memory, won't it? So wouldn't it be more effective to delete the movie after the draw command? And what's your recommended method of doing that removeMovieClip(), unloadMovie() or maybe createEmptyMovieClip() at the same level?
what about the _quality = "best"; ?
That would also make the bitmaps smooth while being rotated and scaled, right?
^^ Nope it won't, thats the whole problem :(
This code is great! My one question is if there is a way to do this and preserve alpha channels. The alpha channel in my pngs drop out when I use this code. Thanks!
^^ I think you might be able to use this but I haven't tested it myself:
myBitmapData.transparent = true;
oh yes I tried this workaround before. However this will not work if the images being loaded are on a different network. the Sandboxing eliminates the ability to capture or manipulate bitmap data generated from these. But still better than nothing (waits for 8.5)
you can preserve the alpha channels using this line instead of the existing one:
var bitmap:BitmapData = new BitmapData(mc._width, mc._height, true, 0x000000);
don't ask my why it needs the redundant 0x000000 to function though!
What if you are using the loader component? Any way to force _quality="BEST" on this? Will this be fixed?
The copy bitmap will only work for images from the same domain. There is an issue with the Flash player security settings that will prevent you to do make bitmap copy for resources residing in another domain. An option is to put them in swf files but the issue remains open for FLV files server from a streaming server.
If anyone is aware of a workaround please post it.
Why can you only load images from thesame domain?! That really s***, because what to do when you'd like to load images from Flickr? What if php doesn't run on your server?!
Please people do something about this.. You're helping nobody with this!
Thank you very much for this information! Really helped me for a project I have to finish in two(!) days..;)
Even the hint to preserve alpha channels worked!
Thanks again and best regards, Roger
how can I save an image (the screen shot) from flash into local disk?
sun
I do not know if you will even read this.
I am loading a jpg from another site and then am scaling it using:
mc._height = 164
mc._width = 164
Of couse without smoothing this look like crap. How could I do the smoothing and then resize the movie clip?
it's a nice workaround but there are several drawbacks you should'nt forget:
- converting needs performance big time
- doing anims with those bitmaps aint not fun too
just stumbled on this bug while working on a gallery - bitmapping 700x400 pics needs 100% load for at least 1-2secs (@3ghz)
and for the planned anims its a complete showstopper.
looks like the peeps over a macromedia never use their own stuff =)
I would really like to know the reasons as to why this sandbox thingy exists for the draw function. I see no reason, if I would like to steal an image or a video off-site for some reason, I certainly wouldn't use flash.
How come it's not documented? I had to spend two hours figuring out what return -5 meant, I thought I had some error in my code first (BitmapData.draw() is not even documented to have any return).
This kills so many creative possibilities it's ridiculous, it would really be sad if this is forced to be there for legal reasons or something, but if not, please fix asap cause it's killing me and my applications...
/Markus
To those objecting to the cross-domain restrictions, three things.
First, you can use BitmapData.draw across domains if what you're draw()ing is a SWF, and that SWF calls System.security.allowDomain to permit access by your domain (or all domains).
Second, there was an omission in FP8: we didn't provide a way to permission BitmapData.draw() across domains when the thing you're draw()ing isn't a SWF (e.g. it's a bitmap). This will be fixed in FP9; you will be able to use policy files to permit such things.
Third, while of course we understand that security is frustrating, please don't take the attitude that we don't understand what we're doing or that we're trying to mess up your lives. The reason you have any livelihood at all writing Flash content is that the Flash Player is on >95% of Internet-connected machines in the world. That would quickly cease to be the case if anyone managed to write a malicious SWF that stole files off your machine or impersonated you to your bank. Preventing problems like this is very difficult, and sometimes has the unfortunate effect of requiring you to prove the legitimacy of what you're doing, so that we can distinguish your legitimate case from a variety of illegitimate cases. Believe me, we hate introducing barriers for Flash developers. But, in the end, we can't live with security vulnerabilities, so we do our best to design a secure runtime.
As time goes by, hopefully we'll do a better job documenting how to deal with Flash security. The new AS3 docs will contain a big chapter on security, and while it will be big and confusing, it's a start, and it will be getting more love in future releases.
a simple proxy script will serve the purpose of fixing the bitmap.draw sandbox limitations. I've already implemented the solution without any issue. Works great and I don't have to wait on FP9.
First, excuse my english. There is a methot to get images from another domain. Create a php file, hosted at the same domain that the swf. This php could get the image data from another domain, like from flickr.com, for example. This work.
Hi,
Flash Player 9 has been released.
I can't find any information about "MovieClip.forceSmoothing". Is there a documentation I've missed?
Thanks, Lars
This issue still doesn't seem to be fixed in Flash 9. In the preview release of Flash 9 I tried the follow code:
stage.quality = StageQuality.BEST;
var request:URLRequest = new
URLRequest("http://www.google.com/intl/en/images/logo.gif");
var loader:Loader = new Loader();
loader.load(request);
addChild(loader);
When you zoom in on the Flash movie the image remains aliased and not
smoothed. Please tell me I'm missing something, that there's a simple
way to smooth an image once loaded in, and not that this issue still
hasn't been fixed.
Many thanks.
Still haven't managed to fix this bug in the released version of Flash 9, eh? Does anyone with a half a brain work on the Flash player team anymore?
I use this php script in the same host i have the swf.
// put ...php?src=IMAGEURL
header("Content-type: image/jpeg");
$file = fopen ($_GET["src"], "r");
if (!$file) {
echo "Unable to open remote file.\n";
exit;
}
while (!feof ($file)) {
$line = fgets ($file, 1024);
echo $line;
}
fclose($file);
You can test it at http://www.familiacastilloquero.com/
The php is at http://www.familiacastilloquero.com/traeimagen.php?src=http://static.flickr.com/66/160704305_e86f330d71.jpg?v=0
So wait--- how do we use the snippet??
Great, was looking for a fix for this!
God Bless you my Son!!
Thank you very much for this snippet, it helped me loads!
Another possible solution for the smooth image loading is a tiny FP7 swf used as an RSL in your project with the express purpose of loading images under it. If you attachMovie() a shared movieclip from the FP7 RSL in the main FP8+ swf, and then load an image under the attachedMovie, the image seems to load using FP7 rules (i.e., smoothed). The full discussion is here.
it really works
thx a lot
Hi there! Can you help me with where to put loadBitmapSmoothed("mypic.jpg",myMC);??
I'm loading a bunch of pictures into a clip dynamically that I'm enlarging on rollover and a bit of a newbie to AS. a snippit of my code...
function thumbnails_fn(k) {
thumbnail_mc.createEmptyMovieClip("t"+k, thumbnail_mc.getNextHighestDepth());
tlistener = new Object();
tlistener.onLoadInit = function(target_mc) {
target_mc._xscale = target_mc._yscale = 75;
target_mc._x = hit_left._x+(target_mc._width+5)*k;
target_mc.pictureValue = k;
help would be greatly appreciated!!
Cheers Tinic!
The fix worked an absolute treat.
Tinic,
I'm using Flash CS3 and I can't find any reference to the MovieClip.forceSmoothing parameter. Did that get cancelled? Right now I'm using a proxy script and bitmapData to get external images (i.e. Flickr) to smooth in Flash 8 and bypass the security issues. This is NOT an effective solution. Is there a simpler way to smooth images loaded from other servers in CS3?
Thanks,
Mark
hi.
in Flash CS3 check out from help
ActionScript classes > MovieClip > forceSmoothing (MovieClip.forceSmoothing property)
it's there but it only works with loadmovie()?
Im using movieliploader and this gives no effect.
We are developing an dynamic animated image gallery using Flash 8 & AS2, for which the images are called up from a different domain. I have used the reflection class (in which bitmapdata.draw() works ) to achieve reflections. This works fine when the images are called from the same domain. But, when the images are called from another domain, the reflection class does not work because bitmapdata.draw() does not work on crossdomain images due to sandbox security. Although the images are showing up. I have been trying this for the last few days with little success.
Please help me how to do ?
you can check same gallery at :
http://www.amazon.com
can you tell me how can i use bitmapdata.draw on loaded image from cross domain server. i am continue trying but little success.
Please help me.
Adobe needs to fix this for good !
In the meantime your snippet worked smoothly ! ;-)
Thanks a lot !
Is it possible to apply a smooth with BitmapData on a picture of the library linked by attachMovie?
I like articles like this. Thanks!
You are a Genious man!, Im not a programmer, just a flash designer with some knlwledge of AS2 coding, and this issue have bother me for a long time, I have tested your solution and works perfect
Thanks!!!
Great Article! Thank You!
Thanks to author! I like articles like this, very interesting.
Hi,
I'm using the following code, yet I cannot get the image smoothing to work.
var myBitmapData:BitmapData = new BitmapData(96,96,true);
myMatrix = new Matrix();
myMatrix.scale(.15,.15);
var mc_1:MovieClip = this.createEmptyMovieClip("mc", this.getNextHighestDepth());
mc_1.attachBitmap(myBitmapData,myMatrix,"auto",true);
myBitmapData.draw(_root.car,myMatrix);
Any help would be apprecaited.
nice blog!
What a friggin´ mess of a solution to anti-alias dynamically loaded images!
Why in the world is this excruciating problem not solved yet..?!?
nice blog!Nice information
:-) ochen\' zaebatyj blog!
soglasen s vami ochen\' zaebatyj blog!
Keep up the great work. It very impressive. Enjoyed the visit!
Nice! Nice site! Good resources here. I will bookmark!
Hi. Solution works well with loaded images, thank you for that.
Problem to be solved now....how do I mask the loaded image using your provided code?
simply setting
mc.setMask(masker);
in the onLoadInit function does not do the trick.
Thanks in advance
-----------------------
well that was easier than expected.
never mind
needed to refer to my initial movieClip -doh-
-----------------------
marc
Hi Tinic
What's the current status of this? In Flash player 9 we still are having issues. We can set the stage quality to BEST to get decent looking images, but this doesn't work in AIR!
Can you advise how we might be able to do proper anti-aliasing in AS3 code instead? Maybe some mip map or something?
thanks
charles
What has me really confused is that the dynamically loaded jpegs are smoothed here: http://www.actionscript.org/resources/articles/129/1/MovieClipLoaders-Part-2---Looping-and-Listeners/Page1.html
Anyone know what the story is?
This example has worked great for me,.
However I'm working on a photographers website and am noticing that there is a loss in image quality, ie: contrast and original color is washed out,.
I'm using the bitmapData example above, then setting the stage.scale="showall";
for scalability..
compare here:
http://shanemccauley.com/4/ - contrast issue
http://shanemccauley.com/3/ - previous version, some distortion, decent contrast values..
any ideas ?
Hello,
Awesome script. Works well.
Question, How can I create a loader for this? All I need is a percentage loader.
Thank you.
This code is great but how do you use it for a WHOLE GALLERY of images pulling from a folder through XML?
Ive spent the last 6 hours trying to figure it out and cant! help!!!!
thanks for the help, was wonering for a while how you could do this in AS2.
This code is great but how do you use it for a WHOLE GALLERY of images pulling from a folder through XML?
Ive spent the last 6 hours trying to figure it out and cant! help!!!!
If you figure out how to modulate this code over to a class(which goes pretty easy) then you can load your gallery using the call to load the external asset for each image. Piece of cake.
The way to do it in flash 9 is MUCH simpler.
in the completeHandler function the code it simply:
var image:Bitmap = Bitmap(loader.content);
image.smoothing = true;
aContainer.addChild(image);
Gracias!!
Thanks! I think i'll switch as soon as possible to AS3, it pays for the effort :)
Make smoothing DEFAULT !!
Thank you for this, it proved perfect for my application.
THanks for the code... THis will same me a headache. I was rackin my brain for hours trying to figure this out.
how on earth should i go about preloading this data? i have a series of neccesarily high res jpg's but there isa pretty long hang time with this script. is is great though dont get me wrong...
preload?? any ideas?
Yeah... no offense to you personally but this is very idiotic on the part of adobe/macromedia (at the time).
I mean if flash 6/7 both support bitmap smoothing by default why wouldn't flash 8? and how rediculous is it that such a complicated work around is necessary just to create smooth rotations/scalings on bitmaps. :| I really like certain things about flash 8 but this is totally a drawback and having to write in that rediculous function to smooth bitmaps has to be a big performance hinderer.
Anyway... i saw that it still isn't fixed in player 9 for AS2/flash8 published files so I guess for now I am stuck either using drawing methods to rotate images or to use flash 7 movies for them.
HI There,
I found this very useful but wanted a more OO way of using it so I slapped into a class. Great resource and little more reusable this way. Hope it helps.
Save it as LoadBitmapSmoothed.as and call it thusly
LoadBitmapSmoothed.load(thumbs[i], thisTmb.img);
Cheers
import flash.display.*;
class LoadBitmapSmoothed {
private static var bmc:MovieClip;
private static var listener:Object;
private static var loader:MovieClipLoader;
public static function load(url:String, target:MovieClip) {
bmc = target.createEmptyMovieClip("bmc",target.getNextHighestDepth());
listener = new Object();
listener.tmc = target;
listener.onLoadInit = function(mc:MovieClip) {
mc._visible = false;
var bitmap:BitmapData = new BitmapData(mc._width, mc._height, true);
this.tmc.attachBitmap(bitmap, this.tmc.getNextHighestDepth(),"auto", true);
bitmap.draw(mc);
};
loader = new MovieClipLoader();
loader.addListener(listener);
loader.loadClip(url, bmc);
}
}
HI There,
I found this very useful but wanted a more OO way of using it so I slapped into a class. Great resource and little more reusable this way. Hope it helps.
Save it as LoadBitmapSmoothed.as and call it thusly
LoadBitmapSmoothed.load(thumbs[i], thisTmb.img);
Cheers
import flash.display.*;
class LoadBitmapSmoothed {
private static var bmc:MovieClip;
private static var listener:Object;
private static var loader:MovieClipLoader;
public static function load(url:String, target:MovieClip) {
bmc = target.createEmptyMovieClip("bmc",target.getNextHighestDepth());
listener = new Object();
listener.tmc = target;
listener.onLoadInit = function(mc:MovieClip) {
mc._visible = false;
var bitmap:BitmapData = new BitmapData(mc._width, mc._height, true);
this.tmc.attachBitmap(bitmap, this.tmc.getNextHighestDepth(),"auto", true);
bitmap.draw(mc);
};
loader = new MovieClipLoader();
loader.addListener(listener);
loader.loadClip(url, bmc);
}
}
Post a Comment
<< Home