Direct access to a single pixel using Python

Issue

Is there any way with Python to directly get (only get, no modify) a single pixel (to get its RGB color) from an image (compressed format if possible) without having to load it in RAM nor processing it (to spare the CPU)?


More details:

My application is meant to have a huge database of images, and only of images.

So what I chose is to directly store images on harddrive, this will avoid the additional workload of a DBMS.

However I would like to optimize some more, and I’m wondering if there’s a way to directly access a single pixel from an image (the only action on images that my application does), without having to load it in memory.

Does PIL pixel access allow that? Or is there another way?

The encoding of images is my own choice, so I can change whenever I want. Currently I’m using PNG or JPG. I can also store in raw, but I would prefer to keep images a bit compressed if possible. But I think harddrives are cheaper than CPU and RAM, so even if images must stay RAW in order to do that, I think it’s still a better bet.

Thank you.

UPDATE

So, as I feared, it seems that it’s impossible to do with variable compression formats such as PNG.

I’d like to refine my question:

  • Is there a constant compression format (not necessarily specific to an image format, I’ll access it programmatically), which would allow to access any part by just reading the headers?
  • Technically, how to efficiently (read: fast and non blocking) access a byte from a file with Python?

SOLUTION

Thank’s to all, I have successfully implemented the functionality I described by using run-length encoding on every row, and padding every row to the same length of the maximum row.

This way, by prepeding a header that describes the fixed number of columns for each row, I could easily access the row using first a file.readline() to get the headers data, then file.seek(headersize + fixedsize*y, 0) where y is the row currently selected.

Files are compressed, and in memory I only fetch a single row, and my application doesn’t even need to uncompress it because I can compute where the pixel is exactly by just iterating over every RLE values. So it is also very easy on CPU cycles.

Solution

If you want to keep a compressed file format, you can break each image up into smaller rectangles and store them separately. Using a fixed size for the rectangles will make it easier to calculate which one you need. When you need the pixel value, calculate which rectangle it’s in, open that image file, and offset the coordinates to get the proper pixel.

This doesn’t completely optimize access to a single pixel, but it can be much more efficient than opening an entire large image.

Answered By – Mark Ransom

Answer Checked By – Willingham (AngularFixing Volunteer)

Leave a Reply

Your email address will not be published.