Thread: Switching to RGB from GRB

  1. #16
    Registered User
    Join Date
    Aug 2003
    Posts
    1,218
    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)

  2. #17
    Crazy Fool Perspective's Avatar
    Join Date
    Jan 2003
    Location
    Canada
    Posts
    2,640
    Quote Originally Posted by Shakti
    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.

    @OP, you can specify the byte order in opengl by using GL_GRB instead of GL_RGB

  3. #18
    Registered User
    Join Date
    Aug 2003
    Posts
    1,218
    Quote Originally Posted by Perspective
    thats only true if your not using mipmapping.

    @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.

    And GL_GRB dont work with my VS.NET 2002 and it wasnt mentioned anywhere in the red book.

  4. #19
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    The constant is GL_BGR_EXT, and the name suggests it is an extenstion, so may not be in the red book.
    Quote Originally Posted by MSDN
    GL_BGR_EXT provides a format that matches the memory layout of Windows device-independent bitmaps (DIBs). Thus your applications can use the same data with Win32 function calls and OpenGL pixel function calls.
    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.

    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!
    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.

    My attempt would look something like:
    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. */
    		}
    	}
    }
    Let me know if it works.

  5. #20
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    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.
    Last edited by VirtualAce; 09-27-2004 at 11:45 PM.

  6. #21
    Registered User
    Join Date
    Jul 2004
    Posts
    35
    Got it working.. Thanks guys, especially anonytmouse and Bubba

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Converting RGB to Hex.
    By mintsmike in forum C Programming
    Replies: 2
    Last Post: 03-23-2009, 12:22 PM
  2. OpenGL: Pixel addition
    By Hunter2 in forum Game Programming
    Replies: 4
    Last Post: 12-15-2008, 02:36 PM
  3. Stopwatch program (need help!)
    By modnar in forum C Programming
    Replies: 9
    Last Post: 03-22-2004, 12:42 AM
  4. Background color in RGB
    By bennyandthejets in forum Windows Programming
    Replies: 16
    Last Post: 06-20-2003, 05:29 AM
  5. Switching frequency and Bandwidth???
    By pastecopy in forum Tech Board
    Replies: 0
    Last Post: 03-23-2003, 11:13 AM