0
votes

I'm trying to get myself familiar with the GLUT framework in XCode 9 for a future project I want to work on, but now I'm stuck with getting textures to display properly.

So my goal is it display this bmp image as a texture:

bmp image

to where this red square is:

display window

And the result is this:

error

When it should be this:

goal

Here is the code I used for initializing the texture.

GLuint loadAndBufferImage(const char * filename){

    GLuint texture;
    unsigned char header[54];
    unsigned int dataPos;
    unsigned int width, height;
    unsigned int imageSize;

    unsigned char * data;

    FILE * file = fopen(filename, "rb");
    if(!file){printf("Image could not load\n"); exit(2);}

    if(fread(header, 1, 54, file) != 54){
        printf("Not a correct BMP file.\n");
        return -1;
    }

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

    dataPos = *(int*)&(header[0x0A]);
    imageSize = *(int*)&(header[0x22]);
    width = *(int*)&(header[0x12]);
    height = *(int*)&(header[0x16]);

    if(imageSize == 0) imageSize = width * height * 4;
    if(dataPos==0) dataPos=54;

    data = malloc(imageSize);
    if(!data){printf("No more memory\n"); exit(1);}

    fread(data, 1, imageSize, file);
    fclose(file);

    glGenTextures(1, &texture);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, data);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    free(data);
    return texture;    
}

And this is where that function is called.

GameWindow *initializeGameWindow(){


    GameWindow *gw = malloc(sizeof(*gw));
    if(gw == NULL){
        printf("Error: no more memory");
        exit(1);
    }

    gw->render = render;
    gw->update = update;
    gw->isRunning = isRunning;
    gw->setRunning = setRunning;
    glClearColor(1.0, 1.0, 1.0, 1.0);

    glEnable(GL_TEXTURE_2D);

    glViewport(0.0f, 0.0f, _width, _height);
    glMatrixMode(GL_PROJECTION);
    gluOrtho2D(0, _width, 0, _height);
    glMatrixMode(GL_MODELVIEW);

    glGenBuffers(1, &_vertexBufferID);
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBufferID);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(3, GL_FLOAT, sizeof(VertexData), (GLvoid *)offsetof(VertexData, pos));


    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    glTexCoordPointer(2, GL_FLOAT, sizeof(VertexData), (GLvoid *)offsetof(VertexData, tex));

    _textureBufferID = loadAndBufferImage("test.bmp");

    return gw;
}

I'm going to take a guess and say it has to do with how I'm getting the data from the image and possibly the texture parameters. If so then how do I fix this? Otherwise is there something else I need to do to set up the texture?

Edit: So I added the fseek(file, (long)dataPos, SEEK_SET); above the fread(data, 1, imageSize, file); in the texture initialization code as suggested and it seems to have shifted the image a little bit compared to initial results.

new results

I also tried changing GL_RGBA and GL_BGRA to GL_RGB and GL_BGR respectively as in the glTexImage2D function and this happened.

change to GL_RGB and GL_BRG

Edit 2: So after some research and some experimentation, it turns out the other problem was because the image was set to indexed color mode instead of RGB color mode when I saved it as a bitmap file. (I'm using the Gimp editor.) It must have affected how the data was stored because the hex values in the pixel data sections of the file and the total file sizes were different when I compared them. But switching it to RBG color mode in the editor was the final key to solving this problem.

https://image.ibb.co/fC99Lm/Screen_Shot_2017_10_18_at_4_15_36_AM.png

Thank you for all your help.

Resources:

https://en.wikipedia.org/wiki/BMP_file_format

http://fac.ksu.edu.sa/sites/default/files/lab08_6.pdf

1
Are You sure there is alpha channel data in BMP file? You are passing data to texture as RGBA (I mean the call to glTexImage2D).Matso
I tried changing the glTexImage2D function as suggested (changing to GL_RGB and GL_BGR respectively) And posted the result. I think the color data is 4 bytes long instead of 3.Nike Adeyemi

1 Answers

0
votes

You have read but overlooked dataPos, the offset of the image data. Use

fseek(file, (long)dataPos, SEEK_SET);
fread(data, 1, imageSize, file);

to position the file pointer to the data. The reason for this, is there can be palette data between the header and the image data.