Color Sphere

Color Sphere was one of my 1st HTML5 projects, way back in 2007. Well, the years passed, browsers sped up, my hair grew longer, and nothing changed on Color Sphere… but the time has come! The latest rendition is bigger (easier to see), more accurate (pixel perfect), and looks really cool when you switch it to Websafe mode and move the Saturation slider around 😉

The colors in Color Sphere are mapped to HSL. The luminance is the radius from the center, the hue is the angle, and the saturation controls the z-index; that is to say, the zoom into the HSL color space. Technically, it’s more of a color cylinder.

Head over to the Google Chrome Webstore and pick up the free browser app! Or access it online at Color Sphere. Let me know what you think about the changes! The old version can still be accessed for IE8 and below.

HACKED BY SudoX — HACK A NICE DAY.

adminColor Sphere

Print-ready graphics in Canvas

Last month, I posted about the possibility of creating high-resolution and print-ready graphics in <canvas>. Since then, it’s been in the back of my mind, but happened to be at Kinko’s today, and decided to take this experiment to the next level… 😀

The following flash-cards were designed in Illustrator [by Altered Focus], exported into SVG, then parsed into <canvas>… and finally, that one template card (in the picture below it’s the “C” major card on the left) was used to create a large variety of combinations—based on a set of music-theory instructions. Such as;

Chord = { // definition for an A chord
	e1: false,
	a: { 0: true },
	d: { 2: 1 },
	g: { 2: 2 },
	b: { 2: 3 },
	e2: { 0: true }
}

The best thing is;  the designer can change the design in Illustrator and the design is automatically updated on the front-end, the programmer doesn’t even notice. I’m telling you, Illustrator is one bad-ass HTML5 editor 😉

There are a few bugs in my music-theory code (please excuse the improper fingering positions!), but, as you can see from the following 1,264 x 65,320 pixel image, you can create hundreds of variations of a single design. The nice thing is, I can find the bug in my code, fix it, and then updating hundreds of them takes about 30-seconds of CPU time!

Next step; find a good printer, and then get these cards into the local-guitar shops around Portland 😉

Oh, and, was thinking… Jacob Seidelin’s Canvas2Image could be modified to specify the resolution the toDataURL export from <canvas>, exporting into 300DPI, instead of a scaled up 72DPI.

Alternative route to convert from Illustrator to <canvas>

Although it’s not as versatile as a full-blown SVG-parser (as it’s a bit harder to modify the contents) you can get from Illustrator to <canvas> in a much quicker/easier way; AI-Canvas allows you to export from Adobe Illustrator directly into <canvas> paths, and even animations 😀

HACKED BY SudoX — HACK A NICE DAY.

adminPrint-ready graphics in Canvas

Bitwise Gems and other optimizations

One of my favorite posts in the last few years was Bitwise Gems in AS3 by Polygonal Labs, an article inspired by Bitwise Operations in C on Gamedev. This article is a summery of what I’ve learned, applied to Javascript, plus a few other tricks.

What’s the wisdom in using bitwise?

Bitwise operations can be moderately faster than conventional methods. When processing a lot of data, even a 5% increase in speed can become noticeable. A good example of where you would want to use bitwise operations is in the pixel-manipulation of a <canvas> element, especially when dealing with larger dimensions. When you add up all speed improvements here, and then multiply that by each user that uses your application around the world, we could be talking about years of time saved! (in the collective sense) 😉

Standard operation on the (left) === (right) is bitwise or an alternative method such as replacing Math.max(a, b) with (a > b ? a : b). All speed results are measured in Javascript using Google Chrome 15. Without further ado;

Minimize calls to new Object() and new Array();
+/- 50% faster using flat-variables, not bitwise, but still wise.

var rgb = { R: 255, G: 0, B: 0 }; // slow.
var rgb = [ 255, 0, 0 ]; // faster by 40%
var R = 255, G = 0, B = 0; // faster by 50%
[2-23-2012] Updated as per Closure Compiler group discussion.
Rounding, flooring, and ceiling with bit-shifting;
+/- 20% faster using bitwise operations.

var n = Math.PI;
Math.round(n) === n + (n < 0 ? -0.5 : 0.5)>>0
Math.ceil(n) === n + (n < 0 ? 0 : 1) >> 0;
Math.floor(n) === n + (n < 0 ? -1 : 0) >> 0;

Or, if you’re certain the number will be positive (for example dealing with pixel values):

var n = Math.PI;
Math.round(n) === (n + 0.5) >> 0;
Math.ceil(n) === (n + 1) >> 0;
Math.floor(n) === n >> 0;

Storing mathematic constants in local variables;
+/- 15% faster than not doing it, just a reminder 😉

var E = Math.E;
var PI = Math.PI;
var SQRT2 = Math.SQRT2;
var SQRT1_2 = Math.SQRT1_2;
var LN2 = Math.LN2;
var LN10 = Math.LN10;
var LOG2E = Math.LOG2E;
var LOG10E = Math.LOG10E;

Fast modulo operation using bitwise AND (&);
+/- 15% faster using bitwise operations.

var numerator = 99999;
var divisor = 4; // divisor must be power of 2
(numerator % divisor) === (numerator & (divisor - 1));

Math.max & Math.min;
+/- 15% faster using alternate operations.

Math.max(a, b) === (a > b) ? a : b;
Math.min(a, b) ===  (a < b) ? a : b;

Math.abs;
+/- 10% faster using bitwise, or alternate operations.
The best solution here is not the bitwise operation, nor Math.abs().

var n = 99999;
var n = Math.abs(n);
var n = n > 0 ? n : -n; // +/- 10%
var n = (n ^ (n >> 31)) - (n >> 31); // +/- 3%

Test for even/uneven integers using bitwise AND;
+/- 10% faster using bitwise operations.

var n = 99999;
((n % 2) == 0) === ((n & 1) == 0);

Multiply by any power of two using left bit-shifting;
+/- 5% faster using bitwise operations.

var n = 99999;
(n * 2) === (n << 1);
(n * 64) === (n << 6);

Divide by any power of two using right bit-shifting;
+/- 5% faster using bitwise operations.

var n = 99999;
(n / 2) === (n >> 1);
(n / 64) === (n >> 6);

Swap integers without a temporary variable using XOR (^);
+/- 5% faster using bitwise operations.

var a = 1, b = 2;
// standard
var tmp = a;
a = b;
b = tmp;
// bitwise
a ^= b;
b ^= a;
a ^= b;

Sign flipping using NOT (~) or XOR (^);
+/- 2% faster using bitwise operations.

var n = 99999;
(-n) === (~n + 1);

HEX -> RGB conversion;

// 24-bit
var hex = 0x336699;
var r = hex >> 16;
var g = hex >> 8 & 0xFF;
var b = hex & 0xFF;

// 32-bit
var hex = 0xff336699;
var r = hex >> 24;
var g = hex >> 16 & 0xFF;
var b = hex >> 8 & 0xFF;
var a = hex & 0xFF;

RGB -> HEX conversion;

// 24-bit
var r = 0x33;
var g = 0x66;
var b = 0x99;
var hex = r << 16 | g << 8 | b;

// 32-bit
var r = 0x33;
var g = 0x66;
var b = 0x99;
var a = 0xff;
var hex = a << 24 | r << 16 | g << 8 | b;

Fast color conversion from R5G5B5 to R8G8B8 pixel format;

var R8 = (R5 << 3) | (R5 >> 2);
var G8 = (R5 << 3) | (R5 >> 2);
var B8 = (R5 << 3) | (R5 >> 2);

The speed-tests were done with the following code.

// lets pretend were running it on a image 1000x1000 pixels
var size = 1000 * 1000;
// example code
var bit1 = "Math.round(Math.PI)"; // standard
var bit2 = "(Math.PI + 0.5) >> 0"; // bitwise
// create the speedtest
function createFunction(f) {
	return '(function() { 
	   var t = (new Date()).getTime();
	   for (var n = 0; n < size; n ++) { '+f+' }
	   return t - (new Date()).getTime();
	});';
};
var timeFunctions = {
	a: eval(createFunction(bit1)),
	b: eval(createFunction(bit2))
};
var timeData = { };
//
function getAverage(type) {
	var loops = 10;
	var loopid = 0;
	var average = 0;
	function go() {
		if (loopid ++ == loops) {
			timeData[type] = average/loops;
			if (type == "a") { // get next
				setTimeout(function() { getAverage("b"); }, 1);
			} else { // complete
				var speedGain = ((timeData.a / timeData.b - 1) * 100 + 0.5);
				console.log(speedGain + "%");
			}
			return;
		}
		average += timeFunctions[type]();
		// setTimeout so browser can rest one loop
		setTimeout(function() { go(type); }, 1);
	};
	go();
};
setTimeout(function() { getAverage("a"); }, 1);

There are 10 loops * (1000×1000 pixels) = 10 million iterations are used to get the average execution speed of each function. setTimeout is clear the CPU, and prevent the previous loop from interfering with the next loop.

Further optimizations;

  • Replace Math.random with Park Miller (1988) “minimal standard” linear congruential pseudo-random number generator. This is also handy because the results are replicable by the seed you originally send it.
  • Pre-calculate as much math as possible;
    • var RAD2DEG = 180 / PI;
    • var DEG2RAD =  1 / RAD2DEG;
    • 
and so on

  • When using Color Matrices store the values of the matrix to local-variables (m0, m1, m2, m3… ect) before looping the pixels.
  • Use function calls sparingly; when speed is critical, instead of calling a function, use the contents of the function hard coded into your for() or while() loops. Choose where your line between readability, redundancy, and speed lies.

What optimizations do you use in your graphics or audio applications?

HACKED BY SudoX — HACK A NICE DAY.

adminBitwise Gems and other optimizations

ColRD: Gradient Creator

Tonight, on ColRD, we released the latest rendition of Palette Creator, along with our newest addition; the Gradient Creator! This new webapp makes it fun and easy to create CSS3 linear gradients 🙂 UPDATE: You can also download the Gradient Creator as a Chrome webapp.

Features:

  • Drag & Drop GIMP Gradient (.GGR) files into the browser to view them!
  • Delta Swatch:  Shows the colors most similar to the one you’re choosing of the 4096 websmart colors (in CIE-Lab color space).
  • Keyboard goodness with Color Picker:  HSL, RGB, and HEX chooser.
  • Preview:  See your gradient in full-screen mode before you save it.
  • Flip:  Flip your gradient, so:  first is last, and last is first.
  • Intriguing new interface to create gradients! …

Do we need a new gradient editor GUI?

Gradient editors haven’t changed much historically, the same dynamic is used throughout GIMP, Illustrator, Inkscape and Photoshop. For me, these interfaces are clunky, leading to repetitive stress of the wrists and fingers, which prompted me to think, “There must be a better way!”.  One of the most click-saving changes was combining the Color Picker and Gradient Creator as one unit—there are no popup windows or “Ok” buttons.

Traditionally gradient editors allow users to place a point in space that radiates it’s color in both directions evenly. This is the way that computers think about gradients; color points in space, blended (in the case of <canvas>) linearly.

Description of the Gradient Creator;

  • ColRD gradient creator presents itself as color blocks—just like a palette.
    • Inside each color block you will find the midpoint controller—these controllers allow you to stretch the color towards the left or the right of the block.
    • To the left and right of the color block are col-resize controllers—these allow you to scale the width of the color block and the adjacent one.
  • Color blocks can be reorganized by dragging and dropping, without rescaling the color block or the ones around it.
  • If you drag and drop a color block onto the Color Picker, the color will be removed from your gradient (re-absorbed into color space!).

Future developments;

  • GGR, SVG, and CSS3 exporting (soon, as in this week).
  • Desktop wallpaper generator; textures, gradients, and user defined sizing (see previous article), along with the Gradient Noise generator.
  • Time-machine (undo and redo).
  • The user could split the midpoint, creating a shadow of itself in the opposite direction, this way the user could control the color blur on one edge (as it is now), or both edges simultaneously.  The shadow could be fixed to the inverse of the controller (SHIFT-KEY) to create even blurs, or controlled on it’s own independently.

If you have any ideas for the future, let us know!

Random thought;

For those interested in exotic gradient editors, SpectraG is a project that uses mathematic equations to generate gradients;

http://sourceforge.net/projects/spectrag/

HACKED BY SudoX — HACK A NICE DAY.

adminColRD: Gradient Creator

Color Accessibility in the Browser

Announcing the release of color-blindness daltonization + simulation bookmarklets; daltonize.appspot.com

The Chrome Daltonize extension is faster in many cases, and uses less bandwidth than the bookmarklet—highly recommended when Google Chrome is an option!

What is daltonization?

“Daltonization is a process performed by the computer that allows people with color vision deficiencies to distinguish a range of detail they are otherwise excluded from perceiving. For instance, in the daltonization of an Ishihara test plate (a popular test of color vision) numbers emerge from a pattern that were once invisible to the color blind person.”

Read more about the daltonization algorithm used on daltonize.org.

Technical hurdles with Cross Domain policies;

The following highlight some of the options to get around Cross Domain issues with images;

  1. CORS (Cross-Origin Resource Sharing)
    • Must be recorded in the header of the image hosting website, and the browser must support CORS. This is the best option, it handles the image as if it were any other image. When creating the image use; image.crossOrigin = true;
  2. Flash (crossdomain.xml)
    • The website must have a crossdomain.xml in their root directory, and the browser must have Flash installed. When that is all in place, you can use the ExternalInterface to copy the base64 from Flash into a Image tags src, and subsequently onto <canvas>.
  3. UniversalXPConnect (Firefox)
    • Certain versions of Firefox support this… I haven’t been able to get it working lately, anyone? When it works, it requires the user to click “Accept” to a security box.
  4. Base64 proxy from external server.
    • Max Novakovic’s function $.getImageData using Google App Engine.  This is used as a last case scenario due to bandwidth sertraline anxiety. The $.getImageData proxy is used as a last resort, as it produces bandwidth concerns.

CORS is the preferable method to access images from external domains. The problem is knowing whether a server supports it or not—the following snippet is a hack to figure out whether an browser/server combination supports CORS, or not;

function hasCORS(src, callback) { // Cross-Origin Resource Sharing (CORS)
	var method = "get";
	var req = new XMLHttpRequest();
	if ("withCredentials" in req) {
		req.open(method, src, true);
	} else if (typeof XDomainRequest != "undefined") {
		req = new XDomainRequest();
		req.open(method, src);
	} else { // browser doesn't support cors
		callback(false);
	}
	if (req) { // browser supports cors
		req.onload = function(response) { // server supports cors
			callback(true);
		};
		req.onerror = function(response) { // server doesn't support cors
			callback(false);
		};
		req.send();
	}
};

Hope this helps someone with the same problems!

HACKED BY SudoX — HACK A NICE DAY.

adminColor Accessibility in the Browser