Question

I am working with textures in OpenGL and have came across a strange issue. Sometimes an image that's loaded in is pushed over to the right slightly. I will supply code and screen shots below.

Image

#include <gl/glew.h>
#include <gl/glut.h>
#include <windows.h>
#include <stdio.h>
#include <SOIL.h>

const int WINDOW_WIDTH = 1024;
const int WINDOW_HEIGHT = 512;

GLuint Tex;
GLuint Tex2;

GLuint LoadTexture( const char * filename, int w, int h )
{
    GLuint texture;
    int width, height;
    unsigned char * data;
    FILE * file;
    file = fopen( filename, "rb" );

    if ( file == NULL ) return 0;
    width = w;
    height = h;
    data = (unsigned char *)malloc( width * height * 3);
    fread( data, width * height * 3, 1, file );
    fclose( file );

    glGenTextures( 1, &texture );
    glBindTexture( GL_TEXTURE_2D, texture );
    glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE,GL_MODULATE );

    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_NEAREST );

    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,GL_REPEAT );
    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,GL_REPEAT );
    gluBuild2DMipmaps( GL_TEXTURE_2D, 3, width, height,GL_RGB, GL_UNSIGNED_BYTE, data );
    free( data );

    return texture;
}

void Reshape( int width, int height )
{
    glViewport( 0, 0, (GLsizei)width, (GLsizei)height );
    glMatrixMode( GL_PROJECTION );

    glLoadIdentity();
    glOrtho( 0.0f, WINDOW_WIDTH, 0.0f, WINDOW_HEIGHT, 1.0f, 100.0f );

    glMatrixMode( GL_MODELVIEW );
}

void lightInit( void )
{
    GLfloat lightWhite[] = { 1.0f, 1.0f, 1.0f, 1.0f };
    GLfloat lightBlack[] = { 0.0f, 0.0f, 0.0f, 1.0f };
    GLfloat lightPos[] = { 0.0f, 0.0f, 0.0f, 1.0f };

    glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, lightWhite );
    glMaterialf( GL_FRONT, GL_SHININESS, 30 );

    glLightfv( GL_LIGHT0, GL_AMBIENT, lightBlack );
    glLightfv( GL_LIGHT0, GL_SPECULAR, lightWhite );
    glLightfv( GL_LIGHT0, GL_DIFFUSE, lightWhite );
    glLightfv( GL_LIGHT0, GL_POSITION, lightPos );

    glEnable( GL_LIGHTING );
    glEnable( GL_LIGHT0 );
    glEnable( GL_COLOR_MATERIAL );
    glEnable( GL_DEPTH_TEST );
}

void drawTexObj()
{
    Tex = LoadTexture( "texture2.bmp", 1024, 512 );
    if( Tex == 0 )
    {
        exit(0);
    }
    glEnable( GL_TEXTURE_2D );
    glPushAttrib( GL_CURRENT_BIT );
    glBegin( GL_QUADS );
        glTexCoord2d( 0.0f, 0.0f );
        glVertex2f( 0.0f, 0.0f );

        glTexCoord2d( 0.0f, 1.0f );
        glVertex2f( 0.0f, 512.0f );

        glTexCoord2d( 1.0f, 1.0f );
        glVertex2f( 1024.0f, 512.0f );

        glTexCoord2d( 1.0f, 0.0f );
        glVertex2f( 1024.0f, 0.0f );
    glEnd();
    glPopAttrib();
    glDisable( GL_TEXTURE_2D );
    glDeleteTextures( (GLsizei)1, &Tex );
}

void drawTexObj2()
{
    Tex2 = LoadTexture( "texture.bmp", 1024, 512 );
    if( Tex2 == 0 )
    {
        exit(0);
    }
    glEnable( GL_TEXTURE_2D );
    glBegin( GL_QUADS );

        glTexCoord2d( 0.0f, 0.0f );
        glVertex2f( 0.0f, 0.0f );

        glTexCoord2d( 0.0f, 1.0f );
        glVertex2f( 0.0f, 256.0f );

        glTexCoord2d( 1.0f, 1.0f );
        glVertex2f( 512.0f, 256.0f );

        glTexCoord2d( 1.0f, 0.0f );
        glVertex2f( 512.0f, 0.0f );

    glEnd();
    glDisable( GL_TEXTURE_2D );
    glDeleteTextures( (GLsizei)1, &Tex2 );
}

void Display()
{
    glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    glLoadIdentity();
    glTranslatef( 0.0f, 0.0f, -1.0f );

    drawTexObj();
    drawTexObj2();

    glutSwapBuffers();
}

int main( int argc, char **argv )
{
    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH );
    glEnable( GL_DEPTH );

    glutInitWindowPosition( 200, 100 );
    glutInitWindowSize( 1024, 512 );

    glutCreateWindow( "Texturing :D!" );

    //lightInit();

    glutDisplayFunc( Display );
    glutIdleFunc( Display );
    glutReshapeFunc( Reshape );

    glutMainLoop();
}
Was it helpful?

Solution

This looks like an issue with reading the file in the first place. BMP files are not simple neat arrays of pixel bytes, so you can't just read in width*height*3 bytes. You will see the image data in there, (assuming 24 bpp storage), but there is also header information which will push the pixel data over on the display. I'm surprised that the 2nd bitmap looks OK, although this might be coincidence that the header matches the image width.

A better solution would be to use the Gdi to load the images...

GdiplusStartupInput lstartup_input;
GdiplusStartupOutput lstartup_output;
ULONG_PTR   ltoken;

GdiplusStartup(&ltoken, &lstartup_input, &lstartup_output);

Bitmap *lbitmap;
lbitmap = new Bitmap(wszPath);

GdiplusShutdown(ltoken);

RGBQUAD *pBits = (RGBQUAD *) malloc(lbitmap->GetWidth() * lbitmap->GetHeight() * 4 * sizeof(BYTE));
lbitmapdata.Scan0 = pBits;
lbitmapdata.Width = lbitmap->GetWidth();
lbitmapdata.Height = lbitmap->GetHeight();
lbitmapdata.PixelFormat = PixelFormat32bppARGB;
lbitmapdata.Stride = lbitmap->GetWidth()*4;

Rect    lrect(0,0,lbitmap->GetWidth(), lbitmap->GetHeight());
st = lbitmap->LockBits(&lrect, ImageLockModeUserInputBuf | ImageLockModeRead,
    PixelFormat32bppARGB, &lbitmapdata);
ASSERT(st == Ok);
st = lbitmap->UnlockBits(&lbitmapdata); // Unlock straightaway, because we just want to extract the pixel data
ASSERT(st == Ok);

This snipped uses 4 bytes per-pixel, as I use the alpha channel, but from there you should be able to convert it as you need it. Here's a code snippet to convert the BGRA to RGB. (You could change the pixel format for UnlockBits to PixelFormat24bppRGB, but you might still need to swap the colours about - try it and see.)

BYTE *rgbBits = (malloc lbitmap->GetHeight() * lbitmap->GetWidth() * 3);
BYTE *rgbPtr = rgbBits;
pPixel = (RGBQUAD *)m_pBits;
for (li = 0; li < lbitmap->GetHeight() * lbitmap->GetWidth(); li++)
{
    *(rgbPtr++) = pPixel->rgbRed;
    *(rgbPtr++) = pPixel->rgbGreen;
    *(rgbPtr++) = pPixel->rgbBlue;
    pPixel++;
}

(Note that I just pulled this code out of my project, so it might need some cleaning up. Let me know.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top