C'mon people there is an easy way. Use a structure that is byte aligned.
Code:
//Already byte aligned
struct ReverseRGB
{
BYTE blue;
BYTE green;
BYTE red;
BYTE alpha;
};
#pragma pack(1)
struct BMPHeader
{
WORD Type;
DWORD Size;
DWORD Reserved;
DWORD Offset;
DWORD HeaderSize;
DWORD Width;
DWORD Height;
WORD Planes;
WORD BitsPerPixel;
DWORD Compression;
DWORD ImageSize;
DWORD XPixelsPerMeter;
DWORD YPixelsPerMeter;
DWORD ColorsUsed;
DWORD ColorsImportant;
};
#pragma pack(16)
void LoadBMPColorMap(std::string File,ReverseRGB *Map,BMPHeader &bmpinfo)
{
WORD handle=_open(File.c_str(),_O_BINARY | _O_RDONLY);
_read(handle,&bmpinfo,sizeof(BMPHeader));
DWORD size=(bmpinfo.Width*bmpinfo.Height)*3;
DWORD bytes=_read(handle,Map,size);
_close(handle);
}
No need to swap array positions or anything. Now when you render you access each color by:
Code:
ReverseRGB *Map=new ReverseRGB[size];
for (DWORD i=0;i<size;i++)
{
BYTE red=Map[i].Red;
BYTE green=Map[i].Green;
BYTE blue=Map[i].Blue;
BYTE alpha=Map[i].Alpha;
...
...
PlotPixel(x,y,red,green,blue,alpha);
}
Now my code DOES not account for images that are not divisible by 4. Image data is padded to the nearest DWORD boundary or the nearest 4 byte boundary. This code can be altered to accomodate for this. Also this is not the official Window's way to load bitmaps, but I don't use the official way because well it's assinine and it sucks. It takes tons of lines of code just to get to the stupid data. Writing your own function and not relying on GDI will help a lot. OpenGL should have functions though to load bitmaps so you don't need all this crap.
I used to reverse the data myself into RGBA order and then I realized that the pixel functions don't care what order the data is in - if you access it via a struct the order will always be correct. It is the order in which you pass the red,green,blue and alpa members to your functions that matter.
This saves a lot of headaches.
Incidentally if you use the struct like this and you want to use assembly you must reverse the order or the DWORD will not be in the correct order and will produce odd results. But in C it does not matter. But in assemby this can be done by a simple rotate right ROR or rotate left by the desired number of bits, in this case 32. The only problem is most cards use RGBA format and this yields ARGB. But that can easily be fixed as well.
Accessing the members via a struct is actually faster than accessing it via indexes - I've profiled both ways and structs are faster although I'm not sure why.
On a side note this:
Code:
for (imageidx = 0; imageidx < bmpinfo->biSizeImage; imageidx+=1){ swaprgb = bmpimage[imageidx]; bmpimage[imageidx] = bmpimage[imageidx + 1]; bmpimage[imageidx + 1] = swaprgb;}
Is dangerous. You are over running your array bounds. imageidx will go from 0 to the size of the image. However, later in the code you use imagedx+1 which will result in bmpinfo->biSizeImage+1 - which is an array overrun.
Lucky you didn't crash the thing.