Search code examples
c++performanceimage-processingdata-structuresmemory-efficient

What would be an ideal data structure to represent an image matrix?


As I'm doing a computer vision library, I wondered what would be the ideal data structure to save an image's data.

Someone told me that doing an std::vector imbrication is pretty bad since data contiguity isn't guaranteed, thus a simple one is more efficient.

Problem is, the vector's content has to be colorspace-dependant. Plus, for size issues it would be best to have an unsigned char per channel, though I'd be better off having floats to perform operations.

To handle colorspaces, should I increase the size of the vector (like tripling it to handle RGB), so I could access data like this:

data[0] => pixel 1, Red
data[1] => pixel 1, Green
data[2] => pixel 1, Blue
data[3] => pixel 2, Red
data[4] => pixel 2, Green
... etc

Or is it possible to do this more efficiently (like using a long int or a float to keep all channel's values into one single variable) and if so, how? How could I make this generic to handle 1, 2, 3 or 4 channels so that I can change colorspace (relatively) easily?

The question is not about the container (I am using a single std::vector already), but the content itself.

EDIT: Since this question has been marked as primarily opinion-based, I will try to make it clearer.

At the moment, I'm storing an image's data in a std::vector<float>. The problem here is that I don't know how many items to store (e.g. 3 times the size to handle RGB/HSV, or implementing a 4-items struct (RGBA) even when I'm only using one (grayscale)?) in order to efficiently change colorspace or perform operations on matrices when I need to. As this is meant to be integrated in a computer vision library, it is highly likely to happen at least once every frame.

I'm asking for something efficient in my case here, which has nothing (or very little) to do with opinion. There could be several good answers and chosing among them relies on opinion, but this is supposed to be my call.


Solution

  • What is the "best" data structure for an image data highly depends on what kind of operations you want to perform on the image, and mostly on what operations you want to have optimized performances.

    Usually a std::vector of bytes can be enough (for the whole image, not a vector for each single line); a vector guarantees that data is stored in a contiguous block of memory, which may or may not fit your use cases (i.e. it doesn't if you need to manage strides longer than scanlines).

    If you need more fine-grained access to the pixelformat information (i.e. single color components), you may want to use a custom defined structure for pixel representation.

    Also, data structure may be more complex depending on which kind of images you need to manage. I.e. are you limited to 1 or a few pixelformats? Are you limited to "packed" images (sequential color components in 1 "plane") or do you need to manage also "planar" images (multiple "planes", one for each color component)?

    You may also look at some available graphics libraries on the web.
    One that (in my opinion) has an interesting pixel components management (with custom iterators and other facilities) is Boost GIL