Categories
photography

Haw Par Villa, Singapore, July 2009

IMG_7156

I went to Haw Par Villa with a mate to shot photos for my “Abandoned Places” [flickr.com] collection and because I think abandoned places are cool. I don’t have a great eye to get the feeling across but I try. Haw Par villa is not actually abandoned, but it’s as close to it as you can come. I can’t imagine the government will keep it open too much longer. Click the image for the full set of photos. See Wikipedia [wikipedia.org] for more info on Haw Par Villa..

You can see the whole Haw Par Villa, Singapore, July 2009 photoset on Flickr [flickr.com].

Categories
photography

Jelly!

IMG_6803
Categories
technical

Concerning Color Algorithms

Long ago I worked on an interface for a reporting system that displayed transaction volume data as a large table; days on one axis and hours on the other.  To improve the readability of this densely packed data we wrote a coloring algorithm to change the background color of the table cell.  The algorithm colored each cell in relation to every other cell using the minimum and maximum values of the displayed data.  The effect was quite good.  Users could instantly see patterns in the data without having to read the actual number in the cells.  This data display, though simple was one of the main selling points of the system.  End-users like the sexy packaging, the unseen technology that actually makes the system a wonder is only of interest to the developers—unless of course it does not work.

I spent a lot of time improving the UI of the system as a project once, and when my CTO asked me what I was going one day I said “optimizing the color algorithm”—that was a mistake.  I didn’t sleep for the next 6 months as I was assigned the new, high priority, has-to-be-done-now project.  For a new technology, that I had no idea how it worked.  It was fun, but that’s a story for another day. The reason I raise this here is that I never finished the intended work on the color algorithm. One of the major goals that I never got to was to fix the color range. The algorithm as implemented ended up with colors that transitioned from purple to yellow. I wanted to improve the algorithm to output colors that transitioned from red through yellow to green. Never got done.

Recently I was working on a project that required some visual UI work. One of the elements was a bar chart that displayed volume over time. So I used the same-old, same-old color algorithm (in PHP):

/*
* getColor()
* $max := the highest value in the set to be colored.
* $min := the lowest value in the set to be colored.
* $c := the current item's value.
*
* Returns a string; the HEX representation of an RGB color.
*/
function getColor( $max, $min, $c) {
   $j=0;
   $r=0;
   $g=0;
   $b=0;

   $j = $max != $min ? ( $c - $min ) * 20 / ( $max - $min) : 0;
   $j = $j > 20 ? 20 : $j;

   $r = 5 + $j;
   $r = $r > 15 ? 15 : $r;

   $g = 5 + $j/2;
   $g = $g > 15 ? 15 : $g;

   $b = 10 - $j/2;
   $b = $b > 0 ? 0 : $b;

   return sprintf( "%01x%01x%01x%01x%01x%01x", $r,$r,$g,0,$b,0 );
}
Old getColor output

Simple right? Well using that you end up with this:

So I started scratching my itch to fix the colors.

My first thought was to just ask a question over at StackOverflow [stackoverflow.com]. As I was typing in my question the system suggested existing questions… and since it’s an SO faux pas to repeat questions I started looking at them. It didn’t take long before I found two questions that seemed to be pointing me in the right direction: 1. Generate colors between red and green for a power meter [stackoverflow.com] and 2. Color scaling function [stackoverflow.com].

Reading the answers to those questions it took about 30 minutes to do this:

/*
* getColor()
*
* $max := the highest value in the set to be colored.
* $min := the lowest value in the set to be colored.
* $c := the current item's value.
*
* Returns a string; the RGB representation of a color (eg. "rgb(255, 255, 255)").
*/
function getColor( $max, $min, $c) {
   $h = (.33 / ($max - $min)) * ($c - $min);
   $s = .8;
   $v = 1;

   $rgb = hsv2rgb($h, $s, $v);

   return(sprintf("rgb(%d,%d,%d)", $rgb['r'], $rgb['g'], $rgb['b']));
}

/*
* hsv2rgb()
*
* $h := the hue, normalized to 0-1.
* $s := the saturation, normalized to 0-1.
* $v := the value, normalized to 0-1.
*
* Returns an associative array containing the red ('r'), green ('g') and blue ('b') values in the range 0-255.
*/
function hsv2rgb ($h, $s, $v){
   $rgb = array();

   if($s == 0){
      $r = $g = $b = $v * 255;
   } else {
      $var_h = $h * 6;
      $var_i = floor( $var_h );
      $var_1 = $v * ( 1 - $s );
      $var_2 = $v * ( 1 - $s * ( $var_h - $var_i ) );
      $var_3 = $v * ( 1 - $s * (1 - ( $var_h - $var_i ) ) );

      if ($var_i == 0) { $var_r = $v ; $var_g = $var_3 ; $var_b = $var_1 ; }
      else if ($var_i == 1) { $var_r = $var_2 ; $var_g = $v ; $var_b = $var_1 ; }
      else if ($var_i == 2) { $var_r = $var_1 ; $var_g = $v ; $var_b = $var_3 ; }
      else if ($var_i == 3) { $var_r = $var_1 ; $var_g = $var_2 ; $var_b = $v ; }
      else if ($var_i == 4) { $var_r = $var_3 ; $var_g = $var_1 ; $var_b = $v ; }
      else { $var_r = $v ; $var_g = $var_1 ; $var_b = $var_2 ; }

      $r = $var_r * 255;
      $g = $var_g * 255;
      $b = $var_b * 255;
   }

   $rgb['r'] = $r;
   $rgb['g'] = $g;
   $rgb['b'] = $b;

   return $rgb;
}

And…. voila:

New getColor output

That’s great! Now maybe I’ll play with the hue bounds, the saturation and the value, but it looks fairly good on my first try.

Moral of the story: this is what StackOverflow is for; getting an answer to a question without even asking it… Because you are not re-inventing the wheel, someone had your problem before, and maybe someone found the answer already. SO, thanks to Paul Dixon [stackoverflow.com] (also here [blog.dixo.net]) and ΤΖΩΤΖΙΟΥ [stackoverflow.com] for their answers!

Categories
ranting

Published 2

I’ve been published; [confusion.cc] again… This time by the Norwegians:

Delte Meninger

I don’t read Norwegian but judging from the website [deltemeninger.no], it’s something to do with ‘the social web’. My photo (here on Flickr [flickr.com]) appears on page 37. Funny that neither this photo nor the one chosen for the cover of Vocabulaire du chinois contemporain 1 are ones I would consider to be among my best [flickr.com].

Interesting that the published cover above (scanned from the book I got) differs from the cover distributed with the ebook in HTML format here [f9.no].

Categories
ranting

One small step

Buzz Aldran's boot print on the moon.

It’s not Armstrong’s [wikipedia.org] “one small step” footprint, it’s a later footprint by Buzz Aldrin [wikipedia.org] but it is from the Apollo 11 mission.

That was 40 years ago today… shouldn’t I be able to make one by now?