How to Generate Random Colors Programmatically
Creating random colors is actually more difficult than it seems. The randomness itself is easy, but aesthetically pleasing randomness is more difficult. For a little project at work I needed to automatically generate multiple background colors with the following properties:
- Text over the colored background should be easily readable
- Colors should be very distinct
- The number of required colors is not initially known
Naïve Approach
The first and simplest approach is to create random colors by simply using a random number between [0, 256[ for the R, G, B values. I have created a little Ruby script to generate sample HTML code:
# generates HTML code for 26 background colors given R, G, B values.
def gen_html
('A'..'Z').each do |c|
r, g, b = yield
printf "<span style=\"background-color:#%02x%02x%02x; padding:5px; -moz-border-radius:3px; -webkit-border-radius:3px;\">#{c}</span> ", r, g, b
end
end
# naive approach: generate purely random colors
gen_html { [rand(256), rand(256), rand(256)] }
The generated output looks like this:
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
As you can see this is quite suboptimal. Some letters are hard to read because the background is too dark (B, Q, S), other colors look very similar (F, R).
Using HSV Color Space
Let's fix the too dark / too bright problem first. A convenient way to do this is to not use the RGB color space, but HSV (Hue, Saturation, Value). Here you get equally bright and colorful colors by using a fixed value for saturation and value, and just modifying the hue.
Based on the description provided by the wikipedia article on conversion from HSV to RGB I have implemented a converter:
# HSV values in [0..1[ # returns [r, g, b] values from 0 to 255 def hsv_to_rgb(h, s, v) h_i = (h*6).to_i f = h*6 - h_i p = v * (1 - s) q = v * (1 - f*s) t = v * (1 - (1 - f) * s) r, g, b = v, t, p if h_i==0 r, g, b = q, v, p if h_i==1 r, g, b = p, v, t if h_i==2 r, g, b = p, q, v if h_i==3 r, g, b = t, p, v if h_i==4 r, g, b = v, p, q if h_i==5 [(r*256).to_i, (g*256).to_i, (b*256).to_i] end
Using the generator and fixed values for saturation and value:
# using HSV with variable hue
gen_html { hsv_to_rgb(rand, 0.5, 0.95) }
returns something like this:
Much better. The text is easily readable, and all colors have a similar brightness. Unfortunately, since we have limited us to less colors now, the difference between the randomly generated colors is even less than in the first approach.
Golden Ratio
Using just rand() to choose different values for hue does not lead to a good use of the whole color spectrum, it simply is too random.

Here I have generated 2, 4, 8, 16, and 32 random values and printed them all on a scale. Its easy to see that some values are very tightly packed together, which we do not want.
Lo and behold, some mathematician has discovered the Golden Ratio more than 2400 years ago. It has lots of interesting properties, but for us only one is interesting:
[...] Furthermore, it is a property of the golden ratio, Φ, that each subsequent hash value divides the interval into which it falls according to the golden ratio!
-- Bruno R. Preiss, P.Eng.
Using the golden ratio as the spacing, the generated values look like this:

Much better! The values are very evenly distributed, regardless how many values are used. Also, the algorithm for this is extremly simple. Just add 1/Φ and modulo 1 for each subsequent color.
# use golden ratio
golden_ratio_conjugate = 0.618033988749895
h = rand # use random start value
gen_html {
h += golden_ratio_conjugate
h %= 1
hsv_to_rgb(h, 0.5, 0.95)
}
The final result:
You can see that the first few values are very different, and the difference decreases as more colors are added (Z and E are already quite similar). Anyways, this is good enough for me.
And because it is so beautiful, here are some more colors ![]()
s=0.99, v=0.99, s=0.25, h=0.8, and s=0.3, v=0.99
Have fun!
Martin
How To: Download Any Flash Video with flashrip in Ubuntu
Downloading flash videos in Linux was already not too difficult, but thanks to flashrip, it has gotten very easy. Here is a little demo how it works:
Once installed, you basically use one click to get a video preview and then a prompt with the filename to save the file. The script works by looking into the newest flash files in your /tmp folder, and creates a hardlink to the save destination. When the video has fully loaded, you can close the browser window. The temp file will get deleted, and the linked copy will remain.
Installing flashrip
Open a terminal like gnome-terminal or konsole, and run these commands:
wget http://martin.ankerl.com/wp-content/uploads/2009/11/flashrip.sh chmod 755 flashrip.sh sudo mv flashrip.sh /usr/local/bin
Now all thats left to do is to create a link in your gnome panel for ease of use: Right click the gnome panel, “Add to panel…”, choose “Custom Application Launcher…”. Choose a proper name, and a command like this:
/usr/local/bin/flashrip.sh /home/manker/Videos
For the command, replace the second parameter with the default location where you want to save the ripped videos (you have to use the full path here!)
I have tested this in Ubuntu, but it should work on any linux where gnome is installed.
Have fun!
Ripping Multilanguage DVDs with Subtitles using Mencoder
Yesterday at Christmas I got the Akira Kurosawa Samurai Edition, which is a 7 disc DVD set of his awesome movies. I am converting it into the best quality files currently possible: MKV as the container, x264 codec for the video, dual audio, and with subtitles. This is short Howto so that I won’t forget how ![]()
Read more
How to Make a Compact Gnome Theme
The themes Human Compact and Clearlooks Compact have been quite a success, and I got several requests to make a tutorial on how to create such a compact theme.
UPDATE: Human Compact Theme for Ubuntu 8.10 (Intrepid Ibex) is available!
Well, it is a bit difficult to create a step-by-step tutorial, but I will try anyways. Prepare to fiddle around with your configuration and try it out several times until you get the desired results.
- All your Gnome themes are located under /usr/share/themes. Find the theme of which you want to create a compact one, and copy it into your home directory with e.g.
cp -r /usr/share/themes/Human ~/.themes/Human-Compact
- If there is a file index.theme, open it and change all the names (e.g. add “Compact” where appropriate). This file is necessary if you want to directly choose the theme from the Appearance Preferences; if it is not available you have to choose a theme and select “customize” to select the compact controls for it.
- Now to the fiddling part. Open gtk-2.0/gtkrc, and change lots of thickness and width settings… When you do this, always check how your changes work visibly, e.g. if the application still have usable borders etc. To help with the fiddling, I have added a diff of the Human vs. the Compact theme, you might be able to reuse some of the settings there.
- Once you are satisfied with your theme, you can create a .tar.bz2 distribution for backup or to be used by others, e.g. with this command:
cd ~/.themes tar cjvf ~/Human-Compact.tar.bz2 Human-Compact
- That’s it. Have fun with your theme!
Logical Volume Manager Cheatsheet
Today I got a new harddisk, so it was finally time for me to have an in depth look at LVM. I use it to combine two harddisks /dev/sdg1 and /dev/sdb1 into one volume group ext_vg which contains one big logical volume /dev/ext_vg/ext. In short, my 250GB and 500GB harddisks are used in one big 750GB ext3 mount point.
I followed the excellent LVM Tutorial, and was surprised how easy everything goes. Here is a short cheat sheet of the important commands (take care to exchange the partition/volume names if you use this):
Installation
I use Ubuntu, so this is a piece of cake:
sudo apt-get install lvm2
There is also a GUI available, but I found the command line tools are very easy to use so there is no real need. I wouldn’t use EVMS as it is not supported in Ubuntu 7.10 and may cause problems.
Create a New Filesystem
First I create the physical volume on the partition sdg1, create a new volume group ext_vg that contains this physical volume, and create a new logical volume of size 450GB within the volume group. Finally create the filesystem (disabled reservation space, see Get More Space Out of Your ext3 Partition).
sudo pvcreate /dev/sdg1 sudo vgcreate ext_vg /dev/sdg1 sudo lvcreate -L 450G -n ext ext_vg sudo mkfs.ext3 -m 0 /dev/ext_vg/ext
Show Status
Each LVM layer has its corresponding command to get information about the metadata:
sudo pvdisplay sudo vgdisplay sudo lvdisplay sudo pvs sudo vgs sudo lvs
Mount via fstab
I use the filesystem mainly for data, so allowing just rw is enough (no executables allowed). noatime allows quicker access.
sudo mkdir /media/mega /dev/ext_vg/ext /media/mega ext3 rw,noatime,user 0 2 mount /media/mega
Resize
It is even possible to do an online resize of the system, wohoo
This extends the logical volume by 200MB.
sudo lvextend -L +200 /dev/ext_vg/ext sudo resize2fs -p /dev/ext_vg/ext
You can watch the resize process going on with df -h.
Add Another Partition to the Logical Volume
To add another partition and use up all the available space in the logical volume, first add the physical volume to the volume group, then use pvdisplay to find out the total available number of free PE (add the numbers from the physical volumes), then use lvextend to use up all this available space.
sudo pvcreate /dev/sdb1 sudo vgextend ext_vg /dev/sdb1 sudo pvdisplay sudo lvextend -l +63602 /dev/ext_vg/ext sudo resize2fs /dev/ext_vg/ext
That’s it! Any questions? please post.