Saturday, October 24, 2009

Draw your own conclusions

Entrepreneurs in Kunshan, China, 24/10/2009
3G Industry Summit
3G Industry Summit

Entrepreneurs in Brussels, Belgium, 24/10/2009

Lest we forget...
Entrepreneurs in Brussels, Belgium, anno 1911
Solvay Conference
Solvay Conference
(Curie, Poincaré, Rutherford, Einstein, ...)

Friday, October 16, 2009

JavaScript Parser for RFC 3339 or ISO 8601 Timestamp Strings

A few days ago I wrote writing a generator for Atom 1.0 timestamps, which are defined as an RFC 3339 profile, which is defined as an ISO 8601 profile. Now I had to parse these strings in another application for chronological sorting. There are several implementations published already but for various reasons they are all lacking. Either the code base has huge dependencies, licensing is unclear, the implementation contains bugs, and so on. So why not invent a rounder wheel?

This is what I came up with:

Internet Timestamp Parser
Copyright (c) 2009 Sebastiaan Deckers
License: GNU General Public License version 3 or later
Date.prototype.setISO8601 = function (timestamp) {
var match = timestamp.match(
"^([-+]?)(\\d{4,})(?:-?(\\d{2})(?:-?(\\d{2})" +
"(?:[Tt ](\\d{2})(?::?(\\d{2})(?::?(\\d{2})(?:\\.(\\d{1,3})(?:\\d+)?)?)?)?" +
if (match) {
for (var ints = [2, 3, 4, 5, 6, 7, 8, 10, 11], i = ints.length - 1; i >= 0; --i)
match[ints[i]] = (typeof match[ints[i]] != "undefined"
&& match[ints[i]].length > 0) ? parseInt(match[ints[i]], 10) : 0;
if (match[1] == '-') // BC/AD
match[2] *= -1;
var ms = Date.UTC(
match[2], // Y
match[3] - 1, // M
match[4], // D
match[5], // h
match[6], // m
match[7], // s
match[8] // ms
if (typeof match[9] != "undefined" && match[9].length > 0) // offset
ms += (match[9] == '+' ? -1 : 1) *
(match[10]*3600*1000 + match[11]*60*1000); // oh om
if (match[2] >= 0 && match[2] <= 99) // 1-99 AD
ms -= 59958144000000;
return this;
return null;


var foo = (new Date()).setISO8601("2009-10-16T20:11:36.456-07:00");
// Date: Sat Oct 17 05:11:36 UTC+0200 2009

var bar = (new Date()).setISO8601("-0448-05-27T05:52:08.97+11:30");
// Date: Mon May 26 20:51:38 UTC+0200 449 B.C.

This method can parse any RFC 3339 timestamp, but does not enforce strict validity. It can handle dates that are not valid RFC 3339 such as negative years or years with more than four digits. It also accepts lowercase "T" and "Z", as described in ISO 8601, and shows other minor leniencies. Do not use this method as a validator.

Fixed Firefox support.

Fixed offset minutes calculation.

Tuesday, October 13, 2009

Generating RFC 3339 or ISO 8601 Timestamps in JavaScript

I've been working on a generator for a custom Atom 1.0 feed. The Atom 1.0 specification (RFC 4287) requires Internet Timestamps (RFC 3339) which are based on ISO 8601 but these are not supported by the JavaScript Date object. Failing to find a drop-in JavaScript snippet which could generate the necessary timestamp format, I created the following function. It generates the Internet timestamp string from either the current time or a JavasScript Date object passed as an argument.

Internet Timestamp Generator
Copyright (c) 2009 Sebastiaan Deckers
License: GNU General Public License version 3 or later
var timestamp: function (date) {
var pad = function (amount, width) {
var padding = "";
while (padding.length < width - 1 && amount < Math.pow(10, width - padding.length - 1))
padding += "0";
return padding + amount.toString();
date = date ? date : new Date();
var offset = date.getTimezoneOffset();
return pad(date.getFullYear(), 4)
+ "-" + pad(date.getMonth() + 1, 2)
+ "-" + pad(date.getDate(), 2)
+ "T" + pad(date.getHours(), 2)
+ ":" + pad(date.getMinutes(), 2)
+ ":" + pad(date.getSeconds(), 2)
+ "." + pad(date.getMilliseconds(), 3)
+ (offset > 0 ? "-" : "+")
+ pad(Math.floor(Math.abs(offset) / 60), 2)
+ ":" + pad(Math.abs(offset) % 60, 2);

// "2009-10-13T13:34:52.000+02:00"

timestamp(new Date(1983, 4, 9, 11, 5, 17));
// "1983-05-09T11:05:17.000+02:00"

Hope this helps anyone.

Wednesday, August 12, 2009

High Dynamic Range Photography

Yesterday I visited the Bulskampveld provincial domain. It is a forest area with a 19th century chateau that currently acts as nature museum and clinic for injured birds. I took a series of regular photos which are over in my Picasa gallery.

More interesting is playing with my camera's automatic exposure bracketing to create high dynamic range (HDR) photos. Cameras cannot capture accurate information from the brightest to the darkest areas in a single exposure. That is why either shadow areas are fully black or highlights are blown out as completely white. Either a short exposure can provide detail in the bright areas or a long exposure gives detail in the shadows. Now with HDR you can get overall detail from shadows to highlights.

Multiple exposures:

HDR image:

The process:
1. Mount the camera on a tripod or place it on an immobile surface.
2. Take multiple photos at the same ISO and aperture but vary the shutter speed.
3. Merge the photos using HDRI editing software.
4. Tone-map the HDR image into an 8-bit JPEG that can be viewed on screen or printed.

Automatically taking multiple exposures can be done using the camera's auto bracketing feature. Place the camera in aperture priority mode ("Av" on Canon models). Look in the settings menu for automatic exposure bracketing (AEB). This is a screenshot of a Canon 450D and it will be different on other models. Taking the exposures manually allows more control over the range and also lets you combine more than three shots.

Ensure that the camera remains in the same position between exposures. If there is movement of the subject you may also see a ghosting effect when the images are merged.

Store the photos in RAW format. This prevents information loss due to the camera's automatic post processing and JPEG compression.

Several software tools exist to merge and tone-map HDR images. Tone mapping is the process of converting the highly precise image to a lower precision image. This is necessary because monitors cannot handle more than 24 bit pixels: 8 bits each for red, green and blue. Our HDR image contains much more accurate pixel values. In this case 3 exposures of 3 times 14 bits per colour would give 126 bits per pixel. Tone mapping takes a subset of the contained information and renders a simple 24 bit RGB image. There are many different techniques ("algorithms") for determining this subset, each producing a different effect from neutral or realistic to highly stylised.

I tried Photoshop CS2 (File > Automate > Merge to HDR) which is fairly limited. The free and open source Qtpfsgui, despite its tongue twisting name, is much more powerful. It features many different tone-mapping algorithms and precise control over their settings. Keep in mind that this is a highly geeky app. It's a bit of a pain to get it working, the user interface is cryptic and intimidating, and crashes happen randomly.

Example exposures:

Result using Photoshop CS2:

Result using Qtpfsgui with the Mantiuk algorithm:

Saturday, July 11, 2009

My First Firefox Persona

I have found a use for the ludicrously wide panorama, entitled Wall of Ships, that I created last year. It looks nice as the backdrop of my first Firefox Persona.

Firefox Personas are a really neat and simple feature that has come out of Mozilla Labs. It's a way to theme the browser by providing a wide image for the top and bottom of the browser. Very easy and effective. This is a good example of how a simple but well executed feature can have a big impact on user experience.

Tuesday, July 7, 2009

GetSatisfaction Tweaks

The GetSatisfaction discussion boards are a great service. They save me so much time compared to the previous phpBB forum that I was using. However it's their in-page feedback widget that is bothering me. To make it eye catching they've made the feedback tab sticky. When the page is scrolled up or down, the tab remains in place. This is done using the CSS property
background-position: fixed

GetSatisfaction tab widget

Neat as it may be, Firefox (up to an including 3.5) has lousy performance when a fixed element is placed over a background image. Scrolling becomes choppy instead of smooth.

Another problem was its interaction with a jQuery Lightbox plug-in that I've used on the website. It pops up a zoomed in screenshot and dims the rest of the website. Great stuff, but the GetSatisfaction tab was not dimming.

That's why I applied the following tweaks in my own stylesheet:

a#fdbk_tab {
/* Smoother scrolling in Firefox */
position: absolute !important;

/* Stay below Lightbox */
z-index: 50 !important;

The first CSS rule ensures that the tab scrolls with the page while staying in the place when the page is resized.

The second rule puts it below the jQuery Lightbox dimmer but above other elements in the page. If you have other elements on the page with an explicit z-index you may need to tweak this value.

Using the !important modifier ensures that these properties override any other inherited or explicitly defined CSS rules.

Wednesday, July 1, 2009

Chrome Incognito vs Skype

I often use Chrome's porn incognito mode to test how sites look when I'm not logged. This browser mode should access the webserver without sending cookies. But then why is it that Skype's homepage detects me as being logged in?

I suspect Skype's browser plug-in may be messing up and not respecting my privacy. This is why it's best to avoid browser plug-ins and stick to native functionality.

Tuesday, June 16, 2009

Opera Unite: Technology Fail

Today's big tech news is the announcement of also-ran browser company Opera and their Unite service.

The Promise of P2P
The concept sounds interesting enough: Give every client a built-in publishing mechanism so that users don't have to rely on intermediary services. The supposed advantages are plenty: Increased network resilience, lower content distribution costs, infinite horizontal scaling, democratisation of communication, etc.

For example: Micro blogging on your own edge service instead of on a centralised service like Twitter. Your followers receive updates directly from your computer. No more fail whale taking out the entire world's micro blogging.

Wrong Technology
Conceptually that sounds great but Opera chose to implement it using HTTP. They "solved" the problems of NAT/firewall piercing, and keeping content available when your computer goes offline, by building a massive proxy server for the whole world to use. Forgetting the privacy and security concerns, or even the cost of scaling that service, I just can't get over how stupid it is to have a centralised proxy when you're building a decentralised network. Sounds like all they had was a hammer and thought this problem was a nail.

Better Solution
At risk of just choosing a different hammer, I would suggest XMPP as a solution to the P2P problem. Its mix of a distributed federation of servers and out-of-band P2P connections solve a lot of the scaling problems that traditional client-server models have. XMPP comes with a lot of protocol infrastructure already in place which has been thought over and implemented by really smart people. Technologies like Pub-Sub, MUC and Jingle to accomodate many types of applications. Content addressing and discovering is provided already. Authentication, encryption and compression come out of the box. Content can be cached on the XMPP server or distributed through a pub-sub/muc service which has its own history storage.

So come on Opera... join the XMPP revolution! Let's build the real time web on technology that works.

Thursday, June 11, 2009

For Sale - Home Theatre - Location Mumbai

I'm selling my entire home theatre system as I'm leaving Mumbai and sadly cannot carry this with me. All components are in top condition and purchased about 7 months ago, with less than an hour a day of usage. Image and audio quality are as good as new. The new price was about Rs 1,00,000. I'm looking for Rs 70,000 for the entire system but will listen to any reasonable offer. Projector and screen must be sold together. Buyer can collect from Andheri West, Mumbai. Respond quickly: +91 9930358460 /


Sold! Logitech Z-5500
5.1 speakers, 505W RMS total power incl. 187W 10" subwoofer, optical and analog inputs, Dolby/DTS decoder, remote control, speaker cables, spare fuses for the amp
Compatible with computer, gaming console, MP3 player, mobile phone, BluRay/DVD player, TV set top box, ...
Incl. manuals, invoice and receipt from Ezone in Oberoi Mall
Target price: Rs 12,000

Sharp XV-Z3100
720p "HD Ready" projector, Japanese brand
Native resolution 1280x720 pixels
1000 ANSI lumens
6500:1 contrast ratio
Remote control
Input from VGA, HDMI, component, composite, S-video
Compatible with computer, gaming console, BluRay/DVD player, TV set top box, ...
Incl. manuals, invoice and receipt for 3 year local warranty in Singapore (Sim Lim Square)

Projection screen
8x6 feet (4:3 ratio, 120" diagonal)
8x4.5 feet (16:9 ratio, 110" diagonal)
High gain material
Spring mechanism with auto lock
Wall mount hooks included, ceiling mount also possible

VGA cable
15m length, noise-free image at HD resolutions

Target price: Rs 58,000 (projector+screen+cable)