freeImage example code

Anyone know where I can find a good example of how to use FreeImage with OpenGL? I want to use FreeImage to load any image file it supports to an OpenGL texture.

I’ve post before about that, look at the end of this thread:

http://www.opengl.org/discussion_boards/…3307#Post233307

It’s good to make a search in this forums before make a question, just use the right side panel.

Good luck, bye

http://www.raul-art.blogspot.com

Oh, there is one thing. In that sample code I converted BGR to RGB in the CPU. It’s faster if you do that in a shader.
Bye!

Thanks RGHP i’ll give it a try.

Certainly not ! why would you want to always swizzle your texture accesses just because of a small hypothetical performance hit for the texture creation…

Moreover you can tell OpenGL that your data is in BGRA format ::

glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA, w, h, 0, GL_BGRA,GL_UNSIGNED_BYTE,(GLvoid*)textura )

Cheers

@Nicolas: if you looked at the code RGHP was referring to you would have noticed the following line

//FreeImage loads in BGR format, so you need to swap some bytes(Or use GL_BGR).

ajam!

I tried using your code RGHP for loading a texture using freeImage. It only work with standard opengl image size. I am trying to load an image that is 39x35. Is there a way I can copy that image to a standard opengl image size with transparency for the new image.


#include <windows.h>
#include <gl\gl.h>
#include <gl\glu.h>
#include <SDL\SDL.h>
#include <fmod.hpp>
#include <FreeImage.h>

//The attributes of the screen
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;

//The surfaces that will be used
SDL_Surface *screen = NULL;


void InitGL(int Width, int Height)	        // We call this right after our OpenGL window is created.
{
  glViewport(0, 0, Width, Height);
  glClearColor(0.0f, 0.0f, 0.0f, 0.0f);		// This Will Clear The Background Color To Black
  glClearDepth(1.0);				// Enables Clearing Of The Depth Buffer
  glDepthFunc(GL_LESS);				// The Type Of Depth Test To Do
  glEnable(GL_DEPTH_TEST);			// Enables Depth Testing
  glShadeModel(GL_SMOOTH);			// Enables Smooth Color Shading
  glEnable(GL_TEXTURE_2D);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();				// Reset The Projection Matrix

  gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);	// Calculate The Aspect Ratio Of The Window

  glMatrixMode(GL_MODELVIEW);
}







/* The main drawing function. */




int main( int argc, char* args[] )
{

    //Initialize all SDL subsystems
    if( SDL_Init(SDL_INIT_VIDEO) != 0  )
    {
        return 1;    
    }
    
    SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
    
	//Set up the screen
    screen = SDL_SetVideoMode( 640, 480, 32, SDL_OPENGL);


    //If there was an error in setting up the screen
    if( screen == NULL )
    {
        return 1;    
    }
    
    //Set the window caption
    SDL_WM_SetCaption( "Hello World", NULL );
 

/*
	FMOD::System *system;
	FMOD::System_Create(&system);
	system->init(100, FMOD_INIT_NORMAL, 0);
	FMOD::Sound *sound;
	system->createStream("music.mp3", FMOD_DEFAULT, 0, &sound);		
	FMOD::Channel *channel;
	system->playSound(FMOD_CHANNEL_FREE, sound, false, &channel);
  */ 
     InitGL(640, 480);
     

    
    FREE_IMAGE_FORMAT formato = FreeImage_GetFileType("image.png",0);//Automatocally detects the format(from over 20 formats!)
	FIBITMAP* imagen = FreeImage_Load(formato, "image.png");
	
	FIBITMAP* temp = imagen;
	imagen = FreeImage_ConvertTo32Bits(imagen);
	FreeImage_Unload(temp);
	
	int w = FreeImage_GetWidth(imagen);
	int h = FreeImage_GetHeight(imagen);
	//cout<<"The size of the image is: "<<textureFile<<" es "<<w<<"*"<<h<<endl; //Some debugging code
	
	GLubyte* textura = new GLubyte[4*w*h];
	char* pixeles = (char*)FreeImage_GetBits(imagen);
	//FreeImage loads in BGR format, so you need to swap some bytes(Or use GL_BGR).
	
	for(int j= 0; j<w*h; j++){
		textura[j*4+0]= pixeles[j*4+2];
		textura[j*4+1]= pixeles[j*4+1];
		textura[j*4+2]= pixeles[j*4+0];
		textura[j*4+3]= pixeles[j*4+3];
		//cout<<j<<": "<<textura[j*4+0]<<"**"<<textura[j*4+1]<<"**"<<textura[j*4+2]<<"**"<<textura[j*4+3]<<endl;
	}
	
	//Now generate the OpenGL texture object 
	GLuint texturaID;
	glGenTextures(1, &texturaID);
	glBindTexture(GL_TEXTURE_2D, texturaID);
	glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA, w, h, 0, GL_RGBA,GL_UNSIGNED_BYTE,(GLvoid*)textura );
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);			
glLoadIdentity();					
glTranslatef(-3.0f,0.0f,-6.0f);
glBegin (GL_QUADS);
glTexCoord2f (0.0, 0.0);
glVertex3f (0.0, 0.0, 0.0);
glTexCoord2f (1.0, 0.0);
glVertex3f (1.0, 0.0, 0.0);
glTexCoord2f (1.0, 1.0);
glVertex3f (1.0, 1.0, 0.0);
glTexCoord2f (0.0, 1.0);
glVertex3f (0.0, 1.0, 0.0);
glEnd ();

    SDL_GL_SwapBuffers(); 
    

  int done = 0;
  while ( ! done ) {
	 
    /* This could go in a separate function */
    { SDL_Event event;
      while ( SDL_PollEvent(&event)  ) {
        if ( event.type == SDL_QUIT ) {
          done = 1;
        }
        if ( event.type == SDL_KEYDOWN ) {
          if ( event.key.keysym.sym == SDLK_ESCAPE ) {
            done = 1;
          }
        }
      }
    }
  }
  
    //Quit SDL
    SDL_Quit();
    
    return 0;    
}

You need the non power of two extension in which case it should just work (potentially with caveats), or you can resize or you can use glubuild2dmipmaps to resize which I think automatically resizes for your base level. It is highly recommended that you use images that are 2^n on a side so you can generate content and control resize filters for optimal results.

Instead of using the non-power of two extension which is not supported by all video cards. I want to find a easy way to copy the non-power of two image into another image that is a power of two. The padding in the image I want to make transparent. I’m looking through the freeImage doucment and I don’t see a way I can set the transparency bit for the new image. Is there a easy way I can do this using FreeImage?

Psuedo code
1)Load image and check if image is a power of two.
2)if the image is not a power of two create a new power of two image using FreeImage.
3) set all bits in the new image to transparent.
4)copy the non power of two image into new image.

Well… to conserve more data from the original image you must store the aspect atio too.
Have you downloaded then FreeImage guide? there are functions like FreeImage_Rescale() in the part Unsampling/downSampling. For make a transparent image you need to convert it to 32 bits( 8 bits per channel, if the image have already transparency nothing is added).
You need to delete all temporary results eh!, like I did in the sample code with he FreeImageBITMAP t.

the new size(width or height) should be like:

newSize = (int)pow(2, (int)log(2,oldSize) );

By the way about using RGB or BGR in graphics card, there is a white paper at Nvidia Developer Website called “Fast texture transfers” that you should read, of course it’s for Nvidia hardware. What’s your graphics card model?

I have an old laptop with ati mobility m3. I do not want to rescale my image I just want to keep the image the same and add the padding so that it will work with opengl texture. I was wondering if there is a easy way to set all bit to transparent in the new image and then copy all the data from the old image over in FreeImage.

Why not create a transparent GL texture once and update a rectangular region of the texture with your image data using glTexSubImage2D?

Thanks everyone for you help. I think I found a solution after reading the FreeImage documentation.


FIBITMAP *image = FreeImage_Allocate(width, height, 32);
for(y = 0; y < FreeImage_GetHeight(image); y++) {
FIRGBAF *bits = (FIRGBAF *)FreeImage_GetScanLine(image, y);
for(x = 0; x < FreeImage_GetWidth(image); x++) {
bits[x].alpha = 0;
}
}
FreeImage_Paste(image, src_image, 0, 0, 255);

I’m still having problem displaying my image correctly in opengl. The image with transparency has little black lines on the right side and bottom of the image. I know FreeImage is working correctly because I save the image using FreeImage and the image looks good. I think there is something wrong with this routine for swapping bit to GL_BGR format but I can’t figure out what. Please help.


	GLubyte* textura = new GLubyte[4*w*h];
	char* pixeles = (char*)FreeImage_GetBits(bitmap2);
	//FreeImage loads in BGR format, so you need to swap some bytes(Or use GL_BGR).
	
	for(int j= 0; j<w*h; j++){
		textura[j*4+0]= pixeles[j*4+2];
		textura[j*4+1]= pixeles[j*4+1];
		textura[j*4+2]= pixeles[j*4+0];
		textura[j*4+3]= pixeles[j*4+3];
	}

The entire code


#include <windows.h>
#include <gl\gl.h>
#include <gl\glu.h>
#include <SDL\SDL.h>
#include <fmod.hpp>
#include <FreeImage.h>

//The attributes of the screen
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;

//The surfaces that will be used
SDL_Surface *screen = NULL;


void InitGL(int Width, int Height)	        // We call this right after our OpenGL window is created.
{
  glViewport(0, 0, Width, Height);
  glClearColor(1.0f, 1.0f, 1.0f, 0.0f);		// This Will Clear The Background Color To Black
  glClearDepth(1.0);				// Enables Clearing Of The Depth Buffer
  glDepthFunc(GL_LESS);				// The Type Of Depth Test To Do
  glEnable(GL_DEPTH_TEST);			// Enables Depth Testing
  glShadeModel(GL_SMOOTH);			// Enables Smooth Color Shading
  glEnable(GL_TEXTURE_2D);
  glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();				// Reset The Projection Matrix

  gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);	// Calculate The Aspect Ratio Of The Window

  glMatrixMode(GL_MODELVIEW);
}


int power_of_two(int input)
{
	int value = 1;
	while ( value < input ) {
		value <<= 1;
	}
	return value;
}


FIBITMAP* GenericLoader(const char* lpszPathName, int flag = 0) {
	FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
	// check the file signature and deduce its format
	// (the second argument is currently not used by FreeImage)
	fif = FreeImage_GetFileType(lpszPathName, 0);
	if(fif == FIF_UNKNOWN) {
		// no signature ?
		// try to guess the file format from the file extension
		fif = FreeImage_GetFIFFromFilename(lpszPathName);
	}
	// check that the plugin has reading capabilities ...
	if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) {
	// ok, let's load the file
		FIBITMAP *dib = FreeImage_Load(fif, lpszPathName, flag);
		// unless a bad file format, we are done !
		return dib;
	}
	return NULL;
}



int main( int /*argc*/, char ** argv) 
{
	

    //Initialize all SDL subsystems
    if( SDL_Init(SDL_INIT_VIDEO) != 0  )
    {
        return 1;    
    }
    
    SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
    
	//Set up the screen
    screen = SDL_SetVideoMode( 640, 480, 32, SDL_OPENGL);


    //If there was an error in setting up the screen
    if( screen == NULL )
    {
        return 1;    
    }
    
    //Set the window caption
    SDL_WM_SetCaption( "SDL", NULL );
 

/*
	FMOD::System *system;
	FMOD::System_Create(&system);
	system->init(100, FMOD_INIT_NORMAL, 0);
	FMOD::Sound *sound;
	system->createStream("music.mp3", FMOD_DEFAULT, 0, &sound);		
	FMOD::Channel *channel;
	system->playSound(FMOD_CHANNEL_FREE, sound, false, &channel);
  */ 
     InitGL(640, 480);

    FIBITMAP *bitmap = GenericLoader("image.png");
    int w = power_of_two(FreeImage_GetWidth(bitmap));
	int h = power_of_two(FreeImage_GetHeight(bitmap));
	FIBITMAP *bitmap2 = FreeImage_Allocate(w, h, 32);
	FreeImage_Paste(bitmap2, bitmap, 0, 0, 255);
    FreeImage_Save(FIF_PNG, bitmap2, "mybitmap.png", 0);

	GLubyte* textura = new GLubyte[4*w*h];
	char* pixeles = (char*)FreeImage_GetBits(bitmap2);
	//FreeImage loads in BGR format, so you need to swap some bytes(Or use GL_BGR).
	
	for(int j= 0; j<w*h; j++){
		textura[j*4+0]= pixeles[j*4+2];
		textura[j*4+1]= pixeles[j*4+1];
		textura[j*4+2]= pixeles[j*4+0];
		textura[j*4+3]= pixeles[j*4+3];
	}

	
	GLuint texturaID;
	glGenTextures(1, &texturaID);
	glBindTexture(GL_TEXTURE_2D, texturaID);
	glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA, w, h, 0, GL_RGBA,GL_UNSIGNED_BYTE,(GLvoid*)textura );
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);			
	glLoadIdentity();					
	glTranslatef(2.0f,0.0f,-6.0f);
	
	glBegin (GL_QUADS);
	glTexCoord2f (0.0, 0.0);
	glVertex3f (0.0, 0.0, 0.0);
	glTexCoord2f (1.0, 0.0);
	glVertex3f (1.0, 0.0, 0.0);
	glTexCoord2f (1.0, 1.0);
	glVertex3f (1.0, 1.0, 0.0);
	glTexCoord2f (0.0, 1.0);
	glVertex3f (0.0, 1.0, 0.0);
	glEnd ();

  
    SDL_GL_SwapBuffers(); 
    
	int done = 0;
	while ( ! done ) 
	{
      SDL_Event event;
      while ( SDL_PollEvent(&event)  ) {
        if ( event.type == SDL_QUIT ) {
          done = 1;
        }
        if ( event.type == SDL_KEYDOWN ) {
          if ( event.key.keysym.sym == SDLK_ESCAPE ) {
            done = 1;
		  }
		}
	  }
	}
    
    //Quit SDL
    SDL_Quit();
    
    return 0;    
}

picture with ghost and two black lines on the right and bottom of the ghost that is not suppose to be there.
http://www.keepandshare.com/photo/view.php?u=142005

how are you loading the texture? I’d never have any problem with that code!. Are you setting TexEnvf() to GL_REPLACE ?. How is youroriginal image

Im not setting TexEnvf() to anything. My orginal image is the ghost with a transparent background. I made a copy of the image with FreeImage and made it a power of two. I open the image in photoshop and it looks good, no black lines on the right side or bottom of the image but when I display it with opengl I see the black lines. I can’t figure out why and I review the code you posted and it looks good. I’m not familiar with how opengl saves it bitmap. Is their any header information in the file that is causing the black lines. Can you try my code I posted above and see if you have the same problem. Comment out the fmod include line and everthing else should be standard opengl, sdl and FreeImage.

fix my problem with the two lines of code below.

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

Well, that could’ve fixed it, but nearest sampling can result in some crappy quality :slight_smile:

Maybe you just need to set the wrapping modes to GL_CLAMP_TO_EDGE.

I tried out GL_CLAMP_TO_EDGE and it didn’t compile, I look through the opengl documentation and this works.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

Thanks for all your help.

heres the code.


#include <windows.h>
#include <gl\gl.h>
#include <gl\glu.h>
#include <SDL\SDL.h>
//#include <fmod.hpp>
#include <FreeImage.h>

//The attributes of the screen
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;

//The surfaces that will be used
SDL_Surface *screen = NULL;


void InitGL(int Width, int Height)	        // We call this right after our OpenGL window is created.
{
  glViewport(0, 0, Width, Height);
  glClearColor(1.0f, 1.0f, 1.0f, 1.0f);		// This Will Clear The Background Color To Black
  glClearDepth(1.0);				// Enables Clearing Of The Depth Buffer
  glDepthFunc(GL_LESS);				// The Type Of Depth Test To Do
  glEnable(GL_DEPTH_TEST);			// Enables Depth Testing
  glShadeModel(GL_SMOOTH);			// Enables Smooth Color Shading
  glEnable(GL_TEXTURE_2D);
  glEnable (GL_BLEND); 
  glBlendFunc (GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();				// Reset The Projection Matrix

  gluPerspective(45.0f,(GLfloat)Width/(GLfloat)Height,0.1f,100.0f);	// Calculate The Aspect Ratio Of The Window

  glMatrixMode(GL_MODELVIEW);


//glOrtho(0, 640, 480, 0, -1, 1);
}

//returns the closest power of two value
int power_of_two(int input)
{
	int value = 1;
	while ( value < input ) {
		value <<= 1;
	}
	return value;
}


FIBITMAP* GenericLoader(const char* lpszPathName, int flag = 0) {
	FREE_IMAGE_FORMAT fif = FIF_UNKNOWN;
	// check the file signature and deduce its format
	// (the second argument is currently not used by FreeImage)
	fif = FreeImage_GetFileType(lpszPathName, 0);
	if(fif == FIF_UNKNOWN) {
		// no signature ?
		// try to guess the file format from the file extension
		fif = FreeImage_GetFIFFromFilename(lpszPathName);
	}
	// check that the plugin has reading capabilities ...
	if((fif != FIF_UNKNOWN) && FreeImage_FIFSupportsReading(fif)) {
	// ok, let's load the file
		FIBITMAP *dib = FreeImage_Load(fif, lpszPathName, flag);
		// unless a bad file format, we are done !
		return dib;
	}
	return NULL;
}



int main( int /*argc*/, char ** argv) 
{
	

    //Initialize all SDL subsystems
    if( SDL_Init(SDL_INIT_VIDEO) != 0  )
    {
        return 1;    
    }
    
    SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
    
	//Set up the screen
    screen = SDL_SetVideoMode( 640, 480, 32, SDL_OPENGL);


    //If there was an error in setting up the screen
    if( screen == NULL )
    {
        return 1;    
    }
    
    //Set the window caption
    SDL_WM_SetCaption( "SDL", NULL );
 
/*

	FMOD::System *system;
	FMOD::System_Create(&system);
	system->init(100, FMOD_INIT_NORMAL, 0);
	FMOD::Sound *sound;
	system->createStream("music.mp3", FMOD_DEFAULT, 0, &sound);		
	FMOD::Channel *channel;
	system->playSound(FMOD_CHANNEL_FREE, sound, false, &channel);
*/ 
     InitGL(640, 480);

    FIBITMAP *bitmap = GenericLoader("image.png");
    int w = power_of_two(FreeImage_GetWidth(bitmap));
	int h = power_of_two(FreeImage_GetHeight(bitmap));
	FIBITMAP *bitmap2 = FreeImage_Allocate(w, h, 32);
	FreeImage_Paste(bitmap2, bitmap, 0, 0, 255);
    FreeImage_Save(FIF_PNG, bitmap2, "mybitmap.png", 0);
    FreeImage_Unload(bitmap);

	GLubyte* textura = new GLubyte[4*w*h];
	char* pixeles = (char*)FreeImage_GetBits(bitmap2);
	//FreeImage loads in BGR format, so you need to swap some bytes(Or use GL_BGR).



	for(int j= 0; j<w*h; j++){
		textura[j*4+0]= pixeles[j*4+2];
		textura[j*4+1]= pixeles[j*4+1];
		textura[j*4+2]= pixeles[j*4+0];
		textura[j*4+3]= pixeles[j*4+3];
	}
 
	FreeImage_Unload(bitmap2);
	
	GLuint texturaID;
	glGenTextures(1, &texturaID);

	glBindTexture(GL_TEXTURE_2D, texturaID);
	
//	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);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
    glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA, w, h, 0, GL_RGBA,GL_UNSIGNED_BYTE,(GLvoid*)textura );

	int done = 0;
	while ( ! done ) 
	{
      SDL_Event event;
      while ( SDL_PollEvent(&event)  ) {

        if ( event.type == SDL_QUIT ) {
          done = 1;
        }
        if ( event.type == SDL_KEYDOWN ) {
          if ( event.key.keysym.sym == SDLK_ESCAPE ) {
            done = 1;
		  }
		}
	  }


    glLoadIdentity();
	glTranslatef(0.0f,0.0f,-10.0f);
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);			
	glBegin (GL_QUADS);
	glTexCoord2f (0.0, 0.0); glVertex3f (0, 0, 0);
	glTexCoord2f (1.0, 0.0); glVertex3f (1, 0, 0);
	glTexCoord2f (1.0, 1.0); glVertex3f (1, 1, 0);
	glTexCoord2f (0.0, 1.0); glVertex3f (0, 1, 0);
	glEnd ();
	SDL_GL_SwapBuffers(); 

	}
    
    //Quit SDL
    SDL_Quit();
    
    return 0;    
}