Adding an image to a 2D OpenGL screen may seem like a relatively simple task, but it’s not. OpenGL is a rendering language, and as such has no native support for loading JPEG, GIF, TIF, BMP or any other popular image type.

If, like me, you’re looking for a quick and simple way to get 2D images onto your screen, then read on.

First, we need to convert the image into a format readable by OpenGL. Yes, there are libraries out there to do the conversion on the fly and yes, you can use them instead of this method but doing the conversion this way will reduce the load of your programs at run time and eliminate the need for external image files. For this example I’ll use GIMP on Ubuntu 9.04.

Open the image with GIMP and go to the Save As / Save A Copy screen. At the bottom you will see a Select File Type (By Extension) button. Click it, select C source code and hit save. You should see another prompt with some options. De-select the Use GLib types checkbox and check the Save alpha channel checkbox, even if there’s no transparency in the image (I couldn’t get images to render properly without selecting this option).

You should now have a file which looks like so:

/* GIMP RGBA C-Source image dump (image.c) */

static const struct {
unsigned int width;
unsigned int height;
unsigned int bytes_per_pixel; /* 3:RGB, 4:RGBA */
unsigned char pixel_data[573 * 457 * 4 + 1];
} gimp_image = {
573, 457, 4,
"\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377"
...
};

This is the raw data of your image. #include this file in your OpenGL program.

Now that we have the image data in the program we can use it as a texture. To load the image into a rectangle, use the following code:


/* create the image variable */

GLuint image;

/* assign it a reference. You can use any number */
glGenTextures(1, &gimp_image);

/* load the image into memory. Replace gimp_image with whatever the array is called in the .c file */
gluBuild2DMipmaps(GL_TEXTURE_2D, gimp_image.bytes_per_pixel, gimp_image.width, gimp_image.height, GL_RGBA, GL_UNSIGNED_BYTE, gimp_image.pixel_data);

/* enable texturing. If you don't do this, you won't get any image displayed */
glEnable(GL_TEXTURE_2D);

/* draw the texture to the screen, on a white box from (0,0) to (1, 1). Other shapes may be used. */
glColor3f(1.0, 1.0, 1.0);

/* you need to put a glTexCoord and glVertex call , one after the other, for each point */
glBegin(GL_QUADS);
glTexCoord2d(0.0, 1.0); glVertex2d(0.0, 0.0);
glTexCoord2d(0.0, 0.0); glVertex2d(0.0, 1.0);
glTexCoord2d(1.0, 0.0); glVertex2d(1.0, 1.0);
glTexCoord2d(1.0, 1.0); glVertex2d(1.0, 0.0);
glEnd();

/* clean up */
glDisable(GL_TEXTURE_2D);
glDeleteTextures(1, &logo);

Voila. You have a texture.

The next thing to note is that textures will always be painted from (0,0) to (1, 1). To move it around, have a play with glEnable(GL_TEXTURE_2D), glTranslatef(…) and glScalef(…). Google can help you figure out what these mean.

  1. Hello Tim. I´m from Brazil and it is the first time i visit your website. First of all , i would like to congratulate you for the site, it looks very nice.

    Well, now, my question.

    I´m getting an error when i try to insert an image as texture in a glutSolidSphere function. This is the error message :

    ” cannot convert `const *’ to `GLuint*’ for argument `2′ to `void glGenTextures(GLsizei, GLuint*)’ RodaGigante.cpp /TrabalhoCG/src line 408 C/C++ Problem ”

    Can you help me?

    If you want, i prefer that you send the answer to my email.

    Thank you very much!

  2. Tim says:

    Hi Matheus,

    Can you please post your source code? I can’t help you find the problem if I can’t see what it is you’re doing.

    Tim

  3. Sure, thank you very much for help me!

    void desenha() {

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    GLuint image;

    glGenTextures(2, &gimp_image); // The error is occuring here

    gluBuild2DMipmaps(GL_TEXTURE_2D, gimp_image.bytes_per_pixel, gimp_image.width, gimp_image.height, GL_RGBA, GL_UNSIGNED_BYTE, gimp_image.pixel_data);

    glEnable(GL_TEXTURE_2D);

    glColor3f(0.0, 0.0, 0.0);

    glPushMatrix();
    glColor3f(0.0,0.0,0.0);
    // esfera que cerca o ambiente para inserir a textura noturna ( céu estrelado )
    glutSolidSphere(70.0,1000,50);
    glPopMatrix();

    /* clean up */
    glDisable(GL_TEXTURE_2D);
    glDeleteTextures(1, &image);

    glPushMatrix();

    glTranslated(0.0,5.0,0.0);

    glRotatef(y_, 0.0, 1.0, 0.0);

    drawTenda(-8,8,-6,4,5);

    glColor3f(1.0, 1.0, 1.0);

    drawTerreno();

    for (float i = 0; i <= 10; i +=1 )
    drawPoste(sin(i)*15, cos(i)*15, 0.0, 6.0);

    glTranslatef(0.0,ys_,0.0);
    glRotatef(z_, 0.0, 0.0, 1.0);

    //glTranslated(0.0,ys_,0.0);

    drawEixo(0.0, 0.0, -0.8, 3.0, 0.1); // eixo central da roda gigante

    drawRodas();

    drawAxes();

    drawCabine(-2.0,8.0,-3.4);

    drawCabine(-2.0,-12.0,-3.4);

    drawCabine(-12.0,-2.0,-3.4);

    drawCabine(8.0,-2.0,-3.4);

    glPopMatrix();

    glPushMatrix();
    glTranslated(0.0,5.0,0.0);
    glRotatef(y_, 0.0, 1.0, 0.0);

    glPushMatrix();
    glColor3f(1.0,1.0,1.0);
    glTranslated(0.0,ys_,0.0);
    glRotatef(90, 1.0, 0.0, 0.0);
    drawEixo(0.0,-0.5,0.0,6.0, 0.11);
    glPopMatrix();
    glPushMatrix();
    glColor3f(0.0,0.0,1.0);
    glRotatef(90, 1.0, 0.0, 0.0);
    drawEixo(0.0,-0.5,0.0,6.0, 0.1);
    glPopMatrix();

    drawSuporte(0.0,-3.0,2.0);

    drawSuporte(0.0,-3.0,-0.5);
    glPopMatrix();
    }

  4. Tim says:

    Hi Matheus,

    What is gimp_image? This is what’s causing your error.

    T

  5. Isaac says:

    i appreciate all the examples above but ive gotta a question how can i save my drawing cuz im makin kind of a paint and i need to save a drawing on my HardDisk is that possible ive been looking for the solution and ive read that i need to combine glreadpixels and after i capture the drawing save it lol do i need to use FILE FOPEN FWRITE OR WHAT HELP thanks

  6. Gilberto says:

    Hello!

    Sorry for my poor english…

    I was searching for an example showing how to embed textures and
    then I found this page that solved my problem. Thank you very much!
    But I still have a doubt.

    I was using GIMP the same way you say here and coding almost
    the same example, but I was trying to use glTexImage2D in the same
    position you used gluBuild2DMipmaps.

    Do you know why I can’t get the texture with glTexImage2D?
    Am I doing something wrong? Is there a way to do it?

    I noticed the mipmaps are overloading the processor and the
    rendering is getting slower. When I load the textures with a
    texture loader the rendering is smooth because I don’t create
    the mipmaps. My application (a game) have lots of textures and
    I really don’t need mipmaps for them. Only the first
    level (level 0) is enough for me. It looks good this way.

    Is there a way to generate the textures without mipmaps?

    Thanks.

  7. Gilberto says:

    Hi!

    I did it!

    But it’s strange. I always thought the glTexImage2D could make
    the job alone. I was wrong. The screen only shows an empty square.
    No texture…

    Then, searching the web, I found examples and tried to put a few
    more instructions. Surprise!

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

    The line above was enough to print the texture.

    I still don’t know why I have to set a minification filter to get
    my texture on the screen. And GL_LINEAR is the only value that
    shows the image…

    Well, the job’s done anyway. I have no complains.

    Thanks for the post.

  8. Ananth B says:

    Hi,
    I am currently working on openGL and am a newbie. I need some help in loading an image. I working on windows platform, could you kindly help me out by giving the suitable suggestions.

    Thanks in advance,
    Ananth

  9. sincere says:

    I want you full code for example(include “int main()……return 0”)

    Very thankful if you can send it to my email

  10. Ainan ihsan says:

    Hi
    I tried to compile my program after including the image file’s source code it gave me the following error:
    fatal error C1091: compiler limit: string exceeds 65535 bytes in length
    Plzzz help!!

  11. girish says:

    hi mathues, it is the first time i visit your website. First of all , i would like to congratulate you for the site, it looks very nice. my question is,i done one robot for that robo i whould like to insert an image.and i would like to insert only face of the robo.only that part i would like to insert.is it possible?can you please help me how can i do like that.. and sorry for poor english

  12. swarna says:

    the code given above is ok. But how to select the image. i mean we have to browse for image first then insert it.Please send me the example

  13. A Prasad says:

    Hi Tim,
    The code given above doesnt work. its giving a seg fault. I m sure you hv missed something in the lines.
    Pls help.

  14. marcus says:

    Hi Tim,
    thanks for sharing that, I could’ve worked it out eventually (gimp exports pre-made struct…nice) saves time seeing a working implementation tho 🙂

  15. Deepak says:

    i did as it was told , i exported the image to a c source file and got that file named 03711_HD.c
    it’s a 18.7 mb file :/
    i should replace gimp_image with 03711_HD or the array that’s huge!! what should i do?