blog dds

2004.09.01

Digital Data Makes Anything Possible

Once data becomes digital anything and everything becomes possible. Consider arranging the books on your bookshelf by the color of their bookcover.

The following Perl script this entry does exactly that, using book cover images obtained from amazon.com. The image on its left is the end-result scaled to 25%. You can see the actual web page here. There are some interesting aspects in the ordering: Knuth's ans Salus's multi-volume works have their volumes appear together; the same is true for four Addison-Wesley titles with a similar cover design. On the other hand, many Prentice-Hall books with the distinctive orange bar on the side, ended up in different rows.

Book covers
#!/bin/perl
# Order the book cover images by color

$rows = 15;

print q{<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE notes SYSTEM "/pub/schema/notes.dtd">
<notes>
};

@img = (glob('*.jpg'), glob('*.gif'));
for $f (@img) {
	($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blocks) = stat($f);
	# Skip unavailable images
	next if ($size < 1000 || $f =~ m/amazon\.gif/);
	# Decode image into PNM
	if ($f =~ m/\.jpg/) {
		system("djpeg $f image.pnm");
	} else {
		system("/app/netpbm/bin/giftopnm $f >image.pnm");
	}
	# Collect color values
	open(IN, 'image.pnm') || die;
	$_ = <IN>;
	$_ = <IN>;
	($x, $y) = split;
	$_ = <IN>;
	$rsum = $gsum = $bsum = 0;
	$n = $x * $y;
	undef $data;
	for ($i = 0; $i < $n; $i++) {
		read(IN, $rgb, 3);
		($r, $g, $b) = unpack('CCC', $rgb);
		$data .= $rgb;
		$rsum += $r;
		$gsum += $g;
		$bsum += $b;
	}
	$rsum /= $n;
	$gsum /= $n;
	$bsum /= $n;
	# Skip duplicates
	next if ($seen{$data});
	$seen{$data} = 1;
	# Calculate saturation and color hue
	$brightness = $maxcomp = max3($rsum, $gsum, $bsum);
	$mincomp = min3($rsum, $gsum, $bsum);
	$saturation = ($maxcomp - $mincomp) / $maxcomp;
	if ($mincomp == $bsum) {
		$hue = 120 * ($gsum - $mincomp) / ($rsum + $gsum - 2 * $mincomp);
	} elsif ($mincomp == $rsum) {
		$hue = 120 * (1 + $bsum - $mincomp) / ($bsum + $rsum - 2 * $mincomp);
	} else {
		$hue = 120 * (2 + $rsum - $mincomp) / ($rsum + $bsum - 2 * $mincomp);
	}
	$row = int($hue / 360 * $rows);
	$brightness{$f} = $brightness;
	push(@{$row[$row]}, $f);
	#print "$f $x $y $row $saturation\n";
}

# Print books in color value rows ordered by saturation
for ($i = 0; $i < $rows; $i++) {
	@r = @{$row[$i]};
	for $f (sort by_brightness @r) {
		$isbn = $f;
		$isbn =~ s/\..*//;
		print qq{<a href="http://www.amazon.com/exec/obidos/ASIN/$isbn/dds-20"><img src="$f" alt="Cover of book with ISBN $isbn" /></a><!--
-->};
	}
	print "<br />\n";
}

print q{
<p /> <p /> <p /> <p />
Cover images obtained from
<a href="http://www.amazon.com/exec/obidos/redirect-home/dds-20">
<img src="amazon.gif" border="0" alt="Amazon.com" /></a><p />
Some cover images and links are related to the current book edition.
</notes>
};

# Sorting function
sub by_brightness
{
	my ($a, $b) = @_;

	return $brightness{$b} <=> $brightness{$a};
}

sub max2
{
	my ($a, $b) = @_;

	return $a > $b ? $a : $b;
}

sub max3
{
	my ($a, $b, $c) = @_;

	return max2(max2($a, $b), $c);
}

sub min2
{
	my ($a, $b) = @_;

	return $a < $b ? $a : $b;
}

sub min3
{
	my ($a, $b, $c) = @_;

	return min2(min2($a, $b), $c);
}

Read and post comments, or share through   


Creative Commons License Last modified: Tuesday, August 31, 2004 2:59 pm
Unless otherwise expressly stated, all original material on this page created by Diomidis Spinellis is licensed under a Creative Commons Attribution-Share Alike 3.0 Greece License.