Creating texture from BMP file

Started by
1 comment, last by EddieV223 11 years, 1 month ago

I am currently trying to draw a plane texture in openGL from a loaded BMP file. Only I don't know the exact codes to do this. I understand that getBMPData(), glBindTexture(), and glTexImage() are some of the functions I need, but I could use an example to understand how to use them.

Advertisement

// To create our window
#include <GL/glut.h>

#ifndef GL_BGRA
#define GL_BGRA 0x80E1
#endif

// For BITMAPFILEHEADER and BITMAPINFOHEADER
#include <windows.h>

#include <stdio.h>

GLuint test_texture_id;

void display(){
    glClear(GL_COLOR_BUFFER_BIT);

    // One vertex is (2 + 2)*4 bytes (2 GLfloats for position, 2 GLfloats for texture coordinates, 4 bytes per GLfloat)
    const int SIZE_OF_VERTEX = (2 + 2)*sizeof(GLfloat);

    GLfloat data[] = {// 2 texture coordinates followed by 2 vertex coordinates in counterclockwise order
        0, 0, -1, -1,// Bottomleft
        1, 0, +1, -1,// Bottomright
        1, 1, +1, +1,// Topright
        0, 1, -1, +1,// Topleft
    };

    // Use this texture
    glBindTexture(GL_TEXTURE_2D, test_texture_id);



    // Tell OpenGL where our vertex data begins and how big each vertex is
    glTexCoordPointer(2, GL_FLOAT, SIZE_OF_VERTEX, data+0);// Texture data begins at index 0
    glVertexPointer  (2, GL_FLOAT, SIZE_OF_VERTEX, data+2);// Vertex  data begins at index 2
    // Draw data
    glDrawArrays(GL_QUADS, 0, 4);

    // We can also draw like this instead (slower but probably more familiar)
/*
    glBegin(GL_QUADS);
    int i;
    for (i=0; i<16; i+=4){
        glTexCoord2f(data[i+0], data[i+1]);
        glVertex2f(data[i+2], data[i+3]);
    }
    glEnd();
*/
    glutSwapBuffers();
}

void reshape(int w, int h){
    glViewport(0, 0, w, h);
}

int main(int argc, char *argv[]){
    glutInit(&argc, argv);
    glutCreateWindow("");

    glutDisplayFunc(display);
    glutReshapeFunc(reshape);

    // Make us able to draw with single function calls (faster)
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    // Make OpenGL draw texture on our triangles/quads/etc
    glEnable(GL_TEXTURE_2D);

    // Enable alpha so we can see through transparent images
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    // Generate a texture id for our texture so we can find it again later
    glGenTextures(1, &test_texture_id);
    // Use this texture id
    glBindTexture(GL_TEXTURE_2D, test_texture_id);
    // Associate this texture id with some texture-specific data
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    /// THIS BITMAP _MUST_ BE 32 BIT BMP!!! (e.g. gimp can export these)

    FILE *fp = fopen("test.bmp", "rb");

    // Load bitmap header
    BITMAPINFOHEADER bmih;
    BITMAPFILEHEADER bmfh;
    fread(&bmfh, 1, sizeof(bmfh), fp);
    fread(&bmih, 1, sizeof(bmih), fp);
    fseek(fp, bmfh.bfOffBits, SEEK_SET);
    // Width of image should be 2^n (2, 4, 8, 16, 32, 64, ...)
    int w = bmih.biWidth;
    int h = bmih.biHeight;
    // Number of bytes (RGBA = 4*1 byte, one byte per color)
    int n = w*h*4;
    void *data = malloc(n);
    fread(data, 1, n, fp);
    // Data loaded from disc to RAM, no need to keep this file open
    fclose(fp);

    // Upload data to GPU (we use GL_BGRA format because bmp colors are messed up)
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_BGRA, GL_UNSIGNED_BYTE, data);

    // Data is in GPU memory, we can delete it from RAM now
    free(data);

    glutMainLoop();

    return 0;
}

I don't recommend this way of loading images or even BMP images, but for testing it is good enough I guess.

I usually use PNG and some library to load it, but the choice mostly depends on what constraints you have.

Note that this is very old OpenGL (which is easier to learn imho but slower than new OpenGL and less versatile).

This is newer OpenGL: https://github.com/progschj/OpenGL-Examples

For simplicity I used 32-bit bmps because they are easier to load since they don't have weird padding bytes every row of pixels (the alpha channel is nice, too).

If you don't have glut and are using Code::Blocks you can get something better here: http://www.transmissionzero.co.uk/software/freeglut-devel/

Just copy the all the include files into your MinGW include folder and the libfreeglut.a into the MinGW lib folder, add -lfreeglut under linkers somewhere and you are good to go (there are other similar ways to do this).

freeimage is a great library, it uses libpng as well as the other libs for opening image files. It however makes it much easier to do so. glfw has a tga loading function.

If you really want to learn to load a bmp by hand ( it's a good learning experience ) then you need to find the right information. Every image has a file header, its the first part of the file's structure that hold the information that you need to know to read and file. Such as width and height, bits per pixel, things like this. Once you have that its pretty easy

You just read the header into a struct, then your data should be next in the file, from the information in the header you should be able to figure out the total number of bytes in the data section. Read this in as an array of chars ( or bytes ). Then when you create your buffer do the following function call to send that data to openGL.

//mWidth is the image width from the image header

//mHeight is the image height from the image header

// mpBytes is a pointer to the char array, its size should be (mWidth * mHeight * (bitsPerPixel / 8)) ( this is in bytes ).

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mWidth, mHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, mpBytes );

// You may need to change the GL_BGRA to whatever format your image is in. In my case its R G B and A channels but in BGRA order.

There are other ways to send your image data to openGL such as mapping the buffer, but this way is easier.

If you want to see an example of bmp loading look at this tutorial

http://www.opengl-tutorial.org

If this post or signature was helpful and/or constructive please give rep.

// C++ Video tutorials

http://www.youtube.com/watch?v=Wo60USYV9Ik

// Easy to learn 2D Game Library c++

SFML2.2 Download http://www.sfml-dev.org/download.php

SFML2.2 Tutorials http://www.sfml-dev.org/tutorials/2.2/

// Excellent 2d physics library Box2D

http://box2d.org/about/

// SFML 2 book

http://www.amazon.com/gp/product/1849696845/ref=as_li_ss_tl?ie=UTF8&camp=1789&creative=390957&creativeASIN=1849696845&linkCode=as2&tag=gamer2creator-20

This topic is closed to new replies.

Advertisement