开发者

How to extract a pixel from a png file using c++?

Is there an image library available that allows a user to extract pixels from a png file that has been loaded onto disk without decompressing it?

So I have 100k 8bit images of size 512x512 where each one is about 10kb when in png format. This means that I would only need 1GB of RAM to store all the images at runtim开发者_如何学JAVAe for a program Im writing.

Is it possible to efficiently retrieve pixels from an image like this? I.e. lets say I have an array images where images[i] references a png image that has been loaded but not uncompressed to RAM (is this what happens when you load a png image?)

Then ideally I would like to write something like

pixel = images[i].getPixel(x,y);

Anyone know if this is possible? Which library? Where my assumptions are false?


I don't think you'll be able to get a pixel without decompressing at least the preceding part of the image. When you open a file, it will just point to the compressed data on disk. When you run it through a PNG library, it will be decompressed.

Your best bet, I think, and the canonical library for reading and writing PNGs, is libpng. It provides great low-level access to image data and metadata, and is probably going to be the fastest/most efficient option. It allows you to decompress the data row by row (and perhaps chunk by chunk--I can't remember), so you can probably decompress until you get your pixel, then toss the decompressed data and move to the next image.

The downside is that it's probably not as programmer friendly as some other options. The documentation is comprehensive to the point of being tedious, IMO, but there may be simpler tutorials out there. On the other hand, you'll probably need all the details in the manual to accomplish what the minimal decompression you're going for. It will also help explain the PNG file format so you can better manage data down to the chunk level.


I don't think what you are asking is practical. Fortunately, it is also unnecessary, as long as you don't keep all the uncompressed pictures in memory at the same time.

Can't you simply (load and) decompress on demand and then release the memory as soon as it is no longer necessary?


First off, I'm not sure I understand your requirement about not decompressing the image into RAM...

While it might be more library than you are looking for, the Cinder library would allow you to easily load images and iterate over the pixels with the Surface class.

Here is a great tutorial on how to do so:

http://libcinder.org/docs/v0.8.3/guide___images.html


I think the best you can do with these requirements is to have all the PNGs compressed in memory (about 1GB as you indicated), and only decompress one at a time when you want to obtain pixels from it. The buffer size of a decompressed 512x512 8-bit grayscale image is 256KB. If the images are RGB, then the size is 768KB. If you also have an alpha channel then the size will be 1MB.

You can find a very lightweight and simple library that decompresses PNGs here.

If you wanted to hide the fact that images are compressed in memory, you could put the compressed PNG data inside an image class. A getPixel(x, y) method in this class will trigger the decompression if the image is compressed. Class members in this class can keep track of what image has been decompressed, and when another image needs to be decompressed the previous one can drop its decompressed buffer.

The only problem you may have with a solution like this is that the system can thrash if you iterate over your 100K images asking for just one pixel, then move to the next pixel. To avoid this, you will need to get all the info you need from a single image, then move on to the next image.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜