I am using the Python Imaging Library to colorize a black and white image with a lookup table that defines the color relationships. The lookup table is simply a 256-element list of RGB tuples:
>>> len(colors)
256
>>> colors[0]
(255, 237, 237)
>>> colors[127]
(50, 196, 33)
>>>
My first version used the getpixel()
and putpixel()
methods:
for x in range(w):
for y in range(h):
pix = img.getpixel((x,y))
img.putpixel((x,y), colors[pix[0]])
This was horribly slow. A profile
report pointed to the putpixel
and getpixel
methods as the culprits. A little investigation (i.e, read the docs) and I find "Note that this method is relatively slow." re: putpixel
. (actual runtime: 53s in putpixel
and 50s getpixel
for a 1024x1024 image)
Based on the suggestion in the docs, I used im.load()
and direct pixel access instead:
pixels = img.load()
for x in range(w):
for y in range(h):
pix = pixels[x, y]
pixels[x, y] = colors[pix[0]]
Processing sped up by an order of magnitude, but is still slow: about 3.5s to process a 1024x1024 image.
A more thorough study of the PIL docs seems to indicate Image.point()
is exactly intended for this purpose:
im.point(table)
=> image
im.point(function)
=> imageReturns a copy of the image where each pixel has been mapped through the given table. The table should contains 256 values per band in the image. If a function is used instead, it should take a single argument. The function is called once for each possible pixel value, and the resulting table is applied to all bands of the image.
I've spent some time hacking around with the interface, but can't quite seem to get it right. Forgive my ignorance, but PIL's docs are curt and I don't have much image processing experience. I've googled around a bit and turned up a few examples, but nothing that made the usage "click" for me. Thus, finally, my questions:
- Is
Image.point()
the right tool for this job? - What format/structure does
Image.point()
expect the table? - Can someone rough out an example implementation? Every iteration I've tried so far has ended up with a straight black image.