Changing images dynamically from a Sprite? - actionscript-3

I have been looking for this answer for days now and no matter how much I look I can't find it for the life of me.
I understand that you can change a bitmap's image easily with something like this:
var image = new Bitmap (Assets.getBitmapData ("image.png"));
// (and later)
image.bitmapData = Assets.getBitmapData ("another-image.png");
but bitmap doesn't support mouse events. Let's say I want to change an image when someone clicks on it, thus I need it to be a sprite. Is there an easy way to just change the image of a sprite? Thanks in advance for any help!

Sure. You can do it one of two ways.
You create a custom class for this and add the bitmap as a public property
You add the bitmap to the Sprite and access it through there. See:
.
var bitmap:Bitmap = new Bitmap();
var container:Sprite = new Sprite();
this.addChild( this.container );
this.container.addChild( this.bitmap );
// to change the bitmap
this.bitmap.bitmapData = new BitmapData();
// or
var bmp:Bitmap = this.container.getChildAt( 0 ) as Bitmap;
bmp.bitmapData = new BitmapData();
The second option assumes the bitmap is the only object in the sprite. If you add more objects to the sprite, you may have to tweak the index accordingly.

Related

Greensock ImageLoader load image as bitmap not create movieclip

I have use greensock imageloader for sometimes (It's a great plug-in so easy to use and i love it), just wondering is there a way you can load bitmap which doesn't create a movieclip inside the container? I couldn't find this solution in the API
http://www.greensock.com/as/docs/tween/com/greensock/loading/ImageLoader.html
does anyone have any experience?
Cheers
Bill
According to the docs:
The ImageLoader's content refers to a ContentDisplay (Sprite) that is created immediately so that you can position/scale/rotate it or add ROLL_OVER/ROLL_OUT/CLICK listeners before (or while) the image loads. Use the ImageLoader's content property to get the ContentDisplay Sprite, or use the rawContent property to get the actual Bitmap. If a container is defined in the vars object, the ContentDisplay will immediately be added to that container).
So they are saying you don't have to supply a container in the vars object. If you just want to get the bitmap then it says you can use the rawContent property.
Try something like this:
//create an ImageLoader:
var loader:ImageLoader = new ImageLoader("your_image.jpg", {name:"image",
x:0, y:0, width:200, height:200, onComplete:onImageLoad});
//begin loading
loader.load();
//see if we have a bitmap
function onImageLoad(event:LoaderEvent):void {
trace(event.target.rawContent);
}
Although you say that you like this, loading a bitmap is trivial in AS3 without a library:
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
loader.load(new URLRequest("your_image.png"));
function onComplete (event:Event):void
{
// get your loaded bitmap
var bmp:Bitmap = Bitmap(LoaderInfo(event.target).content);
}

How can I load a Papervision/Flex application (SWF) as a material on a Papervision plane?

I am trying to build a portfolio application similar to the used by Whitevoid. I am using Flex 4 and Papervision3D 2. I have everything working except for one issue. When I try to load an external SWF as a material on one of the planes, I can see any native Flex or Flash components in their correct positions, but the papervision objects are not being rendered properly. It looks like the viewport is not being set in the nested swf. I have posted my code for loading the swf below.
private function loadMovie(path:String=""):void
{
loader = new Loader();
request = new URLRequest(path);
loader.contentLoaderInfo.addEventListener(Event.INIT, addMaterial);
loader.load(request);
}
private function addMaterial(e:Event):void
{
movie = new MovieClip();
movie.addChild(e.target.content);
var width:Number = 0;
var height:Number = 0;
width = loader.contentLoaderInfo.width;
height = loader.contentLoaderInfo.height;
//calculate the aspect ratio of the swf
var matAR:Number = width/height;
if (matAR > aspectRatio)
{
plane.scaleY = aspectRatio / matAR;
}
else if (matAR < aspectRatio)
{
plane.scaleX = matAR / aspectRatio;
}
var mat:MovieMaterial = new MovieMaterial(movie, false, true, false, new Rectangle(0, 0, width, height));
mat.interactive = true;
mat.smooth = true;
plane.material = mat;
}
Below I have posted two pictures. The first is a shot of the application running by itself. The second is the application as a MovieMaterial on a Plane. You can see how the button created as a spark object in the mxml stays in the correct position, but papervision sphere (which is rotating) is in the wrong location. Is there something I am missing here?
Man. I haven't seen that site in a while. Still one of the cooler PV projects...
What do you mean by:
I cannot properly see the scene rendered in Papervision
You say you can see the components in their appropriate positions, as in: you have a plane with what looks like the intended file loading up? But I'm guessing that you can't interact with it.
As far as I know, and I've spent a reasonable amount of time trying to make something similar work, the MovieMaterial (which I assume you're using) draws a Bitmap of whatever contents exist in your MovieClip, and if you set it to animated=true, then it will render out a series of bitmaps - equating animation. What it's not doing, is displaying an actual MovieClip (or SWF) on the plane. So you may see your components, but this is how:
MovieMaterial.as line 137
// ______________________________________________________________________ CREATE BITMAP
/**
*
* #param asset
* #return
*/
protected function createBitmapFromSprite( asset:DisplayObject ):BitmapData
{
// Set the new movie reference
movie = asset;
// initialize the bitmap since it's new
initBitmap( movie );
// Draw
drawBitmap();
// Call super.createBitmap to centralize the bitmap specific code.
// Here only MovieClip specific code, all bitmap code (maxUVs, AUTO_MIP_MAP, correctBitmap) in BitmapMaterial.
bitmap = super.createBitmap( bitmap );
return bitmap;
}
Note in the WhiteVoid you never actually interact with a movie until it "lands" = he's very likely swapping in a Movie on top of the bitmap textured plane.
The part that you are interacting with is probably another plane that holds the "button" that simply becomes visible on mouseover.
I think PV1.0 had access to real swfs as a material but this changed in 2.0. Sadly. Hopefully Molehill will.
cheers

convert masked movieclip into bitmap and save it on server

i have a
dsgnArea----> a movieclip
dsgnArea is masked by dsgnAreaMask, which inturn is a movieclip
dsgnArea.mask=dsgnAreaMask;
the width,height and position of dsgnAreaMask and dsgnArea are same.
i dynamically added multiple movieclips and labels to dsgnArea;
like..
dsgnArea.addChild(movieClip1);
dsgnArea.addChild(movieClip2);
dsgnArea.addChild(label1);
dsgnArea.addChild(label2); and so on...
these movieclips (movieClip1,movieClip2,......) and labels(label1,label2,....) positions can be altered in runtime..
but as i masked the dsgnArea with dsgnAreaMask, only a portion of the added movieClips and labels are visible...
So, my problem is to grab that visible portion in dsgnArea into a bitmap,like a screenshot of that particular dsgnArea, and save it in my server.
please help me out in this problem.
Say s is the DisplayObject object you want to capture and m is the mask applied on it.
var maskRect:Rectangle = m.getRect(s);
var matrix:Matrix = new Matrix(1, 0, 0, 1, -maskRect.x, -maskRect.y);
var w:Number = Math.min(s.width, maskRect.right) - maskRect.x;
var h:Number = Math.min(s.height, maskRect.bottom) - maskRect.y;
var bd:BitmapData = new BitmapData(w, h);
bd.draw(s, matrix);
Does that work?
The BitmapData draw method is what you are looking for. You can use it's clipRect param to define what you would like to draw (the masked parts).
Quasimondo did a handy little method to do this (take a snapshot of the whole displayObject), it's available here: http://www.quasimondo.com/archives/000670.php
I don't know if it works with masked content though.
if it doesn't, the trick would be to translate the whole content by the size of the mask
var bounds:Rectangle = dsgnAreaMask.getBounds( dsgnAreaMask );
instead of using the content of the clip
var bounds:Rectangle = clip.getBounds( clip );
as far as saving file to server is concerned, the question was asked (answered?) here AS3 Save Media File to server

drawRect in actionscript3

var blockGraphics : Graphics = null;
blockGraphics.clear();
blockGraphics.beginFill(255);
blockGraphics.drawRect(10,10,10,10);
I am trying to simply draw a rectangle but nothing appears on the screen. What am i missing?
Afaik you can't instantiate graphics class..
you need to make a MovieClip or Sprite and work with that.. you can't draw directly to stage.
var mc:MovieClip = new MovieClip();
mc.graphics.beginFill(0xFF0000);
mc.graphics.drawRect(10,10,10,10);
mc.graphics.endFill();
also don't forget to add it to stage
addChild(mc);
var mySprite:Sprite = new Sprite();
mySprite.graphics.beginFill(0x000000);
mySprite.graphics.drawRect(10, 10, 10, 10);
mySprite.graphics.endFill();
addChild(mySprite);
I don't really know a whole lot about the graphics class (I've used it a few times) but I don't believe you can call ANYTHING on a null object.
blockGraphics = null;
blockGraphics.clear();
is the same as calling:
null.clear();
Which is going to give you an error. Typically you'll want to take a movieclip or other such object and get it's graphics instance:
blockGraphics = mc.graphics;
blockGraphics.clear();
blockGraphics.beginFill(0xFF0000);
blockGraphics.drawRect(10,10,10,10);
would draw a red rectangle inside the "mc" movieclip.

How to convert bytearray to image or image to bytearray ?

How to assign bytearray value to panel background image. If anybody have idea or experiance plz help me to overcome the problem. BRIEF EXP:
I have panel control and want to load image getting from webservice as a backgroundimage. So i used setstyle() but its not accepting that image. so how to add that image into my panel background image.Plz tel me your ideas here.
In Flex 3 or higher, you just need to do:
yourImage.source = yourByteArray;
regards!
uhm, well i presume, since it is an image, you have it in a BitmapData, let's say "myBmp" ...
then use the following to extract all the data from BitmapData:
var bytes:ByteArray = myBmp.getPixels(myBmp.rect);
and the following to write:
myBmp.setPixels(myBmp.rect, bytes);
note that only the raw 32 bit pixel data is stored in the ByteArray, without compression, nor the dimensions of the original image.
for compression, you should refer to the corelib, as ozke said ...
For AS3 you can use adobe corelib. Check this tutorial...
http://ntt.cc/2009/01/09/as3corelib-tutorialhow-to-use-jpegencoder-and-pngencoder-class-in-flex.html
I used a flash.display.Loader() to load an image in an array. It has a Complete event that is fired after the image has been loaded. I then draw the image on to a Bitmap which I set to the data of a Image that could be placed in a panel. Hope you can make since of this good luck.
public static function updateImage(img:Image, matrix:Matrix,
pageDTO:PageDTO, bitmapData:BitmapData):void {
var loader:flash.display.Loader = new flash.display.Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, function (e:Event) : void {
bitmapData.draw(loader.content, matrix);
pageViewer.data = new Bitmap(bitmapData);
});
loader.loadBytes(pageDTO.thumbnail);
}
<mx:Panel>
<mx:Image id="pageViewer"/>
</mx:Panel>
Using adobe's JPGEncoder (com.adobe.images.JPGEncoder) class and ByteArray is pretty much all you need. Converting image to byte array (assuming CAPS are variables you'd need to fill in):
// -- first draw (copy) the image's bitmap data
var image:DisplayObject = YOUR_IMAGE;
var src:BitmapData = new BitmapData(image.width, image.height);
src.draw(image);
// -- encode the jpg
var quality:int = 75;
var jpg:JPGEncoder = new JPGEncoder(quality);
var byteArray:ByteArray = jpg.encode(src);
I had the same problem. As a workaround I created sub Canvas nested inside a main Canvas and added an Image to the main Canvas behind the sub Canvas. Anything drawn on the sub Canvas will appear on top of the Image.
Just load it into a Loader instance using the loadBytes function.
var ldr:Loader = new Loader();
ldr.loadBytes(myByteArray);
addChild(ldr);