Modify dynamic created objects that are saved in an array - actionscript-3

i have multiple images that are created dynamically, and i want in some cases to change the image. i can save them in an array, but how can i change the image (load another image) by getting it from the array.
let's say that i have an array:
var ImagesArray:Array = [];
and i push to it loader objects, and want to change (load new) image of ImagesArray[0] or ImagesArray[1]... like:
var loaderNew:Loader = new Loader();
loaderNew = ImagesArray[i];
loaderNew.load(new URLRequest("../lib/NewImg.png"));
Thanks,

You dont need to create new loader if you only want to change its image, here's an example of function to update image url:
private function changeImageByIndex(i:int, url:String):void
{
var loader:Loader = ImagesArray[i] as Loader;
if (!loader)
{
loader = new Loader();
addChild(loader);
ImagesArray[i] = loader;
}
loader.load(new URLRequest(url));
}
If you have bitmap, use loadBytes() method instead load(), here's example:
var bitmap:Bitmap = new Bitmap(new BitmapData(100, 100, true, 0xff0000));
var encoder:JPEGEncoder = new JPEGEncoder();
loader.loadBytes(encoder.encode(bitmap.bitmapData));

Related

Loading an Image with AIR and Displaying It On Stage

I am having trouble loading an image and displaying it on stage using the File API in as3. I am able to successfully load it in but when I put it on stage the image is just noise. I am assuming because I need to decode the PNG/JPG into Bitmap data somehow and I am doing it wrong? Here is my code:
public function browseForIcon(){
var file:File = new File();
file.addEventListener(Event.SELECT, onFileSelected);
file.browseForOpen("Select a an image");
}
private function onFileSelected(event:Event):void {
var stream:FileStream = new FileStream();
stream.open(event.target as File, FileMode.READ);
var bytes:ByteArray = new ByteArray();
stream.readBytes(bytes);
var img = new BitmapData(160,160);
img.setPixels(new Rectangle(0,0,160,160),bytes);
this.addChild(new Bitmap(img));
}
}
THANKS!
One option is to use Loader.loadBytes(). If you're using Flex, you could also use an Image with source set to the File.

photo load order mess up as3

I have created a container(or a movieclip) that will add the photos in order and display on the stage. however, because of the different file size, it will add the smallest file size photo first. how i can solve this issue. please see the sample code below
// image0.jpg -> 3k
// image1.jpg -> 2k
// image2.jpg -> 1k
// image3.jpg -> 2k
// image5.jpg -> 1k
var photoPath:Array = new Array();
var photoContainer:MovieClip = new MovieClip();
photoPath.push('image0.jpg');
photoPath.push('image1.jpg');
photoPath.push('image2.jpg');
photoPath.push('image3.jpg');
photoPath.push('image4.jpg');
for(var i = 0; i < photoPath.length; i++)
{
var loader:Loader = new Loader();
loader.load(URLRequest(photoPath[i]));
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, photoLoaded);
}
function photoLoaded(e:Event):void
{
photoContainer.addChild(e.target.content);
}
//output will looks like (image2,image5,image1,image3,image0) instead of 0,1,2,3,4,5
There are quite a few ways to handle this issue, probably the easiest way to retrofit your current code is to add the Loader to the displaylist as it is instantiated. This will guarantee that they're placed in the photoContainer in the correct order. If you absolutely need the bitmap itself to be in the displaylist as opposed to the loader itself, you can address this in your photoLoaded method:
import flash.display.Loader;
var photoPath:Array = new Array();
var photoContainer:MovieClip = new MovieClip();
photoPath.push('image0.jpg');
photoPath.push('image1.jpg');
photoPath.push('image2.jpg');
photoPath.push('image3.jpg');
photoPath.push('image4.jpg');
for(var i = 0; i < photoPath.length; i++)
{
var loader:Loader = new Loader();
photoContainer.addChild(loader); //add the loader to photoContainer
loader.load(new URLRequest(photoPath[i]));
//you only actually have to listen for complete below if you want to replace the loader with its contents
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, photoLoaded);
}
function photoLoaded(e:Event):void
{
var loader:Loader = e.target.loader;
var index:int = photoContainer.getChildIndex(loader);
// this will add the contents of the loader in the same order the loader was originally added
photoContainer.addChildAt(loader.content, index);
photoContainer.removeChild(loader);
}
Simply loads and adds the photos to the container in the order given in the array:
var photoPath:Array = new Array();
var photoContainer:MovieClip = new MovieClip();
var i:int = 0;
photoPath.push('image0.jpg');
photoPath.push('image1.jpg');
photoPath.push('image2.jpg');
photoPath.push('image3.jpg');
photoPath.push('image4.jpg');
loadPhoto(i);
function loadPhoto(i:int):void
{
var loader:Loader = new Loader();
loader.load(new URLRequest(photoPath[i]));
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, photoLoaded);
}
function photoLoaded(e:Event):void
{
photoContainer.addChild(e.target.content);
trace(e.target.url); // Verify
if(i<photoPath.length-1) loadPhoto(++i);
}
Output:
image0.jpg
image1.jpg
image2.jpg
image3.jpg
image4.jpg

Actionscript 3: Converting bytearray to PNG and display on the scene

I'm getting getting a PNG image stored in SQL through a WCF get call. The image is encoded as a base64 string and delivered to my AS3 code. I need to extract the image from the data and show it on the scene.
Among other things, I have also tried this...
var imgArray:ByteArray = Base64.decodeToByteArray(responseXML.ImageObject);
var myRect:Rectangle = new Rectangle(100,100,200,200);
var bmd:BitmapData = new BitmapData(200,200,true,0xAAAAAAAA);
bmd.setPixels(myRect, imgArray);
var image:Bitmap = new Bitmap(bmd,"auto",true);
this.addChild(image);
but to no avail.
HELP!
why don't you use a loader and loadbytes? It's native.
var loader:Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, handleLoad)
loader.loadbytes(byteArray);
private function handleLoad(e:Event):void {
var loader:Loader = e.currentTarget as Loader;
// removelistener,etc
trace(loader.content as Bitmap);
}
The problem with your code is that PNG is compressed, bitmap is uncompressed.
I used DanielH's input and got the image to load on my stage. Here is what I did in the event handler function...
function ImageLoaded(e:Event):void
{
var bmd:BitmapData = new BitmapData(imageLoader.ImageLoader.width,imageLoader.ImageLoader.height,true, 0xFFFFFF);
bmd.draw(imageLoader.ImageLoader);
var image:Bitmap = new Bitmap(bmd,"auto",true);
image.width=40;
image.height=40;
if(!CheckAndStoreImageIDKey(imageLoader.ImageID))
{
Images[imageLoader.ImageID] = image;
}
}
Try PNGDecoder (http://www.ionsden.com/content/pngdecoder)
import ion.utils.png.PNGDecoder;
var bmd:BitmapData = PNGDecoder.decodeImage(imgArray);

as3 moving image from one mc to another

With the code below I created some imgMcA and some imgMcB then I loaded images into imgMcA ones. ImgMcBs have no image at that moment. So if one of imgMcA is clicked the image should be transferred to one of the empty imgMcBs (may be randomly) and if imgmcB is clicked later the image should move back to its imgMcA back. I could not find out how I can accomplish this.
Thanks in advance
function imageList(mcname, img, index){
var imgMcA:MovieClip=new MovieClip();
imgMcA.graphics.beginFill(0x000000);
imgMcA.graphics.drawRect(0,0,imgWidth,imgHeight);
imgMcA.graphics.endFill();
imgMcA.name=lemma;
imgMcA.addEventListener(MouseEvent.CLICK, moveImage);
var imgMcB:MovieClip=new MovieClip();
imgMcB.graphics.beginFill(0x000000);
imgMcB.graphics.drawRect(0,0,imgWidth,imgHeight);
imgMcB.graphics.endFill();
imgMcB.name=index;
addChild(imgMcB);
var imgLoader:Loader = new Loader();
imgLoader.load(new URLRequest(img));
imgLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, changeProperties);
imgLoader.mouseEnabled=false;
imgMcA.addChild(imgLoader);
}
function moveImage(evnt:MouseEvent){
}
You could linked mcA & mcB by adding them to the same parent.
function createBlock():void
{
var imgLoader:Loader = new Loader();
//add the loading code here...
var mcA:Sprite = new Sprite();
var mcB:Sprite = new Sprite();
// add Click event listeners for both Mcs here...
var parent:Sprite = new Sprite();
//add Children
parent.addChild(mcA);
parent.addChild(mcB);
addChild(parent);
}
function mouseClickHandler(event:MouseEvent)
{
var dispatcher:Sprite = event.currentTarget as Sprite;
//if you added a Loader to it
if( dispatcher.numChildren > 0)
{
//retrieve the image
var img:Loader = dispatcher.getChildAt(0);
//identify the parent
var parent:Sprite = dispatcher.parent;
var index:int = parent.getChildIndex(dispatcher);
//identify the receiving MC
//of course this only works with two children!!!
if(index > 0)
var receiver:Sprite = parent.getChildAt(0) as Sprite;
else
receiver = parent.getChildAt(1) as Sprite;
//add the image to the other MC
receiver.addChild(img);
}
}
The rest is not too complicated to achieve. You will need to use a Boolean and add a TextField. If the TextField contains text, set the Boolean to true.
It may be worth looking at Classes or you could use an Object as a container for the MovieClips, the TextField and the Boolean, although a Class will give you more flexibility...
With a Class, you wouldn't have to iterate in order to find what does what. Your Click listener would look something like this:
private function mouseClickHandler(event:MouseEvent)
{
receiver.addChild( image );
if( hasText)
imageReturn();
}

Finding (loaded) image size in AS3 (Action Script 3.0)

Im currently using the following function to load an image, however i could not figure out a way to find the width of the loaded image, which i intend to use before placing the next image using the same function.
Note that q is a a variable (a number) which is used to load differant images.
=X i need help obtainning the loaded image width...
function LoadImage(q)
{
var imageLoader:Loader = new Loader();
var image:URLRequest = new URLRequest("GalleryImages/Album1/"+q+".jpg");
imageLoader.load(image);
addChild (imageLoader);
imageLoader.x = 0 + CurrentXLength;
imageLoader.y = 0;
imageLoader.name = "image"+q;
trace(imageLoader.x)
}
You can't know the width of the bitmap until it's actually loaded:
function LoadImage(q)
{
var imageLoader:Loader = new Loader();
var image:URLRequest = new URLRequest("GalleryImages/Album1/"+q+".jpg");
imageLoader.contentLoader.addEventListener(Event.COMPLETE, ImageLoaded);
imageLoader.load(image);
addChild (imageLoader);
...
private function ImageLoaded(e:Event):void
{
var imageLoader:Loader = Loader(e.target.loader);
var bm:Bitmap = Bitmap(imageLoader.content);
var CurrentXLength = bm.width;
....
Alternativly this link might be helpful? Haven't tried it myself ...
I just asked for de width property of loader object:
var loader:Loader;
function loadImage(dir:String):void {
loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, placeImage);
var urlReq:URLRequest = new URLRequest(direccion);
loader.load(urlReq);
}
function placeImage(o:Event):void {
loader.x = (1360 - loader.width)/2;
loader.y = (768 - loader.height)/2;
addChild(loader);
}
Where 1360 and 768 are the canvas dimensions...
To access the width you must do it within the function assigned to handle Event.COMPLETE.
"You will want an array containing the items you wish to load. You should probably load this data in with XML so it is dynamic and scalable. Once the xml data is loaded it should be assigned to an array in whatever fashion you like. The reason that we must use an array in this situation, rather then just using the XML object, which is essentially an array, is because you need the know an objects width so that you can base the next objects X position off of the last objects X position plus its WIDTH.
With XML it is common to use a for loop and just iterate through "x" amount of times. We do not want this, in this case. To obtain the "WIDTH" property of the loaded asset, it must be accessed from within the function assigned to fire when the loader fires Event.COMPLETE. Once the image has completed it will remove the item from the array, set a variable as to the lastX and lastWidth, and then get the next item in the array and start all over. Eventually the array is empty and the process is complete.
-Note: I will skip loading the XML and just inject the data into the array myself.
package
{
import flash.display.Sprite;
import flash.display.Loader;
import flash.net.URLRequest;
public class DocumentClass extends Sprite
{
private var _array:Array;
private var _lastX:Number;
private var _lastWidth:Number;
public function DocumentClass():void
{
_array = new Array();
//Add Items to an array however you wish. I did it
//this way to make it easier to read on this site.
_array.push({name: "image1", path: "path/to/image1"});
_array.push({name: "image2", path: "path/to/image2"});
_array.push({name: "image3", path: "path/to/image3"});
loadImage();
}
private function loadImage():void
{
if(_array.length > 0)
{
var loader:Loader = new Loader();
addChild(loader);
var request:URLRequest = new URLRequest(_array[0].path); //Loads first item in the array each time.
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageLoaded);
loader.x = _lastX + _lastWidth;
laoder.load(request);
_lastX = loader.x; //We set after so we are ready for the next.
_array.shift(); //Remove the first item from the array.
}
}
function onImageLoaded(e:Event):void
{
_lastWidth = e.target.width;
loadImage(); //Attempt to load another image if the array isn't empty.
}
}
}
I hope this helps, the code isn't tested, but the concept seems valid.
Yeah I used scott's answer but it's worth noting that 'imageLoader.contentLoader' should be 'imageLoader.contentLoaderInfo' in the LoadImage() function. Solved the width prob for me-- thanks mang