Search Box

Google
 

Monday, February 12, 2007

BitmapData II.......................

Continuing from the previous post explaining about BitmapData class and using it to cache images, i am here again to share some more information about it. Okay till now we saw how we can use BitmapData to cache images but its not the only thing we can do with it but lots and lots. Remember the days of those and before flash player 7 where when a drawing application is developed the developer takes the pain of generating the color palette himself either by actionscripting or designing the color boxes in the "timeline" itself.

And also the end user is at the mercy of selecting only the colors whatever the program(developer) provides. If i say i dont like that red color then i assure to see that red color does not exist at all in my program and the user suffering from red syndrome. Always giving the choice of colors in flash that satisfies the user was never satisfying . Now no more is the case like that with the flash player 8.

Wondering how BitmapData is going to help us in this ????? Just wait and see. This BitmapData has a method called "getPixel" with the "x" and "y" Numbers as the arguments which specifies the location of the area whose color has to be picked. Yes whose COLOR (RGB) has to be picked. This method returns the color of the pixel specified at the x and y pixel. Also there is another method called getPixel32 which returns the ARGB values meaning RGB with Alpha.

Cool isn't it ?? So gone are the days of providing hard coded color palettes where now the user can even pick the color that lies by the side of his circle, oval or square shape that he has drawn in his drawing program.


Regards,

Ashok Srinivasan.

Sunday, February 11, 2007

BitmapData.........

Hai all,

i am back after a very long long time. But happy i am back atleast now. Today we shall discuss about caching image using BitmapData class. Actually "bitmapdata" is a new class that has been introduced for flash player 8. What this class can do is enormous, but we are here to discuss today what it can do for caching dynamically loaded images.

I was always wondering how can i stop those reloading of images again and again, until i was introduced to the BitmapData class by a colleague of mine who recently discovered this. After playing around with the class for sometime an idea struck to me for solving the problem of reloading the loaded images with BitmapData class being the key. This solution ultimately gave birth to a class "ImageCache" which looks after the images loaded using it and ultimately returns a BitmapData which can be attached to the image holding movieClip using attachBitmap() method.

The content of the class goes like this :

import flash.display.BitmapData

class ImageCache
{
/**
@ varible __paths
@ description: The array that holds the path of the images loaded.
*/
private var __paths:Array;

/**
@ varible loader
@ description: MovieClip that holds the images to be loaded and cached.This is a temporary movieClip.
*/
private var loader:MovieClip;


/**
@ method ImageCache
@ description: Constructor Function.
*/
public function ImageCache()
{
__paths = new Array();
}

/**
@ method registerTempLoader
@ arguments : None;
@ access : Public
@ returns : Nothing.
@ description: Method that registers a valid MovieClip to be used for caching Images.
*/
public function registerTempLoader(mc:MovieClip):Void
{
loader = mc;
}


/**
@ method : cacheImage
@ arguments : String path , float Width, float Height;
@ access : Public
@ returns : BitmapData.
@ description : When a path is passed into the argument along with the width and height
loads the image and returns the cached image as a BitmapData.
*/
public function cacheImage(path:String,w:Number,h:Number):BitmapData
{
var index:Number = isCached(path);
if( index < 0)
{
var obj:Object = new Object();
var mc:MovieClip = loader.createEmptyMovieClip('loader'+__paths.length,__paths.length);
obj.path = path;
obj.bdata = new BitmapData((w==undefined)?100:w,(h==undefined)?100:h,false,0xcc33ff);
mc.loader = new MovieClipLoader();
mc.loader.addListener(this);
mc.loader.loadClip(path,mc.createEmptyMovieClip('loader',0));
mc.index = __paths.length;
__paths.push(obj);
return obj.bdata;
}
else
{
return __paths[index].bdata;
}

}


/**
@ method : isCached
@ arguments : String path;
@ returns : Number.
@ access : Private
@ description : When a path is passed into the argument checks from the
__paths array if the path is already loaded returns the
index of the path in the array else returns -1.
*/
private function isCached(path:String):Number
{
for(var i:Number=0;i<__paths.length;i++)
{
if(__paths[i].path == path)
{
return i;
}
}
return -1;
}


/**
@ method : onLoadInit
@ arguments : target MovieClip;
@ returns : Nothing.
@ access : Private
@ description : When an image loads successfully its parent get drawn using BitmapData.
*/
private function onLoadInit(target:MovieClip):Void
{
__paths[target._parent.index].bdata.draw(target._parent);
}
}



Okay, the class is written but how do we use it ??? Nice Question !

i had developed a image gallery using this class believe me. i will paste the actionscript that exists in the timeline of the stage as given below. But before that have two things ready in the library. one is a macromedia scrollpane and the next is create two empty movieclips with one having a linkage name "thumbHolder" and the other empty movieclip does not require any linkage ids.

Now drag the ScrollPane to the stage and name it "$spane" with the content path in the parameters field as "thumbHolder". Now drag the empty movieClip without any linkage id to the stage and name it "$main".

Then paste the below actions on the first frame of the Stage.


//Instance of the ImageCache Class.
var iCache:ImageCache = new ImageCache();

//Temporary images holder.
var imageHolder:MovieClip = this.createEmptyMovieClip('tempImageHolder',0);


//The thumbnal images holder
var galleryHolder:MovieClip = $spane.spContentHolder.createEmptyMovieClip('thumbNailholder',1);


//The main picture holder.
var mainPicture:MovieClip = $main.createEmptyMovieClip('mainLoader',0);

var width:Number = 360;//Width value - change at your will.

var height:Number = 480;//Height value - change at your will.

//The below function is the one that starts to cache images.
function cacheImages():Void
{
var ratio:Number = 360/480;
var thumbHeight:Number = 480/4;
var thumbHolder:MovieClip = galleryHolder.createEmptyMovieClip('holder',0);
for(var i:Number=0;i<19;i++)
{
var index:Number = 787 + i;
var path:String = 'images/SP_A0'+index+'.jpg';//Change this value to your custom image path
var thumb:MovieClip = thumbHolder.createEmptyMovieClip('gal'+i,i);
thumb.createEmptyMovieClip('loader',0).attachBitmap(iCache.cacheImage(path,360,480),0);
thumb.loader._width = ratio * thumbHeight;
thumb.loader._height = thumbHeight;
thumb._y = (thumbHeight+5) * i;
thumb.path = path;
thumb.onPress = function()
{
mainPicture.attachBitmap(iCache.cacheImage(this.path,360,480),0);
//mainPicture.createEmptyMovieClip('loader',0).loadMovie(this.path);
}
}
$spane.redraw(1);
}
imageHolder._visible = false;//setting the visiblity of the tempimages holder to false.

imageHolder._x = 100000;//setting the distance of the tempimages holder to a large one so we cannot see it.


iCache.registerTempLoader(imageHolder);//REgsitering the tempImage Holder as the loader for caching images.


cacheImages();//Start Caching Images.


So having restarted my blogging with the BitmapData class makes me feel a bit enthus !!!!

Thanks for reading.

Regards,

Ashok Srinivasan.

Thursday, September 21, 2006

CHAPTER 1

The start of the day was really nice with the orange ball whose surface temperature known to be 5800K just shooting up in the sky. Was really nice to see him on the rise. So had my quick breakfast and was making my way to work.

Soon after i landed i opened flash and geared up to look at it for the rest of the day. Soon i remembered about sterday where my colleague had a problem using those absolute paths to refer the movieclips due to which the heads were rolling on the floor with our dealine coming to a deadend.

I am an actionscript developer who is basically against using all those absolute paths and am comfortable using relative paths.

But the problem right in front was due to the fact of utter laziness. Seems to be like the movieClip was emerging around 7-8 levels inside the stage. (like _level0.instance1.instance2.instance3.instance4.instance5.instance6.mc);.


here we had to make a function call that resides in the level0 but were unable to coz the movie that we are publishing is just one of the swfs that gets loaded in another swf. and this might change sometime in the future. As i had faced all these scenarios 2 years before itself the experience helped me and i decided on that fine day that i will never use any absolute scoping but only relative mapping at any cost.

Now here is what i did to solve this problem. The movieclip instance from where i needed to call the function was a subchild of order 7 in a main instance on the stage called "$holder". So if we need to access the stage's timeline variables or functions we need to probably call like this

this._parent._parent._parent._parent._parent._parent._parent._parent.funcXYZ();

or

_level0.funcXYZ();

As i said earlier it is my principle that i will not use the second method(absolute pathing method).

So would i use the first method >???? NO !

Better i will device a prototype such that i will be able to use it to handle all the similar problems.

The solution was like this. But before that i had laid a simple rule that the last parent MC i.e., on the stage timeline will have an instance name and no other subparents inside it will have .

cool ? let's get back to the prototype.

MovieClip.prototype.findTheParent = function(whoseNameIs:String):MovieClip
{
var mc:MovieClip = this;
while(mc._name != whoseNameIs)
{
mc = mc._parent;
}
return mc;
}

So now coming to the part where this helped actual scenario being implemented, it was like using this way.....

this.findTheParent("$holder")._parent.funcXYZ();

instead of the below already above mentioned METHODS !@!!!!!!!
{
this._parent._parent._parent._parent._parent._parent._parent._parent.funcXYZ();

or

_level0.funcXYZ();
}



Hope this helps you all !. But sure it helped me!

ReGaRdS,

Ashok Srinivasan.

Wednesday, September 20, 2006

Prologue !

The Title that sounds to be the start of some drama or story will most probably does not have a epilogue for this world of ActionScript is so vast that it will not drain and chances are that it may not have a epilogue. (whew : it was just an opinion).

As this is the first time i am starting to blog and also wondering what to post (This is what has been making me not a blooger all this time i.e., "First Time").

i hereby start with a tip on the essence of Mathematics in programming.

Imagine you have a MovieClip , a Button and a Boolean variable. Now when the button is clicked we will set the bool to true or false respectively. Based on the Boolean value we need to set the alpha state of the button to 30(if false) or 100(if true) respectively.

Yeah i know what you are thinking. Just set a if and else condition that will control the alpha of the button. But dont tell me it is the only way we always need to do it.

To make things clear we will start it with the general way of Scripting.

Intially the MovieClip alpha is at 100.

//Actions on the timeLine

var bool:Boolean = true;

function setAlphaState()
{
if(bool)
{
mc._alpha = 100;
}
else
{
mc._alpha = 30;
}

}
//Actions on the button()

on(press)
{
bool = !bool;
setAlphaState();
}

But again the same setAlphaState function can be written as below thereby reducing the processing.

function setAlphaState()
{
if(!bool)
{
mc._alpha = 30;
return;
}
mc._alpha = 100;
}


Hence there are lot of ways that might emerge to write this piece of process using if and else conditions.

Imagine doing this mathematically,

function setAlphaState()
{
mc._alpha = (Number(bool) *(100-30)) +30 ;
}

Dont you think the above way will work ????? Try it and check it out.

Basically i am a guy who believes that using these if and else conditions actually make your application weak.

The Reason : When a scenario has to dealt with and if we are goin to use our head to analyse the situation we tend to miss out some micro situations and may not present these conditions in the if else part and hence as a result our programs tends to fail at a point.

But on the contrary when we analyze the scenario and get a Mathematical part that can govern the scenario and deal it in the natural way then there are less chances than that of if else way for failing.

Hence this way my blog starts with a note to why we need to use Mathematical methods to deal with scenarios than using wasting time to analyze the micro macro sub scenarios and write it on our own. (This cannot be applied all the time but should implement when we actually can )

Hope my first blog was not sounding so stupid for any advanced readers reading this and neither very advanced to those beginners also reading this.

ReGaRdS,
Ashok Srinivasan.