In my app, I’m storing Bitmap data in a two-dimensional integer array (int[,]). To access the R, G and B values I use something like this:
// read:
int i = _data[x, y];
byte B = (byte)(i >> 0);
byte G = (byte)(i >> 8);
byte R = (byte)(i >> 16);
// write:
_data[x, y] = BitConverter.ToInt32(new byte[] { B, G, R, 0 }, 0);
I’m using integer arrays instead of an actual System.Drawing.Bitmap because my app runs on Windows Mobile devices where the memory available for creating bitmaps is severely limited.
I’m wondering, though, if it would make more sense to declare a structure like this:
public struct RGB
{
public byte R;
public byte G;
public byte B;
}
… and then use an array of RGB instead of an array of int. This way I could easily read and write the separate R, G and B values without having to do bit-shifting and BitConverter-ing. I vaguely remember something from days of yore about byte variables being block-aligned on 32-bit systems, so that a byte actually takes up 4 bytes of memory instead of just 1 (but maybe this was just a Visual Basic thing).
Would using an array of structs (like the RGB example` above) be faster than using an array of ints, and would it use 3/4 the memory or 3 times the memory of ints?
If you are on about speed, then technically I would expect the
int[]version to be faster, as there is a specific IL instruction for getting anintfrom an array (seeOpCodes.Ldelem_I4). To do a custom struct it has to get the address (OpCodes.Ldelema) and then copy the struct (OpCodes.Ldobj) – processing the type metadata for both of those steps.In short – the
intapproach should have better optimisations. But this is micro-optimisation – in general prefer the version that makes your code more readable. What you might consider is writing the struct with a custom static implicit conversion operator fromintto your struct – then you can have theint[]and still do:(it’ll do a static call in the middle, of course)
You might also consider using a union so you don’t need to do lots of shifting:
IMPORTANT I haven’t sanity checked the endianness on this; just change the offsets of R/G/B to change it.