I'm working with general purpose image rendering, and high-performance image processing, and so I need to know how to store bitmaps in-memory. (24bpp/32bpp, compressed/raw, etc)

What is the "usual" or "normal" way to store bitmaps in memory? (in C++ engines/projects?)

How to store bitmaps for high-performance algorithms, such that read/write times are the fastest? (fixed array? with/without padding? 24-bpp or 32-bpp?)

How to store bitmaps for applications handling a lot of bitmap data, to minimize memory usage? (JPEG? or a faster [de]compression algorithm?)

I'm not working with 3D graphics or DirectX / OpenGL rendering and so I don't need to use graphics card compatible bitmap formats.

Some possible methods:

  • Use a fixed packed 24-bpp or 32-bpp int[] array and simply access pixels using pointer access, all pixels are allocated in one continuous memory chunk (could be 1-10 MB)

  • Use a form of "sparse" data storage so each line of the bitmap is allocated separately, reusing more memory and requiring smaller contiguous memory segments

  • Store bitmaps in its compressed form (PNG, JPG, GIF, etc) and unpack only when its needed, reducing the amount of memory used. Delete the unpacked data if its not used for 10 secs.

  • 1
    \$\begingroup\$ A lot of this depends on what you are going to do with them, in a game your textures would reside in VRAM most of the time, giving you limited choices for the formats.. \$\endgroup\$ – user13213 Nov 21 '12 at 15:54
  • \$\begingroup\$ I'll add that your requirements 2 and 3 are often mutually exclusive; fast access and minimized memory usage can very much be a "pick one" case. \$\endgroup\$ – Maximus Minimus Nov 22 '12 at 13:02

For fast software rendering, there are a few things you really want:

16-pixel scanline alignment, for SIMD or vectorized code.

32-bit RGBA or BGRA chunky (as opposed to planar) pixel formats, for fast 4-byte indexing. BGRA for fast copying to video memory for display, or RGBA because that's how image data is usually stored in files. If no alpha is needed, you still want to pad the data to 4 bytes per pixel.

If the image is too large, you'll get expensive cache misses. Keep the image size down, or split the image into tiles.

Working with compressed image formats in software is usually too expensive. For hardware, S3TC and other texture compression formats are commonly used. They are extremely bad quality lossy compression, but work well for the types of images usually used for textures. Their biggest benefit is being fixed size, so to access a given pixel you only need to read and decode one block of data at a known location.

  • \$\begingroup\$ Woah! You know a lot but too fast! Can you clarify what "scanline" and "chunky" means? \$\endgroup\$ – Robinicks Nov 21 '12 at 23:39
  • 1
    \$\begingroup\$ A scanline is one row of pixels. Chunky just means all the color components belonging to a pixel follow each other in memory. Planar is another (rarely used) layout, where you'd store the different color components (red, green, blue) separately. Planar is mostly used by some printer hardware. Consider how JPEG does chroma subsampling, where the two color channels may have a lower resolution than the luminance channel; that's also a form of planar color layout. \$\endgroup\$ – ccxvii Nov 22 '12 at 12:16
  • \$\begingroup\$ Why is 4-byte indexing faster than 3-byte indexing? Because you can use x << 2 instead of x * 3? Or are there assembly level optimizations also? \$\endgroup\$ – Robinicks Nov 22 '12 at 14:14
  • 1
    \$\begingroup\$ BGRA is the most common format for how images are stored on your graphics card, so that will be generally be the fastest. It's also the same as is used in GDI and win32 graphics calls. ARGB is the same as BGRA byte swapped. Intel machines are little endian so if you have your bytes in BGRA order, if you interpret that as a 32-bit integer it can be read as ARGB (A<<24|R<<16|G<<8|B). \$\endgroup\$ – ccxvii Nov 22 '12 at 14:37
  • 1
    \$\begingroup\$ x << 2 is always faster than x * 3 (though you can probably cheat and use x * 2 + x). you can also load and work on the entire pixel as one word, rather than doing it 3 bytes at a time for each pixel. rgba = (int*)data[x] as opposed to r = data[x*3]; g = data[x*3+1]; b = data[x*3+2]; \$\endgroup\$ – ccxvii Nov 22 '12 at 14:41
  1. Pixel arrays with/without tiling.
  2. You should use tiling if you intend to do efficient scaling / interpolation / software rendering since it improves the chances of finding the next accessed pixel still in cache. 32 bits per pixel (with the appropriate alignment) are preferred since there are some CPU-specific optimizations for accessing correctly aligned data.
  3. JPEG is lossy, PNG with max. compression is slow. You'll probably need to add some implementation specific compression step, if there is one.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.