PDA

View Full Version : freeImage example code



phamt78
04-18-2008, 02:29 AM
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.

RGHP
04-18-2008, 11:33 AM
I've post before about that, look at the end of this thread:

http://www.opengl.org/discussion_boards/...3307#Post233307 (http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Main=46341&Number=233307#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

RGHP
04-18-2008, 11:36 AM
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!

phamt78
04-18-2008, 03:59 PM
Thanks RGHP i'll give it a try.

Nicolas Lelong
04-19-2008, 05:40 AM
In that sample code I converted BGR to RGB in the CPU. It's faster if you do that in a shader.
Bye!

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

-NiCo-
04-19-2008, 08:02 AM
@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).

RGHP
04-19-2008, 04:03 PM
ajam!

phamt78
04-19-2008, 05:45 PM
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(&amp;system);
system->init(100, FMOD_INIT_NORMAL, 0);
FMOD::Sound *sound;
system->createStream("music.mp3", FMOD_DEFAULT, 0, &amp;sound);
FMOD::Channel *channel;
system->playSound(FMOD_CHANNEL_FREE, sound, false, &amp;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, &amp;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(&amp;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;
}

dorbie
04-19-2008, 11:10 PM
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.

phamt78
04-20-2008, 03:34 AM
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.

RGHP
04-20-2008, 07:40 AM
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?

phamt78
04-20-2008, 10:02 AM
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.

-NiCo-
04-20-2008, 02:25 PM
Why not create a transparent GL texture once and update a rectangular region of the texture with your image data using glTexSubImage2D?

phamt78
04-20-2008, 05:47 PM
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);

phamt78
04-22-2008, 11:19 AM
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) &amp;&amp; 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(&amp;system);
system->init(100, FMOD_INIT_NORMAL, 0);
FMOD::Sound *sound;
system->createStream("music.mp3", FMOD_DEFAULT, 0, &amp;sound);
FMOD::Channel *channel;
system->playSound(FMOD_CHANNEL_FREE, sound, false, &amp;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, &amp;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(&amp;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

RGHP
04-22-2008, 07:53 PM
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

phamt78
04-22-2008, 11:18 PM
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.

phamt78
04-23-2008, 01:53 AM
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);

-NiCo-
04-23-2008, 02:07 AM
Well, that could've fixed it, but nearest sampling can result in some crappy quality :)

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

phamt78
04-23-2008, 08:05 AM
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) &amp;&amp; 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(&amp;system);
system->init(100, FMOD_INIT_NORMAL, 0);
FMOD::Sound *sound;
system->createStream("music.mp3", FMOD_DEFAULT, 0, &amp;sound);
FMOD::Channel *channel;
system->playSound(FMOD_CHANNEL_FREE, sound, false, &amp;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, &amp;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(&amp;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;
}