;

PDA

Click to See Complete Forum and Search --> : problem with ColorMatrixFilter and external images


divillysausages
10-23-2007, 01:17 PM
hi guys,
im having a problem with a site im currently making for work. part of the site is a gallery section, where thumbnails of movies come up in a little side area that you then click to view the movie in question.
im trying to get an effect to work, whereby the thumbnails (external images loaded using the MovieClipLoader) are desaturated and when you rollover them they regain their color. my problem is this:
when i initially desaturate the image in onLoadInit() and subsequently try to bring the colour back, nothing happens. the matrix is changing and the filter is being applied, so that's not the problem.
i then tried it the other way, starting off with the images normal, and desaturating on rollover and resaturating on rollout. this worked no problems.
so these are my thoughts on it:
when desaturating the image in onLoadInit() this is then set as the "proper" saturation, so when i go to try and resaturate the image, its bringing it to this state, hence stuff going on in the background but nothing visual happening.
not desaturating the image in onLoadInit() allows the proper image saturation to be recorded so stuff goes on in the background and you can see things happening.
this might seem a bit rambling, so to make it simpler, by desaturating the image in onLoadInit(), before the image is initially drawn, flash takes the image as essentially black and white. not desaturating it allows flash to "record" the color data. or something..
has anyone got any experience with this? im coding in cs3, but as actionscript 2.0 and exporting for flash 8 if it makes a difference

thanks
damian

cancerinform
10-24-2007, 08:03 AM
As far as I know you cannot apply any property when the object is not loaded. So you are basically manipulating an empty holder but not its content.

divillysausages
10-24-2007, 08:35 AM
hi cancerinform, thanks for getting back. i thought that was the whole point of onLoadInit(), that you could affect movieclips before they're drawn. im using it to set the size of the thumbnail and set the alpha so i can fade it in and it all works. to be honest this is the first time iv ever had something like this happen, so im at a bit of a loss
is there a way of using the bitmap class to trace out the rgba values of the image? maybe i can see something thats happening that way
thanks
damian

cancerinform
10-24-2007, 09:15 AM
You can use getPixel method. However, since the width of your holder is 0, you won't get any information. Only when the image is loaded you can.

divillysausages
10-24-2007, 09:33 AM
the width of the image does come in, as the onLoadInit() (MovieClipLoader) event fires when "the actions on the first frame of the loaded clip have been executed. When this listener has been invoked, you can set properties, use methods, and otherwise interact with the loaded movie" (from flash help)

i've no problems except when i tried to desaturate it. the movie desaturated correctly, but i couldn't "resaturate" it. the ColorMatrixFilter will call, but not work as it should. ill try and take it out into a seperate fla and upload it so you can see what i mean.

btw, the flash help getPixel() method uses the BitmapData class. i tried
target.cacheAsBitmap = true;
trace("---");
for(var i=0; i<target._width; i++){
for(var j=0; j<target._height; j++){
trace(target.getPixel(i, j).toString());
}
trace("\n");
}
for a loaded mc, but no joy

cancerinform
10-24-2007, 11:24 AM
This is how to get pixel:

import flash.display.BitmapData;
var obj:MovieClip;
var snap:BitmapData = new BitmapData (obj._width, obj._height);
trace (snap.getPixel (obj._x:Number, obj._y:Number));

divillysausages
10-24-2007, 12:05 PM
ok, after extracting all the relevant stuff to a seperate fla, i got it working, so i went back and rewrote the code in my project from scratch, and now it works. not sure why it didn't last time, shoddy bug fixing i guess :D

anywho, for the purpose of education, of just simply to pass some time for people who are bored, her is the full code to load in a jpg, and saturate / desaturate it based on mouse roll overing etc

for this to work, just copy the code into a new project and have an image called "image.jpg" in the same folder


import flash.filters.BitmapFilter; // import the bitmap filter
import flash.filters.ColorMatrixFilter; // import the color matrix filter
import mx.transitions.Tween; // import the tweening class
import mx.transitions.easing.Regular; // import the regular tweening

var _imageWidth:Number = 153; // the image width
var _imageHeight:Number = 119; // the image height
var _mcl:MovieClipLoader; // the movielclip loader
var _listener:Object; // the loader listener
var _holder:MovieClip = _root.createEmptyMovieClip("holder", _root.getNextHighestDepth()); // create a holder mc
var _r1tween, _r2tween, _r3tween, _g1tween, _g2tween, _g3tween, _b1tween, _b2tween, _b3tween:Tween; // the tween object
var _sat_to_desat:Boolean = false; // true = saturated to desaturated, false = desaturated to saturated
var _time:Number = 1; // the time taken to saturate / desaturate
var _func:Function = Regular.easeOut; // the ease function for the tween

// the desaturation values for rgb
var _r_desat:Number = 0.212671;
var _g_desat:Number = 0.715160;
var _b_desat:Number = 0.072169;

this._mcl = new MovieClipLoader(); // create a new movieclip loader
this._listener = new Object(); // create the listener
this._listener.onLoadInit = function(target:MovieClip):Void{ // tie the loadInit function to the class
target._width = _root._imageWidth;
target._height = _root._imageHeight;
target.cacheAsBitmap = true;

setInitialValues();
setActions();
_root.applyRGB(); // apply the rgb values to the image
}
this._mcl.addListener(this._listener); // add the listener

// set the image actions
function setActions():Void{
this._holder.onRollOver = function():Void{
if(_root._sat_to_desat)
desaturate();
else
saturate(); // saturate the image
}
this._holder.onRollOut = function():Void{
if(_root._sat_to_desat)
saturate();
else
desaturate(); // desaturate the image
}
}

function setInitialValues():Void{
// set the initial color values
if(this._sat_to_desat){
// hold the values for an identity color matrix
this._holder._r1 = this._holder._g2 = this._holder._b3 = 1;
this._holder._r2 = this._holder._r3 = this._holder._g1 = this._holder._g3 = this._holder._b1 = this._holder._b2 = 0;
} else {
// hold the values for a desaturated image
this._holder._r1 = this._holder._r2 = this._holder._r3 = this._r_desat;
this._holder._g1 = this._holder._g2 = this._holder._g3 = this._g_desat;
this._holder._b1 = this._holder._b2 = this._holder._b3 = this._b_desat;
}
}

// saturate
function saturate():Void{
_root.checkTweenPlaying(); // check to see if any tweens are playing, if so stop them
// move the rgb values from their desaturated values, to 1
_root._r1tween = new Tween(_root._holder, "_r1", _func, _root._holder._r1, 1, _time, true);
_root._r2tween = new Tween(_root._holder, "_r2", _func, _root._holder._r2, 0, _time, true);
_root._r3tween = new Tween(_root._holder, "_r3", _func, _root._holder._r3, 0, _time, true);
_root._g1tween = new Tween(_root._holder, "_g1", _func, _root._holder._g1, 0, _time, true);
_root._g2tween = new Tween(_root._holder, "_g2", _func, _root._holder._g2, 1, _time, true);
_root._g3tween = new Tween(_root._holder, "_g3", _func, _root._holder._g3, 0, _time, true);
_root._b1tween = new Tween(_root._holder, "_b1", _func, _root._holder._b1, 0, _time, true);
_root._b2tween = new Tween(_root._holder, "_b2", _func, _root._holder._b2, 0, _time, true);
_root._b3tween = new Tween(_root._holder, "_b3", _func, _root._holder._b3, 1, _time, true);
_root.onEnterFrame = applyRGB;
_root._r1tween.onMotionFinished = function():Void{
trace("image saturated");
delete _root.onEnterFrame;
}
}

// desaturate
function desaturate():Void{
_root.checkTweenPlaying(); // check to see if any tweens are playing, if so stop them
// move the rgb values from their desaturated values, to 1
_root._r1tween = new Tween(_root._holder, "_r1", _func, _root._holder._r1, _root._r_desat, _time, true);
_root._r2tween = new Tween(_root._holder, "_r2", _func, _root._holder._r2, _root._r_desat, _time, true);
_root._r3tween = new Tween(_root._holder, "_r3", _func, _root._holder._r3, _root._r_desat, _time, true);
_root._g1tween = new Tween(_root._holder, "_g1", _func, _root._holder._g1, _root._g_desat, _time, true);
_root._g2tween = new Tween(_root._holder, "_g2", _func, _root._holder._g2, _root._g_desat, _time, true);
_root._g3tween = new Tween(_root._holder, "_g3", _func, _root._holder._g3, _root._g_desat, _time, true);
_root._b1tween = new Tween(_root._holder, "_b1", _func, _root._holder._b1, _root._b_desat, _time, true);
_root._b2tween = new Tween(_root._holder, "_b2", _func, _root._holder._b2, _root._b_desat, _time, true);
_root._b3tween = new Tween(_root._holder, "_b3", _func, _root._holder._b3, _root._b_desat, _time, true);
_root.onEnterFrame = applyRGB;
_root._r1tween.onMotionFinished = function():Void{
trace("image desaturated");
delete _root.onEnterFrame;
}
}

// check to see if any tweens are currently playing, and if so, stop them
function checkTweenPlaying():Void{
if(_root._r1tween.isPlaying){
_root._r1tween.stop();
_root._r2tween.stop();
_root._r3tween.stop();
_root._g1tween.stop();
_root._g2tween.stop();
_root._g3tween.stop();
_root._b1tween.stop();
_root._b2tween.stop();
_root._b3tween.stop();
}
}

// apply the rgb values to the holder clip
function applyRGB():Void{
var matrix:Array = new Array();
matrix = matrix.concat([this._holder._r1, this._holder._g1, this._holder._b1, 0, 0]); // red
matrix = matrix.concat([this._holder._r2, this._holder._g2, this._holder._b2, 0, 0]); // green
matrix = matrix.concat([this._holder._r3, this._holder._g3, this._holder._b3, 0, 0]); // blue
matrix = matrix.concat([0, 0, 0, 1, 0]); // alpha

var filter:BitmapFilter = new ColorMatrixFilter(matrix);
this._holder.filters = new Array(filter);
}

this._mcl.loadClip("image.jpg", this._holder); // get the movieclip loader to load the image

chizet
04-16-2008, 06:07 PM
Any ideas on how to apply this to images pulled in via XML?

divillysausages
04-17-2008, 09:35 AM
should be something similar. if your xml looks something like this:

<?xml version="1.0" encoding="iso-8859-1"?>
<slideshow>
<image name="someImage1" />
<image name="someImage2" />
<image name="someImage3" />
</slideshow>

then you load them something like this:


var allPics:Array = new Array();
var loadedPics:Array = new Array();
var topDepth:Number;
//movieclip loader
_root.mcl = new MovieClipLoader();
_root.listen = new Object();
mcl.addListener(listen);
/*

create a new xml object and load the xml
*/
var ss:XML = new XML();
ss.ignoreWhite = true;
ss.load("info.xml");
ss.onLoad = parseXML;
/*

parse it
*/
function parseXML():Void {
_root.oSS = new Object();
oSS.rn = ss.firstChild; // slideshow
oSS.children = oSS.rn.childNodes;
topDepth = oSS.children.length+1;
for (var i = 0; i<oSS.children.length; i++) {
//get each pic and hold the name and logo vars
var child:XMLNode = oSS["child"+i] = oSS.children[i];
var name:String = child.attributes.name;
//make an object to hold all the props
var p:Object = _root["pic"+i] = oSS["pic"+i] = {n:name, num:i};
allPics.push(p);
}
loadPic(0);
}
/*

function to load the pic
*/
function loadPic(i:Number):Void {
var ob:Object = _root["pic"+i];
//create a holder clip
var m:MovieClip = _root.createEmptyMovieClip("image"+i, i+1);
listen.onLoadInit = function(t:MovieClip):Void {
//add to loaded pics, and set vars
loadedPics.push(t._name);
//
// do something here like set the actions
//

// load in the next one
if (loadedPics.length !== allPics.length) {
loadPic(i+1);
}
};
mcl.loadClip("images/"+ob.n+".jpg", m);
}


you could load the images into the holder clip instead of the root. you'd also have to change the actions and apply functions to apply it to the specific movieclip.

to be honest tho, this is only really useful if you're image is really big or bandwidth's a real problem. if it's just for thumbnails or something small, then you're only talking an additional few Kb, so its much easier to make a saturated and a desaturated version in photoshop, load them both in, then fade between them. much much easier and much less processor intensive :)

also, that code was taken from a project and the irrelevant bits removed, so test it separately to make sure it compiles :)

chizet
04-17-2008, 02:47 PM
Awesome, thanks man, very helpful.

My images are small but I'm going the Flash/XML route because my client needs to update the images on their own. Do you think this is the best way to accomplish that?

divillysausages
04-18-2008, 05:11 AM
if you can get him to make 2 versions of each image, then thats much easier. just provide a template xml file and fully explain EVERYTHING that needs to go in to make it work. to be honest tho, in my experience, they either don't change it when you deliver it, or just save new images with the same name so it overwrites what you've in there.