Showing posts with label colour. Show all posts
Showing posts with label colour. Show all posts

Friday, 7 August 2009

Manipulating Colour in Flash - #4 - Building an Interactive Colour Mixer

Now we are beginning to see the end result of all my experiments with manipulating colour using Actionscript. Using the techniques from my previous posts, and a few others to get a working interface, this post explains how to make a simple RGB colour mixer that gives a preview of the colour and the hexadecimal value in a form that can be copy and pasted.

Demo SWF







The Interface

While it is very tempting for those with a graphics background to want to start by designing a groovy interface (including me), it is sometimes a good idea to get just a basic prototype working so you can get the bugs out of the code - and that's what you see here.

The demo above shows my basic interface. Before we can go much further you will need to lay out something similar on your stage. The items in the demo above are labelled, check the key below:

KEY:

A = MovieClip, instance name 'colourspot_mc'
B = Input Text, instance name 'red_txt', variable 'red'
C = Input Text, instance name 'green_txt', variable 'green'
D = Input Text, instance name 'blue_txt', variable 'blue'
E = Dynamic Text, variable 'displayhex'
F = MoveiClip, instance name 'redpointer_mc'
G = MovieClip, instance name 'redclicker_mc'
H = MoveiClip, instance name 'greenpointer_mc'
I = MovieClip, instance name 'greenclicker_mc'

J = MoveiClip, instance name 'bluepointer_mc'
K = MovieClip, instance name 'blueclicker_mc'


Once you have set up your objects on the stage as above, you are ready to start coding.

The Code

I won't go into long and drawn out explanations of everything this time. The colour manipulation is explained in previous posts on this blog, and other things are explained within the code as comments.

NOTE: For some reason blogger is not treating this code very well. When you dump it into Flash make sure you hit the 'Format' button so it looks as it should.



/* set default values for R, G and B */
var red = 0;
var green = 0;
var blue = 0;
/* Create colour object to control colourspot_mc */
var my_color:Color = new Color(colourspot_mc);
/* Button triggers conversion of RGB into hex, then applies it to the colour object */
onEnterFrame = function() { /*This enables colour to be constantly updated */
/* ensures that only values between 0 and 255 can be used for red */
if (red>255) {
red = 255;
}
if (red<0) {
red = 0;
}
/* convert red decimal into hex */
var decred = new Number(red);
hexred = decred.toString(16);
if (decred<=15) {
hexredfinal = "0"+hexred;
} else {
hexredfinal = hexred;
}
/* ensures that only values between 0 and 255 can be used for green */
if (green>255) {
green = 255;
}
if (green<0) {
green = 0;
}
/* convert green decimal into hex */
var decgreen = new Number(green);
hexgreen = decgreen.toString(16);
if (decgreen<=15) {
hexgreenfinal = "0"+hexgreen;
} else {
hexgreenfinal = hexgreen;
}
/* ensures that only values between 0 and 255 can be used for blue */
if (blue>255) {
blue = 255;
}
if (blue<0) {
blue = 0;
}
/* convert blue decimal into hex */
var decblue = new Number(blue);
hexblue = decblue.toString(16);
if (decblue<=15) {
hexbluefinal = "0"+hexblue;
} else {
hexbluefinal = hexblue;
}
/* build the final 6 digit hex figure and prepend with 0x as needed by Flash */
hex = "0x"+hexredfinal+hexgreenfinal+hexbluefinal;
/* build the final 6 digit hex figure and prepend with # as needed by HTML */
displayhex = "#"+hexredfinal+hexgreenfinal+hexbluefinal;
/* set the colour property of the colour object controlling the MovieClip */
my_color.setRGB(hex);
/* Update the location of the pointers */
_root.redpointer_mc._x = ((_root.redclicker_mc._width/256)*red)+_root.redclicker_mc._x;
_root.greenpointer_mc._x = ((_root.greenclicker_mc._width/256)*green)+_root.greenclicker_mc._x;
_root.bluepointer_mc._x = ((_root.blueclicker_mc._width/256)*blue)+_root.blueclicker_mc._x;
};
/* Set the red decimal value with a clicker */
_root.redclicker_mc.onPress = function () {
redleft = _root.redclicker_mc._x;
clickpos = _xmouse;
clickval = clickpos-redleft;
clickprop = (clickval/_root.redclicker_mc._width)*256;
red = Math.floor(clickprop);
/*moving the pointer
_root.redpointer_mc._x = clickpos;
}
/* Set the green decimal value with a clicker */
_root.greenclicker_mc.onPress = function () {
redleft = _root.greenclicker_mc._x;
clickpos = _xmouse;
clickval = clickpos-redleft;
clickprop = (clickval/_root.greenclicker_mc._width)*256;
green = Math.floor(clickprop);
/*moving the pointer */
_root.greenpointer_mc._x = clickpos;
}
/* Set the blue decimal value with a clicker */
_root.blueclicker_mc.onPress = function () {
/*Getting the zero point on the clicker bar */
redleft = _root.blueclicker_mc._x;
/*Capturing the location of the click on the clicker bar */
clickpos = _xmouse;
/*Calculating how far along the clicker bar the click was made */
clickval = clickpos-redleft;
/*Calculating the proportional distance along the bar at which the click was made as a figure between 0 and 1, then converting that into a value between 0 and 256. */
clickprop = (clickval/_root.blueclicker_mc._width)*256;
/*Converting the figure to an integer by rounding DOWN to the nearest whole number. Rounding DOWN ensures we can get 0 at the bottom and 255 rather than 256 at the top. */
blue = Math.floor(clickprop);
/*moving the pointer object to the position clicked on the clicker bar */
_root.bluepointer_mc._x = clickpos;
}


And there we have it.

Solving Issues as You Go

It is always interesting to solve some issues as you go. For instance, I hadn't quite decided whether I wanted users to be able to type RGB values, or just limit them to using the colour bars.

When I decided that some users might want to be able to type them (as it might be easier and faster in some situations) I realised that some users might enter a value greater than 255 - which would then give inaccurate results. So, at the last minute I included the code that converts any number higher than 255 into 255 and any number lower than 0 into 0. Like I say, always interesting.

Another implication was with the pointers on the colour bars (items F, H and J in my diagram). Making the RGB numbers updatem depending on where the user clicked, and moving the pointers to the place the user clicked was one thing. But now we had to also work it the other way, and get the pointers to move to the place on the colour bar representing the value the user typed. It wasn't difficult, just a case of working the equation the other way, but it needed doing.

Sometimes seemingly small decisions about user experience can have a significant impact on our code. That doesn't mean we shouldn't put the user first, but it does mean we should be prepared to modify our code when needed. After all, our interactive applications need to actually do what the user wants, if we want any users to use them.

Thursday, 6 August 2009

Converting Decimal RGB Values Into a 6 Digit Hexadecimal

Recent posts have looked at the Actionscript required to convert decimal numbers into hexadecimal strings. And if we don't look any deeper everything looks hunkydory for mixing any colour we like using RGB values, and then convert to a hexadecimal number you might use to define a colour in HTML.

But we still have a problem to solve.

Low Numbers v. High Numbers

HTML and Flash can both use hexadecimal values to define colours, but the hexadecimal values must be defined as a 6 digit number - 3 pairs representing the 3 colour channels Red, Green and Blue. For example:

White: Decimal Red 255 + Green 255 + Blue 255 = Hexadecimal FFFFFF

In most cases this won't present a problem, after all decimal 255 equates to hexadecimal FF. The problem comes when the decimal value drops below 16. Lets take a look:

Decimal 255 = hex FF
Decimal 16 = hex 10
Decimal 15 = hex F
Decimal 1 = hex 1
Decimal 0 = hex 0

Notice that as soon as the decimal value drops below 16 the hexadecimal value drops into single digits. Lets see what this means in practice:

Black: Decimal Red 0 + Green 0 + Blue 0 = Hexadecimal 000

This is a problem because to convey colour values to HTML or Flash consistently we need a 6 digit hexadecimal number, but what we have here is only a 3 digit number.

To solve the problem we need to remember how hex counts. As an example let's count to thirty in hex:

0 1 2 3 4 5 6 7 8 9 A B C D E F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E

In this example values 16 and above all have 2 digits in hex. We need to find a way of making the lower numbers all have 2 digits too. This is actually very easy, in fact we do this all the time, most commonly when we write the date. Take for example 1st January 2009 written numerically - 01/01/09. We can turn a single digit number into a 2 digit number, without changing its value, very easily by placing a '0' (zero) in front (this is called prepending), like so:

1 becomes 01
2 becomes 02

All we have to do then is prepend single digit hex values with a '0' (zero), like so:

00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

If we do this we can display black as a 6 digit hex number after all:

Black: Decimal Red 0 + Green 0 + Blue 0 = Hexadecimal 000000

But how do we do this in Flash with Actionscript?

Prepending Single Digit Hexadecimal Numbers With '0' Using Actionscript

I am sure there are many and varied ways to do this, but I prefer the following method. First I will give you the code, then I will explain how it works.

/* R is defined as a value between 0-255 in a text input field by the user */

_root.calc_but.onPress = function() {
var decimalred = new Number(R);
hexred = decimalred.toString(16);
if (decimalred<=15) {
hexredfinal = "0"+hexred;
} else {
hexredfinal = hexred;
}

}

Here's how it works:

1. First we take the user inputted value (a number between 0 and 255) and pass it to 'decimalred' specifically defining it as a number.

2. Then we convert the 'decimalred' number into a hexadecimal string and pass the result to 'hexred'.

3. Then we test to see if the original value inputted by the user was 15 or less. We do this because we already know that any decimal between 0 and 15 will convert to a single digit hex number.

4. If the original value inputted by the user was 15 or less, then we use Actionscript to prepend a '0' to the converted 'hexred' value like so:

hexredfinal = "0"+hexred;

Then we pass the result to 'hexredfinal'.

5. If the original value inputted by the user was not 15 or less, then we don't prepend anything, we just pass the 'hexred' value straight to 'hexredfinal' untouched.


In this way we can make sure that in the conversion from decimal to hexadecimal, all values between 0 and 255 are shown as 2 digit hex numbers. This allows us to produce the 6 digit numbers required in HTML and by Flash.

What fun.

Manipulating Colour in Flash - #3 - Successfully Converting Decimal to Hexadecimal Using the toString Method (even with user defined variables)

My last two posts looked at how you can use Actionscript to change the colour of a MovieClip, and to convert decimal colour values into hexadecimal.

Teething Trouble

But as I work towards harnessing these techniques to make a simple colour mixer in Flash I suddenly ran into difficulty converting decimal to hexadecimal when the user defines the decimal values in text input fields.

I must confess that to begin with I spent a while being stumped by this. As I Googled around for a solution there were similar questions, but no answers. Anyway, I am happy to say, there is a solution.

No doubt some of you will have a similar problem, so let me talk you through the problem I experienced and then the solution (I hope it helps).

The Problem

In my tests the toString method easily converted a decimal defined as a variable in a keyframe to a hexadecimal as follows:

/* This works */
var R = 255;

mybutton_but.onPress = function () {
hex = R.toString(16);
trace(hex); //Returns FF
}

However, when the value of R was defined by the user through a text input box it suddenly stopped working, as follows:

/* This DOESN'T work */
/* value of R is defined as 255 in a text input field by the user */


mybutton_but.onPress = function () {
hex = R.toString(16);
trace(hex); //Returns 255
}


For some reason, when the value of R was defined in the keyframe the toString method successfully converted the decimal value 255 and returned FF, but when the value of R was defined in a text input field the toString method failed to perform any conversion on the decimal value 255 and returned 255.

Preparing to Find a Solution

When I struggle with solving these niggly little problems I often find that taking some time out and doing something else gives the mind time to unwind (and also mull over the problem without having to try out every idea instantly). The brain is a fantastic problem solver, if it is given the right conditions. As a college lecturer I know that the ideal conditions come when an individual is relaxed but alert. So, if needed, take a break, unwind, get some sleep or remove distractions. I spent the morning cutting the grass and sorting out the chickens, then in the afternoon found the solution.

The Solution

As I said before, none of my Googling revealed an answer to my problem, but as I hunted around for anything I could find that might give me a hint, or prompt an idea I came across this snippet on WikiBooks.org:

var i = new Number(555);
trace(i.toString());

I must have seen several similar examples yesterday evening and got nothing from them (too tired no doubt). But having taken a break from the problem since then, and relaxed, my brain was ready to spot the significant detail that was the solution:

var i = new Number(555);

And there it was, staring out at me. Something I had not yet tried. So I modified my code as follows:

/* This DOES work */
/* value of R is defined as 255 in a text input field by the user */

mybutton_but.onPress = function () {
var decimalred = new Number(R);
hexred = decimalred.toString(16);
trace(hexred); //Returns FF
}

Why it Works

So why didn't it work before, and what's the big difference that makes it work this time?

I suspect that the reason it did not work before was because the user defined variable 'R' was already being treated by Flash as a string and so using the toString method to convert to a string did nothing, because it was already a string to start with.

Result: 255 (string) in, 255 (string) out.

The solution is really hidden within the problem (as are so many design solutions). We are converting a decimal value (representing a colour channel intensity) into its hexadecimal equivalent. We want to do this using the toString method. However, the toString method is for datatype conversion. This means converting one datatype to another datatype, in this case a non-string into a string. For this to work we need to force Flash to treat the user input 'R' as a number so that we can use toString to convert it into a string in hex format.

The script above does this by passing the user defined decimal value 'R' to a new variable 'decimalred' - with 'decimalred' specifically defined as being a new Number. This forces Flash to treat the user defined value as a number datatype thereby allowing toString to work as expected and convert the decimal number value to a hexadecimal string.

Result: 255 (number) in, FF (string) out.

And that's a wrap.

It is precisely this kind of problem that I see as being the drawback of having come to Flash and Actionscript from a graphic design, rather than a programming background. Nevertheless, I hope that by posting my solution I have helped at least one other poor designer get to grips with with one small area of Actionscript. If my Googling is anything to go by, this may well be the only explanation of this problem on the web (at time of posting of course).

Happy coding.

Tuesday, 4 August 2009

Manipulating Colour in Flash - #2 - Dynamically Changing MovieClip Colour

Converting decimal colour values into hexadecimal is one part of the puzzle, but then we have to use the result to dynamically change the colour of a MovieClip.

One of the inconsistent(?), and certainly annoying things about Flash is the way you modify the colour of a MovieClip with Actionscript. We already know you can modify various attributes of a MovieClip such as _height, _width, _x, _y, _rotation... but there is no attribute for colour.

The Colour Object

What you have to do instead is create a create a colour Object which in turn controls the colour of the MovieClip. It's not difficult, take this as an example:

var my_color:Color = new Color(MovieClipName_mc);

In this code we call the object 'my_color' and in the parenthesis we specify the instance name of the MovieClip the colour object will be controlling the colour of, in this case a MovieClip called 'MovieClipName_mc' - you can of course name your MovieClip differently, provided you specify its name in the parenthesis as above.

Changing the Colour

We know the name of the colour object - 'my_color' - so now we can tell Flash the colour value of that object in hexadecimal (just as we would specify a colour in HTML). Here's the code:

my_color.setRGB(0xFFFFFF);

In HTML we prefix a hexadecimal colour value with '#' as in '#FFFFFF'. In Actionscript we prefix with '0x' as above '0xFFFFFF'.

FFFFFF of course represents the colour White (if white is a colour), if you change this value in the script above the MovieClip specified in the colour object will adopt the same colour.

Practical Use

That explains the principles of how we can use a colour object to control the colour of a MovieClip, but how about a practical example...

1. Create an object on the stage, select it and hit F8 to turn it into a MovieClip. Give the MovieClip the instance name of 'colourthing_mc'.

2. Create a new layer, name it 'Actions', then select the first frame of the layer.

3. Now create a Dynamic Text Box of the Input variety on the stage. In the properties panel set the variable to be '_root.usercolour', the reason for this will be explained in my comments below.

4. Now create a Button on the stage and give it the instance name 'calc_but'.

And that's the easy bit, now for the easy code:

/* This is one of those really silly things about Flash. Instead of having a colour attribute like they have _width and _height attributes, you have to create a colour Object which in turn controls the colour of a specified MovieClip. Here's how you do it: */

var my_color:Color = new Color(colourthing_mc);

/* This next step sets up for allowing the user to specify the colour of the MovieClip. */

/* First we create the user controlled variable */

var usercolour = "000000";

/* Then we create another variable that is the result of formatting 'usercolour' as required for Flash to understand it as a hexadecimal value by pre-pending it with '0x' */

var hexusercolour = "0x"+usercolour;

/* Then we setRGB of 'my_color' to that hexadecimal value */

my_color.setRGB(hexusercolour);

/* All that remains is to create a dynamic text box that allows the user to input their own hex value for the 'usercolour' variable and a button that will update the 'my_color' value with the user value from the text box, whenever it is clicked.

The important thing to remember when setting up the text input box, is to se the variable very precisely. If the variable it is updating is in the root timeline, then you must define the variable in the text box as '_root.variablename' not simply 'variablename'. In this case the variable for the text box must be '_root.usercolour'. */

/* This code then makes the button update the colour object with the user specified value. */

_root.calc_but.onPress = function () {
var hexusercolour = "0x"+usercolour;
my_color.setRGB(hexusercolour);
}

And that should be it.

Now we have been able to change the colour of an object through user input of the hex value. This could be developed further to allow the user to change the value by using sliders. This will require us to change 0-255 values into hex values on the fly. But knowing what we know from my previous post, this shouldn't be too hard.

Monday, 3 August 2009

Manipulating Colour in Flash - #1

Following on from my previous post, I have begun to look into how I can use Actionscript to work with colour.

This experiment looks at how we can convert decimal RGB values into hexadecimal using Actionscript.

It's very simple...

The Code

/* First we set the RGB values as decimal integers (whole numbers) from 0-255, as you would see them defined in any graphics program. This example would reproduce white, but you can change the values to be anything you like between 0-255. */

var R = 255;
var G = 255;
var B = 255;

/* Then we convert the RGB decimals to their hexadecimal equivalents. The toString method is the easiest way I have found of doing it (thanks to Colin Moock). This script takes the value of each of the variables and converts the datatype from a numeric value
(in this case 255) into a string using '16' as the radix argument of the method. As a result 255 becomes FF, the hexadecimal equivalent. The code below then simply stitches the converted values of the R, G and B variables together to form a 6 digit hex number for the colour. */

trace(R.toString(16)+G.toString(16)+B.toString(16)); //Returns FFFFFF


What I like about this method is its simplicity. It would form the basis of a very simple colour mixer program, since the R, G and B values could easily be set by sliders, or the user keying in decimal values for each of the channels.

Over to you... meanwhile, I play with colour some more.

Thoughts on Colour

Colour is a fascinating thing. As a child there was always that wonder of discovery that went with mixing colours to make new colours... always resulting in that grimy brown in the end.

I have since learned that as a child I was playing with subtractive colour, the mixing of pigments to subtract from white and make black. Meanwhile your computer monitor uses additive colour, mixing light to add to black and make white.

It gets even more interesting when you introduce colour wheels and start to notice the relationships between primary, secondary and tertiary colours. Or the difference between tint, hue and shade, or complementary colours and colours in common.

16 Million +

Computers make mixing colours so easy, in fact, with the right tools it becomes less about art or aesthetics and more about mathematics. Did you know for instance that the 16 million or so colours your monitor can display are made up of just 3 colours, red, green and blue? Each of these is called a channel, a red channel, a green channel and a blue channel. In fact your computer can display 256 increments (levels of colour strength) on each channel and by mixing those colours in different amounts you get all the colours available to your monitor.

Just think about it, 3 colour channels, 256 increments of each to mix:

256 x 256 x 256 = 16,777,216 possible colours

Decimal v. Hexadecimal

In decimal we count from 0 to 9 before starting over, giving us 10 increments. like so:

0 1 2 3 4 5 6 7 8 9

Using decimal to define colour we start with 0 as the lowest colour value, and end with 255 as the highest, giving 256 increments.

However, HTML (and at times Flash) prefers hexadecimal which differs from decimal in that we count from 0 to 15 before starting over, giving us 16 increments. Like so:

0 1 2 3 4 5 6 7 8 9 A B C D E F

Using hexadecimal to define colour we start with 00 as the lowest colour value, and end with FF as the highest, giving 256 increments also.

We can say that a decimal 255 and a hexadecimal FF are of equal value. They represent the same number. Likewise a decimal 0 and a hexadecimal 00 are also equal.

Defining Colour Values Numerically

A present we are looking at specifying RGB colour, that is colour defined by the amounts of Red, Green and Blue in their makeup.

When defining RGB colour numerically, it is vital to remember the order of the colour channels. It is always Red, then Green, then Blue. Take the following decimal example:

255,192,128

Knowing the order of the colour channels means we can understand that this means the Red channel is on full blast at 255, the green channel is at three-quarter strength at 192 and the blue channel is at about half strength at 128.

Using hexadecimal we would write the same colour as:

FFC080

The first 2 digits are the red channel, the second 2 digits the green channel and the last 2 digits the blue channel.

Fascinating stuff.

Anyway, as a result of my interest in digital colour, I have decided to take the plunge and see how Flash can be used to manipulate colour. From my initial reading an understanding of the above will be vital to colour manipulation with Actionscript.