Search Box

Google
 

Sunday, February 18, 2007

ever wanted to make a face to others ?

Subject : Face cropping in flash, irregular image cropping, cropping of irregular shapes and of irregular symmetry.

I do not know why but amongst all the new features of flash player 8, BitmapData stands out of the rest shining like DHRUVA guiding and seemingly being the solution to all image/graphic related issue in flash (those issues are now history anyway).

But i would say that BitmapData ROCKS. Few days back i was just feeling i am getting to love this class very much and wanted to mention about her again and again. The rest of the blog is all about a small application that i had developed to meet the need like cutting a face or cutting a portion of the image using flash. I mean basically think it as an application/tool for cutting the beautiful face of yours and adding it to the headless cartoon with Superman's body. I know you have already suspected that i am upto some mischief. Maybe but even though it is so, but the end result is a tool being developed with the power of flash and php.

First of all i would like to thank "SEPIROTH" for his wonderful class tha does the saving of BitmapData and sending it to php safely. Hei man your class really rocks.

Next coming to the flash part (kudos to ME), which is the easiest part than php. Here is the place where some points are added to the image and in turn the points are interconnected with the lines and filled duly thus making a shape of irregular symmetry. No problem i have at all the times keep monitoring the individual points for their x,y coordinates and thus using them to compute the rectangle formed by these collection of points.

Do not get overwhelmed at this point for once you see the output you will start to understand howExaggerating i was in this summarisation. But still if you still wish to proceed by reading further read on, else jump to the bottom where there is a link pointing to the location of the files. No problem at all jumping and do not feel bad.

But before jumping to the link make sure you have all this in your system to test the tool !

PHP server with GD library installed.


Note: To install GD library (if not installed, make sure you take a backup of you php.ini before you make any changes.), open you php.ini file and remove the ';' symbol before the line ";extension=php_gd2.dll". This is for windows and i dont know what it looks like to enable GD library in php on linux box. i guess it should be "php_gd2.so" instead of ".dll".


Link to the image cropping files.


Link to the screenshot of the tool

(incase you are finding it difficult to download the file then mail me : ashok_srinivasan2002@yahoo.com. i will see to that i will be in a position to sort it.)


Hope you enjoy and use this tool for your wildest uses and adventures.

Regards,

Ashok Srinivasan.

Friday, February 16, 2007

A Delegate Action.

So what does Delegate has got to do with ActionScript ? Yes it means a lot when it comes to Actionscript classes and scope management. Scope issues are one of the fundamental issues when it comes to ActionScript classes.

Let me take the pleasure of discussing about Delegate class today. But wait where does Delegate come from ? She comes from mx.utils.Delegate. Meaning there is a folder 'mx' containing lots of flash goodies classes among them we find a branch 'utils' which holds the fruit called 'Delegate'. Why do i need to praise so much will be understood by you shortly.

Consider the following script :



//in the main timeline we have a movieclip with instance name "$mc".


var This:MovieClip = this;

this.$mc.onPress = function()
{
trace(This);//traces _level0;
}


Guess that code was very elementary to be understood and hope does not require any explanation. Things are working fine is assumed based on the trace message of "_level0" which should be seen when rendered.

But this is not the case when it comes to classes. For example consider the next example :



//Now in the main timeline using the movie created with the example 1.

var This:MovieClip = this;
var te:Test = new Test($mc);

//For the class 'Test' copy the code below, create a new .as name it "Test" and paste the code.


//The class defintion starts.

class Test
{
var movie:MovieClip;
var This:MovieClip;
public function Test(mc:MovieClip)
{
movie = mc;
This = movie._parent;
movie.onPress = function()
{
trace(This)//traces 'undefined';
}
}
}


Ctrl + Enter and click the movieclip on the stage.Now did you see what happened, it would have been a message 'undefined'. So how are we going to handle this forms the rest of the story with the introduction of our Delegate character as the hero.

Okay now we will do some slight modification to our "Test" class with the help of Delegate and see what happens.




//The class re - defintion starts.


import mx.utils.Delegate;
class Test
{
var movie:MovieClip;
var This:MovieClip;
public function Test(mc:MovieClip)
{
movie = mc;
This = movie._parent;
movie.onPress = Delegate.create(this,function()
{
trace(This)//traces '_level0';
});
}
}





Now on ctrl+Enter and triggering the press action of the movieclip displays a message "_level0" meaning the code was successfully doing the right thing. hmmm can i know what has happened to the new version of 'Test' class ? It was the 'Delegate' class who was taking the pain of mapping the variables of the class within the scope of the $mc's onPress action. B-e-a-utiful isn't it ?

The 'Delegate' class comes to the rescue for scope management while writing in classes.

As a bonus i wish to specify a hack for the Delegate class but i am stopped to make you wonder for what the bonus could be. If you start using Delegate class, soon you will come to a point you will be struck. Then at that time come back and earn your bonus. Till then happy sailing with Delegate class.


Regards,

Ashok Srinivasan.

Wednesday, February 14, 2007

Cloning is illegal , but not for FLASH OBJECTS..........

Its been really a controversial topic. "CLONING" was a buzz word that started the dawn of the era where Biotechonology was seen by a common man. Ask Michael Crichton and he would tell you scores of information about it in the form of stories. Dolly was the first cloned living being. Then there were protests, controversies and conspiracies following.

Do not worry by reading this and learning to Clone an Object or Array will not end you up in Jail, for cloning in ActionScript is not controversial or understanding it is like a grasping a big conspiracy theory.

But before that let us understand why do we need to clone ??? yeah that was a great question and i see a reason why you should read the rest of the story. The real reason for why cloning can be best understood by the following example :

Example 1 :



//in the main timeline

var num1:Number = 20;

var num2:Number = num1;
trace(num1);//traces 20
num2 = 50;
trace(num1);//traces 20 again;


Did you see what happened?
1)we created a variable num1 with a value 20.
2)Again we created a variable num2 and pointed it to num1.
3)Traced the value of num1 and it was 20
4) changed the value of num2 to 50
5) Traced the value of num1 and it was still 20.

I hope you would have understood what i am meaning by this. Once again consider the following example.

Example 2:



//In the main Timeline

var obj1:Object = new Object();
obj1.name = 'Ashok';
obj1.age = 24;

var obj2:Object = obj1;

trace(obj1.name);//traces Ashok;

obj2.name = 'Srinivasan';
trace(obj1.name);//traces Srinivasan.



So what happened here. We did the same thing that was done in Example 1, but the difference was that first example was dealing with numbers and the second one was dealing with objects. In the first one it was "copying of the value operation" and in the second one it was "pointer operation" meaning it does not create a copy and store in the new variable but instead points the first object "obj1" to the new name "obj2". Coincidentally this is the same case when we do it with Arrays. Luckily we have the "slice" and "splice" methods which can get us a copy so as to leaving the choice to us for creating a copy or pointer for an Array. But there is not a method that gives us the choice of creating copies.

Now how can this be solved ? How can i make a copy for an object and not create a pointer instead. ?

The fundamental principle is to use the "for in " loop method. But how do we clone if there are objects inside object ?

Accidentally when i was searching for ActionScript blogs yesterday i stumbled upon a blog in the name of "Arul's blog" (link:http://www.shockwave-india.com/blog/services/as-highlight2/index.php) and there the blogger guy has mentioned about this problem which made me also to think and give a mention cum workaround solution for this problem.

Using the code in "Arul's Blog" and modifying and reducing the lines where-ever possible i am pasting the code below. Make sure to check it out.




Object.prototype.clone = function ()
{
if (typeof (this) == "object")
{
var to = (this instanceof Array )?[]:{};
for (var i in this)
{
to[i] = (typeof (this[i]) == "object") ? this[i].clone () : this[i];
}
return to;
}
trace ("Warning! Object.clone can not be used on MovieClip or XML objects");
return undefined;
};
Object.prototype.trace2 = function()
{
for(var i in this)
{
trace (i + ' : ' + this[i]);
}
}
ASSetPropFlags (Object.prototype, ["clone"], 1);
ASSetPropFlags (Object.prototype, ["trace2"], 1);
myObject = new Object ();
myObject.name = "Ashok";
myObject.gender = "Male";
myObject.age = 24;
myObject.trace2();
copyObject = myObject.clone ();
copyObject.trace2();



So what does the code do ?? i guess the code was self-explanatory.

Regards,

Ashok Srinivasan.

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.