I am building a portfolio site which dynamically loads large hi-res images when the user clicks on a thumnail. However I'm having problems maintaining the original image's quality when resizing it to fit the current browser.
Currently I'm just adjusting the width & height properties of the image to width to the stage proportionally which is working fine getting it to fit, however I cannot figure out how to maintain image quality? Do I need to load it as a bitmap and redraw/smooth or something similar?
This is the appropriate code that I am currently using:
var req:URLRequest = new URLRequest("images/101.jpg");
var loader:Loader = new Loader();
var widthRatio:Number;
var heightRatio:Number;
function imageLoaded(e:Event):void
{
//add image to stage
addChild(loader);
// resize proportionally
if (loader.width > stage.stageWidth){
widthRatio=loader.width/stage.stageWidth;
trace(widthRatio)
trace(loader.width);
}
if (loader.height > stage.stageHeight){
heightRatio=loader.height/stage.stageHeight;
trace(heightRatio)
trace(loader.height)
}
if (widthRatio > heightRatio){
loader.width = stage.stageWidth;
loader.height = loader.height/widthRatio;
} else {
loader.height = stage.stageHeight;
loader.width = loader.width/heightRatio;
}
//centre on stage
loader.x=stage.stageWidth/2 - loader.width/2;
loader.y=stage.stageHeight/2 - loader.height/2;
}
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoaded);
loader.load(req);
Have a look at Bitmap smoothing.
Your Loader will have a content property which will be a Bitmap. Set it's smoothing to true.
function imageLoaded(e:Event):void
{
//add image to stage
addChild(loader);
Bitmap(loader.content).smoothing = true;
// ...
It makes the image a bit blurry but it is a significant improvement in most cases.
Related
I have implemented Sharing music features on WeChat.
Sharing on iOS works good. But when sharing on Android, the edge of the background are white and pixelated. I'm thinking is it caused by the low pixel of images? I’m looking for a solutions to get rid of those pixelated edges.
Code for Android:
WXMusicObject musicObj = new WXMusicObject();
musicObj.MusicUrl = link; // URL to open when the song is clicked
musicObj.MusicDataUrl = userAudioURL; // URL of actual music data
WXMediaMessage msg = new WXMediaMessage();
msg.mediaObject = musicObj;
int imgId = (int)typeof(Resource.Drawable).GetField("icon").GetValue(null);
Bitmap thumbBitmap = BitmapFactory.DecodeResource(Forms.Context.Resources, imgId);
Bitmap thBitmap = Bitmap.CreateScaledBitmap(thumbBitmap, 150, 150, true);
thumbBitmap.Recycle();
using (System.IO.MemoryStream outStream = new System.IO.MemoryStream())
{
thBitmap.Compress(Bitmap.CompressFormat.Png, 150, outStream);
msg.ThumbData = outStream.ToArray();
}
SendMessageToWX.Req req = new SendMessageToWX.Req();
req.Transaction = buildTransaction("music");
req.Message = msg;
req.Scene = SendMessageToWX.Req.WXSceneSession; //chat
mWxApi.SendReq(req);
Finally found out the root cause. For sharing music on WeChat, background will set to thumbnail images.
I solved this with using a higher pixel images, so background image wouldn't stretched and can displayed without pixelation.
I am getting an image dynamically from a webservice. Afterwards I am supposed to use it as background for the upper half of the screen. My problem is that I only get one size of the image (which should be approximately right for many smartphones phones) but when I resize it to make it fill half of the screen it gets pixelated.
I have tried putting it as background of a container (adding padding to the expected size) and using BACKGROUND_IMAGE_SCALED_FILL and/or using Image methods scaledHeight/scaledWidth, fill and scaled.
It doesn't matter if I scale it to a bigger or smaller size it still deteriorates noticeably.
Is this to be expected? Is there another way to scale images?
public class CopyOfVistaPantallaPrincipal extends VistaDisparaEventos {
private Container canvasPantallaPrincipal;
public CopyOfVistaPantallaPrincipal() {
canvasPantallaPrincipal = new Container();
canvasPantallaPrincipal.setName("canvasPantallaPrincipal");
super.canvas = this.canvasPantallaPrincipal;
initPantallaPrincipal();
}
private void initPantallaPrincipal() {
canvasPantallaPrincipal.setLayout(new LayeredLayout());
canvasPantallaPrincipal.getUnselectedStyle().setBgTransparency(0);
ModeloNovedades modelo = new ModeloNovedades();
Image imgPrincipal = createImagenPrincipal(modelo);
canvasPantallaPrincipal.setName("canvas pantalla principal");
Container otro = new Container(new BorderLayout());
if (imgPrincipal != null) {
img.getUnselectedStyle().setBorder(null);
img.getUnselectedStyle().setPadding(0, 0, 0, 0);
img.getUnselectedStyle().setMargin(0, 0, 0, 0);
canvasPantallaPrincipal.addComponent(img);
}
canvasPantallaPrincipal.addComponent(otro);
}
private Container createImagenPrincipal(ModeloNovedades modelo) {
return loadTopImage(modelo, modelo.getDestacado());
}
private Container loadTopImage(ModeloNovedades modelo, Hashtable destacado) {
int width = Display.getInstance().getDisplayWidth();
int imgHeight = (int) ((Display.getInstance().getDisplayHeight() / 2) * 0.95) ;
//Default image
Image foregroundImage = FormFactory.loadImage("/imagenPrincipaLogoOld.png");
if (! modelo.getDestacado().isEmpty()){
String destacadaURL = "" + destacado.get("imagen");
if (! destacadaURL.equals("")){
//After updating it loads the downloaded image here
byte[] data = (byte[]) DataCenter.getInstance().get(destacadaURL, false);
foregroundImage = FormFactory.loadImage(data, 100);
}
}
imageContainer.getAllStyles().setPadding(imgHeight/2, imgHeight/2, width/2, width()/2);
imageContainer.getAllStyles().setBgImage(foregroundImage);
imageContainer.getAllStyles().setBackgroundType(Style.BACKGROUND_IMAGE_SCALED_FILL);
return imageContainer;
}
}
If I'm not returning the image but a container having it as background I would add it to a Container like this:
imageContainer.getAllStyles().setPadding(imgHeight/2, imgHeight/2, width/2, width/2);
imageContainer.getAllStyles().setBgImage(foregroundImage);
imageContainer.getAllStyles().setBackgroundType(Style.BACKGROUND_IMAGE_SCALED); //only if it was scaled
Original image (please ignore the dark bar over it, it was added recently and I didn't save the previous version, as I said it comes dynamically):
http://i68.tinypic.com/16lmeqr.jpg
Scaled:
http://i68.tinypic.com/w7zafm.jpg
Cropped:
http://i65.tinypic.com/2nkp79l.png
Image as of the last update:
http://i68.tinypic.com/2ik7eiq.png
Remove all of your code that manipulates the image, needs scaling, scale etc... That is all redundant. Every pass you do on manipulating an image deteriorates it a little bit...
You need just one line change and you need to do it always so the image will always "fit" without cropping or any other changes:
imageContainer.getAllStyles().setBackgroundType(Style.BACKGROUND_IMAGE_SCALE_TO_FILL);
Notice that you can just use ScaleImageLabel instead of image container which does roughly the same thing.
this is a post I have made on the adobe forum...
I'm newish to flash and i'm doing a presentation as part of a University assignment.
My problem is basically this. As part of my presentation I have a photo gallery which uses thumbnail images as buttons and then a UI loader to load a pop up version of the larger image from my webserver - as per https://www.youtube.com/watch?v=Peo_nT9HHa0
The image was created on photoshop. It is a .jpg and has text within the image that describes underneath it what the image is all about. The text within photoshop is set to anti-aliasing 'smooth' and when I test the movie within flash, the text underneath the image looks fine - just as it does in photoshop.
However, when I publish and upload the .swf file to my webserver and view the image through a browser, the text looks awful - all jaggy and broken if that makes sense.
Any ideas why?
I was given a reply of...
If you are loading the images dynamically then you will have to set the smoothing property true after the file(s) has been loaded. So if you don't currently have a listener for the images finishing loading, you will need one, and an event handler function to assign the smoothing property to true for each of them.
Can anyone help with creating the actionscript for this listener and event handler function?
I basically have a gallery movie clip with buttons that act as clickable thumbnails. The actionscript for that is...
btnImage1.addEventListener(MouseEvent.CLICK, loadimage1);
function loadimage1 (event:MouseEvent):void{
imagetxt.text = "a";
togglewindow.gotoAndPlay(2)
}
and then a UI loader that displays the larger image when a thumbnail is clicked
if (MovieClip(this.parent).imagetxt.text == "a"){
var imgurl:String ="IMAGE URL";
var myrequest:URLRequest = new URLRequest(imgurl);
myloader.load(myrequest);
}
As indicated, you should always turn smoothing on if the image is going to be scaled at all. It uses a different scaling algorithm that blurs pixels rather than deletes them. Take note that it is substantially slower to smooth, but on modern machines you shouldn't notice the difference unless you are doing it to thousands of images all at once.
After instantiation, add a Event.COMPLETE handler to Loader.contentLoaderInfo.
var myLoader = new Loader();
myLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, loaderCompleteHandler);
Then in the handler, you can access the Bitmap and turn smoothing on.
function loaderCompleteHandler(e:Event):void {
var image:Bitmap = myLoader.content as Bitmap; //Loader.content is typed as a DisplayObject, so we need to cast it as a Bitmap
image.smoothing = true;
}
And that should solve the issue. You may need to add the image object to the stage rather than the myLoader object. I don't think you'll have to, but I can't remember.
Just add event an event listener to your loader. Like this:
load.addEventListener(Event.COMPLETE,doneLoad);
then in the doneLoad function get the event.data and cast it to Bitmap and set the bitmap smoothing to true:
var myBitmap:Bitmap= e.target.data as Bitmap;
myBitmap.smoothing=true;
//add bitmap to parent ....
I wrote you universal method for loading images, you should pass 3 arguments to the method: holder for big images, image path, and rectangle to restrict image bounds and resize them. This method should be sufficient for your task.
private function loadImage(holder:DisplayObjectContainer, path:String, bounds:Rectangle):void {
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, function (e:Event):void {
var bitmap:Bitmap = loader.content as Bitmap;
if (bitmap != null) {
bitmap.smoothing = true;
//Resize bitmap to fit bounds
var availableRatio:Number = bounds.width / bounds.height;
var componentRatio:Number = bitmap.width / bitmap.height;
if (componentRatio > availableRatio) {
bitmap.width = bounds.width;
bitmap.height = bounds.width / componentRatio;
} else {
bitmap.width = bounds.height * componentRatio;
bitmap.height = bounds.height;
}
//Clear previous
var i:uint, len: uint = holder.numChildren, old: Bitmap;
for(i; i < len; ++i){
old = holder.removeChildAt(0) as Bitmap;
old.bitmapData.dispose();
}
//Here you can add some appear animation
bitmap.x = bounds.x + ((bounds.width - bitmap.width) >> 1);
bitmap.y = bounds.y + ((bounds.height - bitmap.height) >> 1);
holder.addChild(bitmap);
}
});
loader.load(new URLRequest(path));
}
Usage:
loadImage(myContainer, "Path-to-Image", new Rectangle(20, 20, 400, 200));
I'm using Greensock's LoaderMax to parse an XML doc and load thumbnails and large images onto the stage - the large images are hidden off screen initially.
What I'd like to do is click on a thumbnail and have the large image tween into place, I have assigned the same name to the relevant thumbnail and image, ie 0 in thumbs corresponds to the 0 image
Thumbnails have been added to a movieclip named mc2, images are in a mc called bigDocWrap
Here's my attempt:
function callFull(event:MouseEvent):void
{
var clicked = [event.target.name];
if (isUp == true) {
// Do some stuff
fadeOut.addEventListener(TweenEvent.MOTION_FINISH, end);
function end(event:TweenEvent) {
// Some more stuff
// Animate large image in
mcDocIn = new Tween (clicked, "y", Strong.easeOut, clicked.y, -650, 1, true);
}
}
}
This didn't work - undefined reference error
mcDocIn = new Tween (bigDocWrap.clicked, "y", Strong.easeOut, bigDocWrap.clicked.y, -650, 1, true);
You are passing Name of object and not object to new Tween(). Use event.currentTarget or event.target, depends on your need.
I have updated your code like so:
function callFull(event:MouseEvent):void
{
if (isUp == true) {
// Do some stuff
fadeOut.addEventListener(TweenEvent.MOTION_FINISH, end);
function end(event:TweenEvent) {
// Some more stuff
// Animate large image in
mcDocIn = new Tween (event.currentTarget, "y", Strong.easeOut, clicked.y, -650, 1, true);
}
}
}
I made an application that the user could load an image, then they could edit it. The problem is, when I load an image for the first time, it loaded with it's original pixel size. But when i load another image, the pixel size differ from the original one.
Here is the function code when image loaded to stage :
function onFileLoadComplete(event:Event):void
{
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onDataLoadComplete);
loader.loadBytes(loadFileRef.data);
loadFileRef = null;
}
function onDataLoadComplete(event:Event):void
{
var bitmapData:BitmapData = Bitmap(event.target.content).bitmapData;
var matrix:Matrix = new Matrix();
matrix.translate(-imageView_mc.x, -imageView_mc.y);
matrix.scale(scaleX, scaleY);
matrix.translate(imageView_mc.x, imageView_mc.y);
imageView_mc.graphics.clear();
imageView_mc.graphics.beginBitmapFill(bitmapData, matrix, false, true);
imageView_mc.graphics.drawRect(0, 0, bitmapData.width, bitmapData.height);
imageView_mc.graphics.endFill();
trace ("Image width: " ,imageView_mc.width, ", Image height: " ,imageView_mc.height);
imageView_mc.width = stage.stageWidth;
imageView_mc.height = stage.stageHeight;
(imageView_mc.scaleX < imageView_mc.scaleY) ? imageView_mc.scaleY = imageView_mc.scaleX : imageView_mc.scaleX = imageView_mc.scaleY;
(imageView_mc.scaleX > imageView_mc.scaleY) ? imageView_mc.scaleY = imageView_mc.scaleX : imageView_mc.scaleX = imageView_mc.scaleY;
imageView_mc.x = 0.5*(stage.stageWidth-imageView_mc.width);
imageView_mc.y = 0.5*(stage.stageHeight-imageView_mc.height);
}
so, is there something wrong with this code? this code is for loading image to stage, then scale it proportionally to stage size.
Any feedback would be really appreciated.
Reset your scale when loaded new image before applying matrix transform.
scaleX = scaleY = 1;