views:

53

answers:

4

I need to write some code which will operate on a number of pixel formats (eg A8R8G8B8, R8G8B8, R5G6B6, and even potentially floating point formats).

Ideally I would like to not have to write each function for each format since that is a massive amount of near identical code.

The only thing I could think of is some kind of interface letting it deal with pixel format conversions eg:

class IBitmap
{
public:
    virtual unsigned getPixel(unsigned x, unsigned y)const=0;
    virtual void setPixel(unsigned x, unsigned y, unsigned argb)=0;
    virtual unsigned getWidth()const=0;
    virtual unsigned getHeight()const=0;
};

However calling a virtual function for every get or set pixel operation is hardly fast, since not only is there the extra overhead of a virtual call, but it also far more importantly prevents inlining for something which is just a few instructions long.

Are there any other options which would allow for me to support all these formats efficiently? Generally speaking my code is likely to only operate on a small portion of the bitmap, and needs read/write access in many cases (blending).

+1  A: 

Consider using templates. This will allow you to write generically where possible and take the hit for specialising the code at compile time

Sometimes known as static polymorphism. http://en.wikipedia.org/wiki/Curiously_Recurring_Template_Pattern

morechilli
+1  A: 

You may consider Adobe Generic Image Library (GIL). Disclaimer: I have not used it before.

Typically, it may be unavoidable to convert a portion of the image into a common-denominator format such as R8G8B8 or R8G8B8A8 (or their 16-bit equivalents) in order to perform any kind of image operation, and then convert the results back to the desired format. This is true even for highly-optimized vectorized imaging libraries. The reason has to do with CPU caching.

On Windows you can consider Windows Imaging Component. On Linux, try FreeImage.

rwong
Another great library for that purpose is [Vigra](http://hci.iwr.uni-heidelberg.de/vigra/) which is a bit older than GIL, but comes with many sophisticated image processing algorithms.
Fabio Fracassi
A: 

On modern processors virtual functions are pretty darn fast, so I'm not sure I'd reject them out of hand. Run a timing test or two to be sure. Virtual functions give you runtime polymorphism, which allows you to conceivably write (or generate at compile time) less code. The static polymorphism represented by templates will probably cause the compiler to generate that massive amount of code that you're trying to avoid.

gregg
Setting a pixel is such a tiny amount of work that the overhead of calling a virtual function (or even ordinary function) is roughly the same or larger magnitude than the work of the function itself. Especially if you call SetPixel half a million times to cover a surface, you could be wasting half or more of that time on function call overhead. Yes, virtual functions are fast, but not for a setpixel function.
AshleysBrain
A: 

To avoid having to write loads of formats, write a Color class or similar that always stores a particular format (eg. A8R8G8B8 or A32R32G32B32F) then have methods on that class to retrieve in different formats, eg. get(FORMAT_R5G6B6) or similar. All your methods can then deal with that class. Whenever possible, convert the color only once (eg. when drawing a rect, convert the rect color to the destination format then write that to all the pixels - don't convert it for every pixel!).

Avoid having a SetPixel/GetPixel method at all. It cannot be done efficiently, especially if you're doing colour conversions on the fly, and especially not if the optimizer decides not to inline the calls. You'd do better to expose memory buffers directly, and trust that the caller will correctly use the memory. That's how every other API I've used before does it.

AshleysBrain