Advertisement

Loading image into OpenGL

Started by February 06, 2014 09:55 PM
16 comments, last by Ramal Kurdy 10 years, 11 months ago

Iam trying to load a bmp image into OpenGL. The program works fine but the image does not appear. The source code below does not contain any errors. Could you please help.

Thanks


SOLVED: THE CODE BELOW WORKS.
#include "stdafx.h"
#include <stdlib.h>
#include "glut.h"
#include <math.h>
#include <stdio.h>
float fTranslate = 0.0;
GLuint texture[1];
typedef struct Texture_Image
{
int width;
int height;
int format;
unsigned char *data;
} TEXTURE_IMAGE;
typedef TEXTURE_IMAGE *P_TEXTURE_IMAGE;
P_TEXTURE_IMAGE t1;
P_TEXTURE_IMAGE AllocateTextureBuffer(GLint w, GLint h, GLint f)
{
P_TEXTURE_IMAGE ti=NULL;
unsigned char *c=NULL;
ti = (P_TEXTURE_IMAGE)malloc(sizeof(TEXTURE_IMAGE));
if (ti != NULL) {
ti->width = w;
ti->height = h;
ti->format = f;
c = (unsigned char *)malloc(w * h * f);
if (c != NULL) {
ti->data = c;
}
else {
printf("error");
return NULL;
}
}
else
{
printf("error");
return NULL;
}
return ti;
}
void DeallocateTexture(P_TEXTURE_IMAGE t)
{
if(t)
{
if(t->data)
{
free(t->data);
}
free(t);
}
}
int ReadTextureData (char *filename, P_TEXTURE_IMAGE buffer)
{
FILE *f;
int i, j, k, done = 0;
int stride = buffer->width * buffer->format;
unsigned char *p = NULL;
f = fopen(filename, "rb");
if (f !=NULL)
{
for (i = buffer->height-1; i>=0; i--)
{
p = buffer->data + (i * stride);
for (j = 0; j < buffer->width; j++)
{
for (k = 0; k < buffer->format-1; k++, p++, done++)
{
*p = fgetc(f);
}
*p = 255; p++;
}
}
fclose(f);
}
else
{
printf("name error\n");
}
return done;
}
void BuildTexture (P_TEXTURE_IMAGE tex)
{
glGenTextures(1, &texture[0]);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, tex->width, tex->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex->data);
}
int InitGL(GLvoid)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0, 500, 0, 500);
t1 = AllocateTextureBuffer(256, 256, 4);
if (ReadTextureData("globe.bmp", t1) == 0)
{
printf("error\n");
return false;
}
BuildTexture (t1);
DeallocateTexture (t1);
glEnable(GL_TEXTURE_2D);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
return true;
}
void quad(){
glBindTexture(GL_TEXTURE_2D, texture[0]);
glBegin(GL_QUADS);
glTexCoord2f(1.0, 0.0);glVertex3f( 112, 112, 0.0);
glTexCoord2f(1.0, 1.0);glVertex3f( 112, -112, 0.0);
glTexCoord2f(0.0, 1.0);glVertex3f( -112, -112, 0.0);
glTexCoord2f(0.0, 0.0);glVertex3f( -112, 112, 0.0);
glEnd();
}
GLvoid DrawGLScene (GLvoid)
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0,1.0,1.0);
glBindTexture(GL_TEXTURE_2D, texture[0]);
glPushMatrix();
glTranslatef(250,250,0);
quad();
glPopMatrix();
glutSwapBuffers();
glutPostRedisplay();
}
int main(int argc, char **argv)
{
glutInit(&argc,argv);
glutInitWindowPosition(350, 200);
glutInitDisplayMode (GLUT_RGBA | GLUT_DOUBLE);
glutCreateWindow("Image");
InitGL();
glutDisplayFunc(DrawGLScene);
glutMainLoop();
return 0;
}

Its most likely due to mipmaps, since you didn't generate any and didn' disable mipmapping filter eigther. Eigther use


glGenerateMipmap(GL_TEXTURE_2D)

after glTexImage2D or turn of mipmapping by by setting the filter to GL_LINEAR.

Advertisement

You may load into OpenGL any image file Windows available with the CImage class. Technology provided:Codes and Demo.

Your texture coordinates are all 1.0, try

glTexCoord2f(1.0, 1.0);glVertex3f( 2, 2, 0.0);
glTexCoord2f(1.0, 0.0);glVertex3f( 2, -2, 0.0);
glTexCoord2f(0.0, 0.0);glVertex3f( -2, -2, 0.0);
glTexCoord2f(0.0, 1.0);glVertex3f( -2, 2, 0.0);

also might want to check the winding on that quad and your GL_TEXTURE_WRAP_*, s and t modes.

Are you sure of using GL_RGBA for a bmp in your glTexImage2D?

Anyway, this tutorial loads a bmp.

Its most likely due to mipmaps, since you didn't generate any and didn' disable mipmapping filter eigther. Eigther use


glGenerateMipmap(GL_TEXTURE_2D)

after glTexImage2D or turn of mipmapping by by setting the filter to GL_LINEAR.

Where do I place it?

Advertisement

Your texture coordinates are all 1.0, try

glTexCoord2f(1.0, 1.0);glVertex3f( 2, 2, 0.0);
glTexCoord2f(1.0, 0.0);glVertex3f( 2, -2, 0.0);
glTexCoord2f(0.0, 0.0);glVertex3f( -2, -2, 0.0);
glTexCoord2f(0.0, 1.0);glVertex3f( -2, 2, 0.0);

also might want to check the winding on that quad and your GL_TEXTURE_WRAP_*, s and t modes.

Thanks I changed it. Now I can see the picture upside down and a bit blurry. I edited the code above. Could you please have a look at it.

The picture is blurry since you used GL_LINEAR instead of GL_NEAREST in those calls:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
And if the texture is upside down, you just have to invert the y texture coordinates.

glTexCoord2f(1.0, 0.0);glVertex3f( 2, 2, 0.0);
glTexCoord2f(1.0, 1.0);glVertex3f( 2, -2, 0.0);
glTexCoord2f(0.0, 1.0);glVertex3f( -2, -2, 0.0);
glTexCoord2f(0.0, 0.0);glVertex3f( -2, 2, 0.0);

The picture is blurry since you used GL_LINEAR instead of GL_NEAREST in those calls:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
And if the texture is upside down, you just have to invert the y texture coordinates.

glTexCoord2f(1.0, 0.0);glVertex3f( 2, 2, 0.0);
glTexCoord2f(1.0, 1.0);glVertex3f( 2, -2, 0.0);
glTexCoord2f(0.0, 1.0);glVertex3f( -2, -2, 0.0);
glTexCoord2f(0.0, 0.0);glVertex3f( -2, 2, 0.0);

I modfied the code, but the picture is still blurry. Iam trying to insert the image below. I have resized it and made it smaller. Do you think I need to change the values within texture buffer?


t1 = AllocateTextureBuffer(256, 50, 4);

This is what it looks like.

direct link

http://s30.postimg.org/eurazb6i9/Picture1.png

Are you trying to display this on a 2d quad stuck to the screen, or, in 3d? Im assuming 2d because you are using gluOrtho. Its going to be blurry to some degree if the pixels dont map 1 to 1 with the quad.

Use the following to stop the image from repeating, unless repeating is what you want then use GL_REPEAT


glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

Im not sure what size the glut window is, so try this to start


int gWidth = 800, gHeight = 600;  // store these globally where all functions can access

glutInitWindowSize(gWidth, gHeight); // before glutCreateWindow()

Also setup a reshape function to handle window resizing


void Resize()
{
        glViewport(0, 0, (GLsizei)gWidth, (GLsizei)gHeight);

        // initialize viewing values
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();
        gluOrtho2D(0.0, 1.0, 0.0, 1.0);             // 2d coordinates will need to be normalized (0.0 to 1.0)

        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
}

void ReshapeGlut(int w, int h)
{
        // update
        gWidth = w;
        gHeight = h;
        // apply
        Resize();
}

glutReshapeFunc(Reshape);            // set it in main after create window

and when drawing, draw using normalized coordinates and fit the quad to the image (might have to call Resize() before clearing during draw)


const float nw = float(ti->width) / float(gWidth);
const float nh = float(ti->height) / float(gHeight);

glBegin(GL_QUADS);   // counter clock wise
glTexCoord2f(0.0, 0.0);glVertex3f( 0.0, 0.0, 0.0);   // bottom left corner
glTexCoord2f(1.0, 0.0);glVertex3f( nw, 0.0, 0.0);     // bottom right
glTexCoord2f(1.0, 1.0);glVertex3f( nw, nh, 0.0);      // top right
glTexCoord2f(0.0, 1.0);glVertex3f( 0.0, nh, 0.0);    // top left  
glEnd();

This topic is closed to new replies.

Advertisement