One thing with the texture you are using, the sizes of the texture are not of power of 2, which is the only sizes ogl can work with (without using go-around functions)
Printable View
One thing with the texture you are using, the sizes of the texture are not of power of 2, which is the only sizes ogl can work with (without using go-around functions)
thats only true if your not using mipmapping.Quote:
Originally Posted by Shakti
@OP, you can specify the byte order in opengl by using GL_GRB instead of GL_RGB
Yes that is why I said go-around functions, because with gluBuild2DMipmaps() it will scale the texture automaticly to the nearest power of 2 dimension, so the limit is sill there.Quote:
Originally Posted by Perspective
And GL_GRB dont work with my VS.NET 2002 and it wasnt mentioned anywhere in the red book.
The constant is GL_BGR_EXT, and the name suggests it is an extenstion, so may not be in the red book.
As for swapping from BGR to RGB you were close with your last effort. However, you need to take into account that the width in bytes of each bitmap scan line is padded to the nearest DWORD (4 bytes). For example, your image is 709 pixels wide.Quote:
Originally Posted by MSDN
Your function does not take this padding into account. You can see that the color varies in the texture as a result of this error.Code:709 * 3 = 2127
2127 % 4 != 0 // Image is not DWORD aligned!
So we add padding bytes.
2128 % 4 == 0 // Image is now DWORD aligned!
My attempt would look something like:
Let me know if it works.Code:/*
* Performs an inplace conversion of a 24bpp BGR bitmap to a
* 24bpp RGB bitmap.
*/
void BGRToRGB(BYTE* bmpimage, BITMAPINFOHEADER* pbih)
{
size_t iLine, iByte, iEndByte;
size_t cbLineWidth = pbih->biSizeImage / pbih->biHeight; /* Width of scan line in bytes. */
/* Loop through each line of the image. */
for (iLine = 0;iLine < pbih->biHeight;iLine++)
{
iByte = (iLine * cbLineWidth); /* First byte of the scan line. */
iEndByte = (iLine * cbLineWidth) + (pbih->biWidth * 3); /* Last byte of image data in line. */
while (iByte < iEndByte)
{
BYTE oldBlue = bmpimage[iByte + 0]; /* Get blue value. */
bmpimage[iByte + 0] = bmpimage[iByte + 2]; /* Set old blue to red. */
bmpimage[iByte + 2] = oldBlue; /* Set old red to blue. */
iByte += 3; /* Move to next pixel. */
}
}
}
C'mon people there is an easy way. Use a structure that is byte aligned.
No need to swap array positions or anything. Now when you render you access each color by: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);
}
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.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);
}
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:
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.Code:for (imageidx = 0; imageidx < bmpinfo->biSizeImage; imageidx+=1){ swaprgb = bmpimage[imageidx]; bmpimage[imageidx] = bmpimage[imageidx + 1]; bmpimage[imageidx + 1] = swaprgb;}
Lucky you didn't crash the thing.
Got it working.. Thanks guys, especially anonytmouse and Bubba :)