#include "image_loader.h" #include #include "wx/image.h" #include "wx/wx.h" GLuint* loadImage(wxString path, int* imageWidth, int* imageHeight, int* textureWidth, int* textureHeight) { GLuint* ID=new GLuint[1]; glGenTextures( 1, &ID[0] ); glBindTexture( GL_TEXTURE_2D, *ID ); // the first time, init image handlers (remove this part if you do it somewhere else in your app) static bool is_first_time = true; if(is_first_time) { wxInitAllImageHandlers(); is_first_time = false; } // check the file exists if(!wxFileExists(path)) { wxMessageBox( _("Failed to load resource image") ); exit(1); } wxImage* img=new wxImage( path ); (*imageWidth)=img->GetWidth(); (*imageHeight)=img->GetHeight(); glPixelStorei(GL_UNPACK_ALIGNMENT, 1 ); /* * Many graphics card require that textures be power of two. * Below is a simple implementation, probably not optimal but working. * If your texture sizes are not restricted to power of 2s, you can * of course adapt the bit below as needed. */ float power_of_two_that_gives_correct_width=std::log((float)(*imageWidth))/std::log(2.0); float power_of_two_that_gives_correct_height=std::log((float)(*imageHeight))/std::log(2.0); // check if image dimensions are a power of two if( (int)power_of_two_that_gives_correct_width == power_of_two_that_gives_correct_width && (int)power_of_two_that_gives_correct_height == power_of_two_that_gives_correct_height) { // note: must make a local copy before passing the data to OpenGL, as GetData() returns RGB // and we want the Alpha channel if it's present. Additionally OpenGL seems to interpret the // data upside-down so we need to compensate for that. GLubyte *bitmapData=img->GetData(); GLubyte *alphaData=img->GetAlpha(); int bytesPerPixel = img->HasAlpha() ? 4 : 3; int imageSize = (*imageWidth) * (*imageHeight) * bytesPerPixel; GLubyte *imageData=new GLubyte[imageSize]; int rev_val=(*imageHeight)-1; for(int y=0; y<(*imageHeight); y++) { for(int x=0; x<(*imageWidth); x++) { imageData[(x+y*(*imageWidth))*bytesPerPixel+0]= bitmapData[( x+(rev_val-y)*(*imageWidth))*3]; imageData[(x+y*(*imageWidth))*bytesPerPixel+1]= bitmapData[( x+(rev_val-y)*(*imageWidth))*3 + 1]; imageData[(x+y*(*imageWidth))*bytesPerPixel+2]= bitmapData[( x+(rev_val-y)*(*imageWidth))*3 + 2]; if(bytesPerPixel==4) imageData[(x+y*(*imageWidth))*bytesPerPixel+3]= alphaData[ x+(rev_val-y)*(*imageWidth) ]; }//next }//next // if yes, everything is fine glTexImage2D(GL_TEXTURE_2D, 0, bytesPerPixel, *imageWidth, *imageHeight, 0, img->HasAlpha() ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, imageData); (*textureWidth) = (*imageWidth); (*textureHeight) = (*imageHeight); delete [] imageData; } else // texture is not a power of two. We need to resize it { int newWidth=(int)std::pow( 2.0, (int)(std::ceil(power_of_two_that_gives_correct_width)) ); int newHeight=(int)std::pow( 2.0, (int)(std::ceil(power_of_two_that_gives_correct_height)) ); //printf("Unsupported image size. Recommand values: %i %i\n",newWidth,newHeight); GLubyte *bitmapData=img->GetData(); GLubyte *alphaData=img->GetAlpha(); int old_bytesPerPixel = 3; int bytesPerPixel = img->HasAlpha() ? 4 : 3; int imageSize = newWidth * newHeight * bytesPerPixel; GLubyte *imageData=new GLubyte[imageSize]; int rev_val=(*imageHeight)-1; for(int y=0; yHasAlpha() ? 4 : 3, newWidth, newHeight, 0, img->HasAlpha() ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, imageData); (*textureWidth)=newWidth; (*textureHeight)=newHeight; delete [] imageData; } // set texture parameters as you wish glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // GL_LINEAR glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // GL_LINEAR glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); return ID; }