Rendering image with div tags using Javascript

As I was trying to figure out how to protect image files from being copied; I thought: Why not render them as a bitmap using <div> tags? After a bit of searching I couldn’t find any project that does this, although there are plenty of examples that use html to draw images on the page. A good one that I like is Google Pacman. The closest “implementation” I found was to use the html5 canvas tag. But that wouldn’t work for my purposes because you can right click on it and save it as an image.

Working buttom-up, I wrote the code that reads a JPEG image pixel by pixel and feeds it to the browser. Executing the below code will print the number of horizontal pixels in the image (space separator), followed by the number of vertical pixels (space separator) then followed by 6 character hex codes (no delimiters) representing the color of each pixel from left to right.

$im = imagecreatefromjpeg('test.jpg');

$sx = imagesx($im);
$sy = imagesy($im);

$colors = array();
$num_colors = 0;
echo $sx . ' ' . $sy . ' ';
for ($y = 0; $y < $sy; $y++){
    for ($x = 0; $x < $sx; $x++){
        $color = imagecolorat($im, $x, $y);
        $r = ( $color >> 16 ) & 0xFF;
        $g = ( $color >> 8 ) & 0xFF;
        $b = $color & 0xFF;
        printf("%'02X%'02X%'02X", $r, $g, $b);

This is grossly inefficient. A 10.4 KB JPEG turns into 241.41 KB. There are a number ways to makes this more efficient, like echoing out $r, $g, and $b values to the screen as characters (they’re 8 bits after all) then building the hex value in Javascript. In that case you get other issues like characters that you aren’t really supposed to use (e.g. null string).

I used GD to generate the colors from the image. I would have preferred ImageMagick; it looks like the PixelIterator would be more efficient. But my webhost doesn’t have the php extension (shamefully I don’t have it installed on my computer either). Either way you only need to generate the colors file once then can statically feed it to the renderer.

The rendering code is fairly basic. Assuming the above color data is loaded into the variable data then the result will be an imgdiv variable containing a DOM div element with the entire image rendered in divs.

var i = 0;
var sx = '';
var sy = '';
var ca = data.charAt(i);
while( ca != ' '){
	sx += ca;
	ca = data.charAt(++i);
sx = parseInt(sx);
ca = data.charAt(++i);
while( ca != ' '){
	sy += ca;
	ca = data.charAt(++i);
sy = parseInt(sy);
var color = '';
var imgdiv = document.createElement('div');
for(var y = 0; y < sy; y++){
	for(var x = 0; x < sx; x++){

		for (var j = 0; j < 6; j++){
			color += data.charAt(++i);

		var newdiv = document.createElement('div');
		newdiv.setAttribute('style', 'background-color:#'+color);
		newdiv.setAttribute('class', 'r');
		if (x == 0) {
			newdiv.setAttribute('class', 'r fp');
		else {
			newdiv.setAttribute('class', 'r');
		color = '';

Styles that I used to force the images to be 1 pixel:

div.r {
	width: 1px;
	height: 1px;
div.fp {

So… did it work? Short answer is yes, but it takes so much processing power for the browser to render it that it makes the process not worth it. You can see for yourself: render.html It takes me a notch less than 10 seconds to load & render that page, it may crash your browser if you’re running on a slow machine. This probably can be optimized, but the image is only 206×200. I hate to think what happens at 400×400 when there are 4 times as many pixels to render.

The real bottleneck is the browser, it’s not made to display thousands of 1 pixel <div> tags. With a sigh, I thought of a next idea: Why not split the jpeg into many other jpegs (say, 1 image into 100) then load them next to each other? This naturally follows: Why not scramble the image, like this puzzle, then use background position style to reassemble back on the page? Although not as cool as rendering everything in JS, this may provide some level of deterrence against image copying. I’ll make another post if I implement this idea.

Installing Firetray in Thunderbird 6

After installing Mozilla Thunderbird 6 I quickly discovered that one of my favorite add-ons was no longer working. Firetray is listed as incompatible with Thunderbird 6 but after searching around I discovered that it worked for some people after they compiled it from source.

Searching around in the build files revealed that the add-on needs a version bump to properly install. Once I changed the max version number and compiled the add-on it worked flawlessly!

You can download my x86_64 build or follow the steps below to compile it on your PC. The patch file (in the steps below) will bump up the version number. Compiling the add-on requires you to have gecko-sdk and scons already installed on your system.

mkdir firetray
cd firetray
wget ""
unzip ""
wget ""
patch firetray-thunderbird6.patch

IDEA: automatically untag facebook photos

Perhaps this will never reach implementation stage, but here’s a nifty idea: automatically untag yourself from facebook photos. I remember the photo tags section of the API having a delete function. It looks like this is no longer the case. So I can’t exactly put this in a script to run as a cron job.

However we can still probably scrape the page and click the link programmatically. First step would be to query the facebook photo tag API and get a list of photos where you’re tagged. The list contains a link to each photo in facebook. From here we have to options.

  1. Click on the “remove tag” button and record the http request. Reverse engineer it to see if we can replay with with a unique ID of another photo. If that is the case then great, the only thing that’s stopping us are session cookies.
  2. Option 2 is just to click “remove tag” button via some software. People already had ideas like that but the testing software package Selenium comes to mind. It can find the “remove tab” by itself and click it.

I was about to implement this idea, but realized that my privacy settings already allow only me to see photos that I’m tagged in. So this effort would be for vanity since people can’t see my photos anyway.

If any of you would actually like to see this done hit my up on twitter @pavel987 and I’ll probably be motivated enough to write it.

Gingerbread on my Droid 1

Today I finally decided to screw around with my android phone and put a custom ROM on it. I had played around with the SDK before but haven’t actually done anything with the phone. I read on droid-life that Peter Alfanso made a gingerbread ROM for Droid 1 and I wanted to try it out.

First step was to root my phone; the rageagainstthecage exploit worked really well. I followed instructions directly from except the paths. For those of you using Gentoo, the adb path is


after you have installed the android-sdk-update-manager package. If you’re installing package from fresh, then you also need to download the sdk tools and a platform api from within the sdk. Basically just run:


After that you can just go to the android market and download ROM Manager. It requires root access, so the step above is necessary. With ROM manager you can install clockwordmod recovery and finally flash Gingerbread onto your Droid 1 (you DID already download the rom .zip file onto your sd card, right?).

The original reason I wanted to play around with Gingerbread was for the integrated SIP support. If I set my phone to receive calls from my Gizmo account, and set my google voice number to forward to both my SIP account and my cellphone. What happens when someone calls? 🙂

Unfortunately I was rather disappointed at the SIP calling. The audio was really choppy and sometimes didn’t work at all. There’s also a warning that receiving SIP calls drains your battery 🙁

FATAL: Error inserting w83627ehf

It was many months ago that lm_sensors stopped working and only recently have I decided to investigate. I have an Asus P5Q-E board with a Winbound w83627ehf chip.

When attempting to insert it, I got the following error:

Turm ~ # modprobe w83627ehf
FATAL: Error inserting w83627ehf (/lib/modules/2.6.36-gentoo-r3/kernel/drivers/hwmon/w83627ehf.ko): Device or resource busy

Investigating this further we find that there’s a conflicting ACPI driver.

Turm ~ # dmesg | tail
[fglrx] Reserved FB block: Unshared offset:f921000, size:3df000 
[fglrx] Reserved FB block: Unshared offset:3fff4000, size:c000 
NET: Registered protocol family 10
lo: Disabled Privacy Extensions
ADDRCONF(NETDEV_UP): eth1: link is not ready
sshd (5426): /proc/5426/oom_adj is deprecated, please use /proc/5426/oom_score_adj instead.
eth0: no IPv6 routers present
w83627ehf: Found W83667HG chip at 0x290
ACPI: resource w83627ehf [io  0x0295-0x0296] conflicts with ACPI region HWRE [io  0x0290-0x0299 pref]
ACPI: If an ACPI driver is available for this device, you should use it instead of the native driver

After googling around a bit, it turns out that after kernel 2.6.31 they deprecated the use of sensor chip modules in favor of ACPI drivers when they’re available. To get your sensors back you need to use the asus_atk0110 acpi driver. You need to make sure it’s compiled into your kernel and lm_sensors is at least version 3.1.0. Then just issue

modprobe asus_atk0110

and everything should work. There is no need to rerun sensors-detect because lm_sensors is no longer involved in loading proper sensor modules.

Then you may want to adjust the lm_sensors startup script to load proper modules. On Gentoo look at /etc/conf.d/lm_sensors and change any instance of w83627ehf to asus_atk0110


MultiWord is a program I wrote WAY back in High School to speed up the mundane process of defining words for English class. Basically you can define multiple words at once. Just put in a comma separated list of words and press Define.

Download MultiWord The file is about 25 megabytes because it contains an English WordNet dictionary.

It’s a standard Java project that should run on JRE 1.4 or higher. You probably already have a java virtual machine installed (who doesn’t?) but just in case here’s a link: To run the Jar file you can look up instructions on wikiHow.

I’m fairly sure this program is no longer needed, but if someone finds it useful then contact me. If I know someone uses it then I’ll add more features and just generally make the program better/simpler.


Hello all Whitespace enthusiasts!

Here you can find information about my whitespace endeavor.

This is a whitespace interpreter written in C++, it has a little more features than the original interpreter written by Edwin Brady. I wrote this because I wanted a bit of C++ practice and had some free time over the summer. You can find out more information about the original idea on the whitespace website.


I used type long to represent all the stored data and memory. This means that if you try to store a number greater than LONG_MAX it will wrap around and be negative. Same goes for memory, you can’t address memory higher than LONG_MAX. Hopefully this won’t impede on any programs, although the factorial program hits its limit at 25! 🙁


Download the source
Download the x86_64 binary

Everything is GNU/GPL of course!

I realize that I have almost no documentation about it posted right now. If anyone wants to know the specifics, I’m on the whitespace mailing list. You can reach me from there. Please ask if you have questions, it will encourage me to put up more documentation.

Keeping a Desktop & Laptop in Sync

This post is tagged as backlogged, so the stuff I’m writing here isn’t exactly “new”. Anyway a few years ago (2) I became an owner of a 12″ laptop which was useful to take to class but needed to be constantly synced with my desktop.

Fortunately Gentoo had Unison in its repository. This program works very well and presents a graphics merge window when conflicts arise. After searching for a Sync solution for a while, this is the best that I could find. Emerging unison on Gentoo gets you an executable with a version number to it. A quick

ln -s /usr/bin/unison-2.27 /usr/bin/unison

fixes that inconvenience.

Below is an example unison config in case anyone finds it useful. I saved the file as default.prf in the unison directory.

# Unison preferences file
root = /home/cogent
root = ssh://Turm
# Paths that I want to sync

path = my_stuff
path = school
path = workspace
#path = work
path = .ssh
path = .purple
path = .gnupg
#path = .thunderbird
path = archive/music

ignore = Name *~
ignore = Name .purple/status.xml
ignore = Path .purple/accels
ignore = Name .purple/blist.xml
ignore = Name .purple/prefs.xml
ignore = Name .purple/accounts.xml

log = false
height = 40

Having done that, running

unison default

resulted in a purely automatic sync. To get the process as smooth as possible, you should add your ssh keys to the respective machines. That way you won’t be asked for the password each time. Also, be sure to connect to the machine at least once before connecting with unison. If I remember correctly, it doesn’t present the “add this machine to know ssh hosts” dialog correctly. Possibly resulting in a silent failure.