Skip to main content
Ben Nadel at CF Summit West 2024 (Las Vegas) with: Igor Mazor
Ben Nadel at CF Summit West 2024 (Las Vegas) with: Igor Mazor

Using InputBaseN() To Encode HEX Colors Into An INT In ColdFusion

By
Published in Comments (3)

As I'm digging into the Zxing barcode library in ColdFusion, one of the options that I have it set the On/Off colors for the pixels within the rendered image. Each of these colors is represented as a single integer in which the Alpha, Red, Green, and Blue channels of the color are encoded into the four bytes of the 32-bit integer, respectively. ColdFusion makes this an easy task with its inputBaseN() function, which allows us to effortlessly convert numbers between different radix.

To explore this technique, let's use Java's java.awt.Color class. This class can be instantiated using various constructor signatures. And for this exploration, we'll use these two:

  • Color( int r, int g, int b, int a )
  • Color( int rgba, boolean hasalpha )

The first constructor call will act as our control. Since we're passing-in the individual channels, we know that we won't have to worry about bit-mechanics. Then, the second constructor call will act as our test, to see if we can generate the same colors using a single integer (in which each byte represents a different channel).

Here's the ColdFusion code that makes both calls and then compares the output:

<cfscript>

	hexColor = "ff3366aa"; // {R,G,B,A}
	red =   hexColor.mid( 1, 2 );
	green = hexColor.mid( 3, 2 );
	blue =  hexColor.mid( 5, 2 );
	alpha = hexColor.mid( 7, 2 );

	// Creating colors using individual RGBA channels.
	colorFromChannels = createObject( "java", "java.awt.Color" ).init(
		inputBaseN( red,   16 ),
		inputBaseN( green, 16 ),
		inputBaseN( blue,  16 ),
		inputBaseN( alpha, 16 )
	);

	// Creating colors with a single INT in which each of the four bytes (within the INT)
	// represents Alpha, Red, Green, and Blue, respectively. Notice that we have to switch
	// where the Alpha byte is located: in the original Hex string it was at the end
	// (which is what we use on the web); but, the INT-input needs it to be at the start.
	colorFromInt = createObject( "java", "java.awt.Color" ).init(
		inputBaseN( "#alpha##red##green##blue#", 16 ),
		true // Has alpha.
	);

	dump(
		label = "From Channels",
		var = [
			colorFromChannels.getRed(),
			colorFromChannels.getGreen(),
			colorFromChannels.getBlue(),
			colorFromChannels.getAlpha()
		]
	);
	dump(
		label = "From HEX Int",
		var = [
			colorFromInt.getRed(),
			colorFromInt.getGreen(),
			colorFromInt.getBlue(),
			colorFromInt.getAlpha()
		]
	);

</cfscript>

One caveat here is that I defined the original input hex as ff3366aa, in which the alpha - aa - is at the end of the string. This is how colors work on the web. However, when representing the color as an INT (in this context), the alpha channel needs to be on the other end (aaff3366). This is why I'm using string concatenation when defining the colorFromInt variable.

And, when we run this ColdFusion code, we get the following output:

Screenshot of the RGBA channels of the two different colors showing same exact values.

As you can see, the RGBA channels extracted from the Color instances are exactly the same. We were able to properly represent the RGBA color as an INT in which each byte represented a different color.

I'll demonstrate this in a follow-up post on QR Codes; but, in the Zxing library, which technique allows me to easily create those On/Off colors:

<cfscript>

	imageConfig = fromJars( "com.google.zxing.client.j2se.MatrixToImageConfig" )
		.init(
			inputBaseN( "ff0000CD", 16 ), // On color ARGB.
			inputBaseN( "ffffffff", 16 )  // Off color ARGB.
		)
	;

</cfscript>

ColdFusion is so freaking sweet!

Want to use code from this post? Check out the license.

Reader Comments

29 Comments

@Ben,

I wonder what a barcode reader's minimum contrast needs to be between the two colors to be scannable. You may want to have one of the following:
Function to generate a contrasting color given an input color.
Function to determine if the contrast between two colors meets a minimum contrast level.

While the barcode is machine readable, I'd expect that people will need to recognize that one is present to know where to scan on a particular object. I wonder if there could to be a check on the color combination (On/Off colors) to determine if that combo could cause some colorblind folks to not be able to differentiate the colors to recognize that there's a barcode present.

16,042 Comments

@All,

As an update, this code actually breaks in Adobe ColdFusion (ACF). For reasons that I don't fully understand, Lucee CFML seems to be able to cast ffffffff to an int, but ACF cannot. At least not without using the "two's complement" approach. I've outlined that here:

www.bennadel.com/blog/4816-encoding-ffffffff-into-an-int-in-adobe-coldfusion.htm

Basically, when initializing the MatrixToImageConfig class, you have to finagle the ff______ value to use the most significant bit to represent a negative number by subtracting 2^32 from it. So, you'd have to change:

<cfscript>
	imageConfig = fromJars( "com.google.zxing.client.j2se.MatrixToImageConfig" )
		.init(
			inputBaseN( "ff0000CD", 16 ), // On color ARGB.
			inputBaseN( "ffffffff", 16 )  // Off color ARGB.
		)
	;
</cfscript>

... to be more like:

<cfscript>
	imageConfig = fromJars( "com.google.zxing.client.j2se.MatrixToImageConfig" )
		.init(
			( inputBaseN( "ff0000CD", 16 ) - 4294967296 ),
			( inputBaseN( "ffffffff", 16 ) - 4294967296 )
		)
	;
</cfscript>

That will then work in both Lucee CFML and Adobe ColdFusion.

16,042 Comments

@Danilo,

That's a really interesting question. And, on point for something I was thinking about over the weekend. When I was working on my ACF 2025 hackathon project, one thing I did was generate a QR Code. And, I used the ColdFusion logo colors as the on/off colors of the QR Code. But, they are both shades of blue and wasn't sure if the contrast would be enough. In my case, I just rendered it and checked it with my phone's camera app (which reads QR codes). And it worked; but, that's as much as I thought about it 😆

Post A Comment — I'd Love To Hear From You!

Post a Comment

I believe in love. I believe in compassion. I believe in human rights. I believe that we can afford to give more of these gifts to the world around us because it costs us nothing to be decent and kind and understanding. And, I want you to know that when you land on this site, you are accepted for who you are, no matter how you identify, what truths you live, or whatever kind of goofy shit makes you feel alive! Rock on with your bad self!
Ben Nadel

OSZAR »