This blog post was originally a lightning talk I gave at the Guardian as I was beginning to use Scala and the Play framework.
Imagine you are working in a department that is producing Play apps at a rate of knots. Without careful planning you can end up with a whole row of identical looking tabs in which you can’t distinguish one app from another.
![]()
Using the Guardian favicon doesn’t really help that much either…
![]()
One approach to create an easily identifiable favicon would be to modify an existing favicon in Photoshop or GIMP. However I am neither rich enough to own Photoshop nor have a mind that is twisted enough to use GIMP. Clearly the answer is to write some scala code:
val favicon = ImageIO.read(new File("src/favicon-blue.png"))
val inputPixels = for {
x <- 0 until favicon.getWidth
y <- 0 until favicon.getHeight
} yield Pixel(favicon.getRGB(x,y))
val sortedPixels = inputPixels.distinct.sorted
val paletteSize = 4
val darkest = sortedPixels.head.luminance - 20 // fudge factor
val lightest = sortedPixels.last.luminance
val range = darkest to lightest by ((lightest - darkest) / (paletteSize - 1))
val colourPalette = range.map{ Pixel.luminance(_) }
val remappedPixels = inputPixels.map { pixel =>
colourPalette.reduceLeft { (result, elem) =>
if (result.compare(pixel) < elem.compare(pixel)) {
result
} else {
elem
}
}
}
val distinctPixelCounts = remappedPixels.distinct.sorted.map{ pixel =>
pixel.luminance -> remappedPixels.count(pixel ==)
}
val outputImage = new BufferedImage(width, height, TYPE_INT_RGB)
for {
x <- 0 until favicon.getWidth
y <- 0 until favicon.getHeight
} {
val pixel = remappedPixels.get(x * 16 + y)
outputImage.setRGB(x, y, pixel.rgb)
}
ImageIO.write(outputImage, "png", new File("output-new.png"))
println(s"Distribution of remapped pixels (palette of $paletteSize):")
println(distinctPixelCounts.map{ case (lum, count) => s"Luminance: $lum Count: $count" }.mkString("\n"))This code reads an existing favicon and converts it into a greyscale image with a smaller palette size. It’s not particularly pretty code but this what happens when we pump in the Guardian favicon:
![]()
Why stop there?! Let’s write some increasingly ridiculous Scala code:
import sihil.baking._
val ediblePixels = remappedPixel.map { pixel =>
new EdiblePixel(pixel.luminance)
}
val ingredients = List(flour, chocolate, egg, sugar,
moreSugar, moreChocolate, bakingSoda)
val cake = new ChocolateCake(ingredients).baked()
cake.decorate(outputImage, ediblePixels)So what does that look like when you run it? Well let’s start with the edible pixels. Using dark, milk and white chocolate (plus a mix) we can create four different tones of chocolate. When spread thinly and cut into one centimeter squares with a pizza cutter you get something that looks a little like this:
![]()
Next we need to bake a cake and make sure we’ve got enough pixels of each type of chocolate.
![]()
And, having not built a robot for the task, we’ll also need a grid to work from.
![]()
In order to start laying down the pixels we go from the middle outwards. First step is to mark the centre and then mark the center lines in both the x and y direction. Next pixels are individually laid onto the still warm chocolate icing, partially melting as they go on.
![]()
Some time later (really quite a long time later, it’s dark now) it is beginning to take shape and the technique of placing pixels has been mastered.
![]()
The final cake is carefully photographed directly from above. and then turned into a lower resolution icon suitable for being a favicon.
![]()
It is carefully masked.
![]()
Finally the resolution is reduced so it is suitable for being a favicon.
![]()
As you can now see we have now created a recognisable favicon for our new application. The hard way.
![]()
The finished cake was shipped into the office and tasted pretty much as good as it looked…