Thursday, April 16, 2009

Comparing images pixel for pixel on the linux command line

There's an old file format called ppm that stores an image as a very simple, very large text file. Unfortunately, there are several types of ppm images, without even getting into the pgm and pbm images which form the rest of the pnm family of image formats.

The Wikipedia netpbm article gives more details on how the family of formats work.

The P3 ppm (sometimes called "ascii ppm" or "plain ppm") image is most useful. It's surprisingly simple, and I've often implemented it by hand in C when I got sick of trying to make an image library work and just needed to get pixels into an image. It's also useful for pixel-by-pixel comparisons:

Let's say you have two images, a.png and b.png, and you want to know if the pixels differ at all between the two images. You could use gimp to subtract them and then tweak the histogram to hilight the differences, but it's slow going.

Instead, you can convert them to P3 ppm files and use diff to compare:

(-compress none tells the ImageMagick convert utility to produce a P3 ppm)
$ convert a.jpg -compress none a.ppm
$ convert b.jpg -compress none b.ppm
$ diff a.ppm b.ppm > differences
$ head differences
< 58 61 58 58 61 58 58 60 58 58 60 58
> 58 60 58 58 60 58 58 60 58 58 60 58

So, 13000 lines into the files, we see that a 61 has become a 60, and that it does so again the next pixel over. (These files have lines with 4 pixels each. In the above output, a.ppm had (rgb values) (58,61,68), (58,61,68), (58,60,58), (58,60,58), for example. So b.ppm differed by a single bit in the green channel in two adjacent pixels.)

No comments: