The tiles that make up each mosaic
March 15th, 2006 in The Making of TheBroth · By Markus WeichselbaumThis article reveals what the TheBroth’s tiles are actually made of.
Technically, each tile is a “div”, a standard HTML block element. Using CSS, we define its width and height, a background color, and borders.
The borders are used to create a subtle 3D bevel effect that makes the squares look more like tiles.
Animating the tiles
The x/y positions of the tiles are being manipulated using JavaScript. Read more about how the tiles are animated.
What colors should the tiles be?
Room owners that choose to have their own, room-specific mosaic have the option to define the colors of the tiles.

We use images to define the colors of the tiles. In other words, a source image is analyzed for its RGB color, pixel by pixel, and each RGB color is then assigned to a tile. Practically, it means that a room owner can upload an image (from within the account page), and voila, all tiles change color accordingly.
It’s a lot of fun uploading a JPEG of the Mona Lisa and then trying to reassemble the masterpiece, albeit with a rather drab color palette of lots of browns and greens!
We actually noticed some interesting psychological effects based on color choice. Read more here about the choice of tile colors.
In order to ensure we get all the colors, we first resize this source image so that it contains exactly (or near enough) as many pixels as we have tiles. The resizing algorithm (as part of the GD library for PHP) uses cubic interpolation so that we get a good approximation of all the colors present in the source image.
Calculating the border colors

To create a 3D bevel effect, we make the top and left borders ever so slightly lighter than the tile color, and the right and bottom borders darker.
For this, we use a simple but effective algorithm, using a lighten and darken factor, respectively, on each component of the RGB color value. For instance, to calculate a color that is darker, we could use 90% of the RGB value, eg. R x 0.9, G x 0.9, B x 0.9.
Similarly, to lighten, we may use 110%, eg. R x 1.1, G x 1.1, B x 1.1.
RGB manipulation in JavaScript
Here’s the JavaScript code that we ended up using in the final release version of TheBroth. Note that we use an array with three elements as the datatype for each RGB value.
function makeLighter(rgb) {
var r=Math.min(Math.round(rgb[0]*1.07),255);
var g=Math.min(Math.round(rgb[1]*1.07),255);
var b=Math.min(Math.round(rgb[2]*1.07),255);
return 'rgb('+r+','+g+','+b+') ';
}
function makeDarker(rgb) {
var r=Math.round(rgb[0]*0.913);
var g=Math.round(rgb[1]*0.913);
var b=Math.round(rgb[2]*0.913);
return 'rgb('+r+','+g+','+b+') ';
}
RGB manipulation in PHP
We sometimes also need to calculate these border colors (the lighter and the darker color) using PHP, for example for the snapshot function that creates actual images out of mosaics.
Here’s the equivalent PHP code. Note that the data structures are associative arrays as used by the GD libary. LIGHTEN_FACTOR and DARKEN_FACTOR are constants that are used globally throughout TheBroth. These constants are also used when the JavaScript code (as shown above) is generated via PHP.
function col_lighten($rgb) {
$rgb['red']=(int)min($rgb['red']*LIGHTEN_FACTOR,255);
$rgb['green']=(int)min($rgb['green']*LIGHTEN_FACTOR,255);
$rgb['blue']=(int)min($rgb['blue']*LIGHTEN_FACTOR,255);
return $rgb;
}
function col_darken($rgb) {
$rgb['red']=(int)($rgb['red']*DARKEN_FACTOR);
$rgb['green']=(int)($rgb['green']*DARKEN_FACTOR);
$rgb['blue']=(int)($rgb['blue']*DARKEN_FACTOR);
return $rgb;
}
Why not manipulate in the HSL color space?
We initially experimented with much more complicated border color algorithms that manipulated saturation and lightness independently. The algorithm converted the RGB value into the HSL color space (aka HSB) , but we found that this introduced more artefacts in the conversion than it did any good! Besides, this algorithm was obviously much slower in execution.
The effect of our poor man’s direct-in-RGB algorithm is in fact much more pleasing to the eye, runs much faster, and the effect is much easier to control.
More info on RGB and HSB at Web-Colors-Explained.com.
Why not use the CSS property border-style?
Yes, we could have used border-style:outset; instead of calculating our own border colors:
So why did we not use border-style? Simple - the effect is a bit unpredictable and typically way too pronounced. Our own function creates a much more subtle effect:












