mattsven
mattsven

Reputation: 23263

Converting alpha percent to RGBA hex in AS3?

Say I have the following setup in my AS code:

var color:String = "#0000FF"; //blue
var alpha:Number = 42; //42% or 42/100

How would I combine those into a #RRGGBBAA hex color? I've been Googling around and trying to figure out hexadecimal conversion and notation without luck.

Upvotes: 2

Views: 4760

Answers (2)

George Profenza
George Profenza

Reputation: 51837

There are two ways you could do this. One is a bit hacky using int's toString() method and passing 16 as the radix/base:

var rgb:int = (int)("#0000FF".replace("#","0x"));//convert the string to a int (note you can type hex ints starting with 0x (e.g. 0x0000FF)
var a:int = 42;
var rgba:int = int("0x"+rgb.toString(16) + a.toString(16));

or the less hacky and probably faster computationally method using bitwise operators:

var rgb:uint = (uint)("#0000FF".replace("#","0x"));
//extract components using bit shifting (>>) and masking (0xFF)
var r:uint = rgb >> 16 & 0xFF;
var g:uint = rgb >>  8 & 0xFF;
var b:uint = rgb >>  0 & 0xFF;//same as rgb >> 0xFF, just added >> 0 to make the shift obvious
var a:uint = 42;
var rgba:uint = r << 24 | g << 16 | b << 8 | a;
var argb:uint = a << 24 | r << 16 | g << 8 | b;
//test
trace(rgba.toString(16));
trace(argb.toString(16));

Note that using toString(16) in the trace above is to make it useful to us humans, you'd use the actual uint value when working with hex color values.

Also note that you might want to use ARGB in as3 sometimes, for example when working with BitmapData:

addChild(new BitmapData(100,100,true,0x2a0000ff));//add a 42% transparent blue box (100x100 px)

UPDATE

The above bitshift code snippet actually explains rgb extraction in detail which helps understand things better, but you already have rgb, so it's a matter of adding the alpha component. Also you mentioned 42% which is not the same as on a 0 to 255 scale. Therefore bellow lies your answer:

var rgb:uint = (uint)("#0000FF".replace("#","0x"));
var   a:uint = (uint)((42 * .01) * 255);//map 42 from 0<>100 to 0<>255 ( *.01 is the same as / 100 but faster
var rgba:uint = rgb << 8 | a;
var argb:uint = a << 24 | rgb;

Regarding speed, if I run the two different conversion methods a million times here are execution times:

using strings (var rgba:int = int("0x"+rgb.toString(16) + a.toString(16));) takes 851 ms 
using bitwise ops (var rgba:uint = rgb << 8| a;) takes 3 ms

As you can the bitwise version is much faster and for your case even less verbose than the string version. Also, now that you understand bitwise operators probably it's easier to read/understand.

In conclusion:

var color:String = "#0000FF"; //blue
var alpha:Number = 42; //42% or 42/100
var rgb:uint = (uint)(color.replace("#","0x"));
var   a:uint = (uint)((alpha * .01) * 255);
var rgba:uint = rgb << 8 | a;
trace("hex: #",rgba.toString(16),"test",0x0000ff6b.toString(16));

Also, it's funny you mentioned Google, because you can use the search to convert to hex.

Update: There seems to be a bit of confusion so I've split the 3 steps into functions:

  1. converting a hex string to an int
  2. converting a alpha percentage (0-100) to a 0-255 int
  3. concatenating the above

Which would be:

function getHex(hexStr:String):uint{
    return (uint)(hexStr.replace("#","0x"));
}
function getHexAlpha(alpha:uint):uint{
    return (uint)((alpha * .01) * 255);
}
function rgbaConcat(rgb:uint,a:uint):uint{
    return rgb << 8 | a;
}
trace("test",rgbaConcat(getHex("#FF9900"),getHexAlpha(50)).toString(16));

or all in one go:

function rgbaConcat(hexStr:String,alpha:uint):uint{
    var rgb:uint = (uint)(hexStr.replace("#","0x"));
    var a:uint = (uint)((alpha * .01) * 255);
    return (rgb << 8 | a);
}
trace("test",rgbaConcat("#123456",100).toString(16));

Upvotes: 8

wich
wich

Reputation: 17127

I'm not sure if sprintf or something similar is available in action script, but you would use something like:

var alpha_2:int = Math.round(255*alpha/100);
var rgba:String = sprintf("%s%2x", color, alpha_2);

By the way, be sure to check whether it is supposed to be #RRGGBBAA or #AARRGGBB

So apparently sprintf is not available, you can use some substitute as mentioned in Is there something like printf in Action Script 3?

If you do not like to use a printf like function you can use:

function hex_char(value:int) {
  if (value < 0)
    return "X";
  if (value < 10)
    return String.fromCharCode("0".charCodeAt(0)+value);
  if (value < 16)
    return String.fromCharCode("A".charCodeAt(0)+value-10);
  return "X";
}

var alpha_2:int = Math.round(255*alpha/100);
var rgba:String = color + hex_char(alpha_2/16) + hex_char(alpha_2%16);

alternatively you coulde use the following definition for hex_char which (I assume) will give you an exception/error for any value under 0 or over 15 instead of "X"

function hex_char(value:int) {
  return "0123456789ABCDEF".charAt(value);
}

Upvotes: 2

Related Questions