copengl

Exception thrown at 0x69F1454A (nvoglv32.dll) in Playground.exe: 0xC0000005: Access violation reading location 0x0A08D000


I want to display a texture but the compiler (Visual Studio 2017) gives me this error:

Exception thrown at 0x69F1454A (nvoglv32.dll) in Playground.exe: 0xC0000005: Access violation reading location 0x0A08D000.

The loadBMP_custom function has been taken from this website: http://www.opengl-tutorial.org/beginners-tutorials/tutorial-5-a-textured-cube/

Any help is going to be appreciated.

This is my code:

#include <GL\freeglut.h>
#include <stdio.h>

GLuint loadBMP_custom(const char * imagepath) {
    unsigned char header[54]; 

    unsigned int width, height;
    unsigned int imageSize; 

    GLuint textureID;      
    unsigned char * data;    
    FILE * file;
        
    file = fopen(imagepath, "rb");    
    printf("%s\n", imagepath);    

    if (!file) { 
        printf("Image could not be opened\n"); 
        return 0; 
    }
    
    if (fread(header, 1, 54, file) != 54) { 
        printf("Not a correct BMP file\n");
    }

    if (header[0] != 'B' || header[1] != 'M') {
        printf("Not a correct BMP file\n");
    }


    imageSize = *(int*)&(header[0x22]);     //34
    width = *(int*)&(header[0x12]);         //18
    height = *(int*)&(header[0x16]);        //22

    if (imageSize == 0)    imageSize = width*height * 3;

    data = (unsigned char* )malloc(imageSize);
    
    fread(data, 1, imageSize, file);
    fclose(file);

    for (int i = 0; i < width * height; ++i)
    {
        int index = i * 3;
        unsigned char B, R;
        B = data[index];
        R = data[index + 2];

        data[index] = R;
        data[index + 2] = B;

    }
    
    glGenTextures(1, &textureID);
    
    glBindTexture(GL_TEXTURE_2D, textureID);    
    
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, 
    GL_UNSIGNED_BYTE, data);    

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

    return textureID;
}

void displayMe(void) {
    GLuint bmp;

    glClear(GL_COLOR_BUFFER_BIT);       
    glEnable(GL_TEXTURE_2D);

    
    glPushMatrix();

    bmp = loadBMP_custom("C:\\Dev\\Playground\\Release\\template.bmp");
    glBindTexture(GL_TEXTURE_2D, bmp);
    glBegin(GL_POLYGON);
    glTexCoord2f(0.0, 0.0);
    glVertex2f(0.0, 0.0); 

    glTexCoord2f(0.1, 0.0);
    glVertex2f(0.1, 0.0);                    

    glTexCoord2f(0.1, 0.1);
    glVertex2f(0.1, 0.1);                    

    glTexCoord2f(0.0, 0.1);
    glVertex2f(0.0, 0.1);                    
    glEnd();
    
    glPopMatrix();

    glutSwapBuffers();
}

void reshape(int w, int h) {
    glViewport(0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(60.0, (GLfloat)w / (GLfloat)h, 1.0, 30.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    glTranslatef(0.0, 0.0, -3.6);
}

int main(int argc, char** argv) {
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
    glutInitWindowSize(800, 800);                   
    
    glutCreateWindow("hi");       
    glutDisplayFunc(displayMe);    
    glutReshapeFunc(reshape);

    glutMainLoop();
    return 0;
}    

Solution

  • if (imageSize == 0)    imageSize = width*height * 3;
    [...]
    data = (unsigned char* )malloc(imageSize);
    [...]
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
    

    You are telling OpenGL that it should interpret the data pointer as describing an image with RGBA components at each pixel, each as bytes, but you provide only RGB data, which means that the GL will access beyond the end of your buffer.

    The last three parameters of glTexImage describe the image data in client memory: the numer and order of the channels, the data format for each channel, and the pointer to the first pixel. The GL_RGB you use as internalFormat just describes the format the GL shall internally store the texture at.

    The correct code should be

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // use tightly-packed data buffer with no padding between image rows
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);