Missing library from test link list.
[dcpomatic.git] / hacks / gl / image_loader.cc
1 #include "image_loader.h"
2 #include <cmath>
3
4 #include "wx/image.h"
5 #include "wx/wx.h"
6
7
8 GLuint* loadImage(wxString path, int* imageWidth, int* imageHeight, int* textureWidth, int* textureHeight)
9 {
10
11         GLuint* ID=new GLuint[1];
12         glGenTextures( 1, &ID[0] );
13
14         glBindTexture( GL_TEXTURE_2D, *ID );
15
16         // the first time, init image handlers (remove this part if you do it somewhere else in your app)
17         static bool is_first_time = true;
18         if(is_first_time)
19         {
20                 wxInitAllImageHandlers();
21
22                 is_first_time = false;
23         }
24
25         // check the file exists
26         if(!wxFileExists(path))
27         {
28                 wxMessageBox( _("Failed to load resource image") );
29                 exit(1);
30         }
31
32         wxImage* img=new wxImage( path );
33
34         (*imageWidth)=img->GetWidth();
35         (*imageHeight)=img->GetHeight();
36
37         glPixelStorei(GL_UNPACK_ALIGNMENT,   1   );
38
39     /*
40      * Many graphics card require that textures be power of two.
41      * Below is a simple implementation, probably not optimal but working.
42      * If your texture sizes are not restricted to power of 2s, you can
43      * of course adapt the bit below as needed.
44      */
45
46         float power_of_two_that_gives_correct_width=std::log((float)(*imageWidth))/std::log(2.0);
47         float power_of_two_that_gives_correct_height=std::log((float)(*imageHeight))/std::log(2.0);
48
49         // check if image dimensions are a power of two
50         if( (int)power_of_two_that_gives_correct_width == power_of_two_that_gives_correct_width &&
51             (int)power_of_two_that_gives_correct_height == power_of_two_that_gives_correct_height)
52         {
53                 // note: must make a local copy before passing the data to OpenGL, as GetData() returns RGB
54                 // and we want the Alpha channel if it's present. Additionally OpenGL seems to interpret the
55                 // data upside-down so we need to compensate for that.
56                 GLubyte *bitmapData=img->GetData();
57                 GLubyte *alphaData=img->GetAlpha();
58
59                 int bytesPerPixel = img->HasAlpha() ?  4 : 3;
60
61                 int imageSize = (*imageWidth) * (*imageHeight) * bytesPerPixel;
62                 GLubyte *imageData=new GLubyte[imageSize];
63
64                 int rev_val=(*imageHeight)-1;
65
66                 for(int y=0; y<(*imageHeight); y++)
67                 {
68                         for(int x=0; x<(*imageWidth); x++)
69                         {
70                                 imageData[(x+y*(*imageWidth))*bytesPerPixel+0]=
71                                         bitmapData[( x+(rev_val-y)*(*imageWidth))*3];
72
73                                 imageData[(x+y*(*imageWidth))*bytesPerPixel+1]=
74                                         bitmapData[( x+(rev_val-y)*(*imageWidth))*3 + 1];
75
76                                 imageData[(x+y*(*imageWidth))*bytesPerPixel+2]=
77                                         bitmapData[( x+(rev_val-y)*(*imageWidth))*3 + 2];
78
79                                 if(bytesPerPixel==4) imageData[(x+y*(*imageWidth))*bytesPerPixel+3]=
80                                         alphaData[ x+(rev_val-y)*(*imageWidth) ];
81                         }//next
82                 }//next
83
84                 // if yes, everything is fine
85                 glTexImage2D(GL_TEXTURE_2D,
86                              0,
87                              bytesPerPixel,
88                              *imageWidth,
89                              *imageHeight,
90                              0,
91                              img->HasAlpha() ?  GL_RGBA : GL_RGB,
92                              GL_UNSIGNED_BYTE,
93                              imageData);
94
95                 (*textureWidth)  = (*imageWidth);
96                 (*textureHeight) = (*imageHeight);
97
98                 delete [] imageData;
99         }
100         else // texture is not a power of two. We need to resize it
101         {
102
103                 int newWidth=(int)std::pow( 2.0, (int)(std::ceil(power_of_two_that_gives_correct_width)) );
104                 int newHeight=(int)std::pow( 2.0, (int)(std::ceil(power_of_two_that_gives_correct_height)) );
105
106                 //printf("Unsupported image size. Recommand values: %i %i\n",newWidth,newHeight);
107
108                 GLubyte *bitmapData=img->GetData();
109                 GLubyte        *alphaData=img->GetAlpha();
110
111                 int old_bytesPerPixel = 3;
112                 int bytesPerPixel = img->HasAlpha() ?  4 : 3;
113
114                 int imageSize = newWidth * newHeight * bytesPerPixel;
115                 GLubyte *imageData=new GLubyte[imageSize];
116
117                 int rev_val=(*imageHeight)-1;
118
119                 for(int y=0; y<newHeight; y++)
120                 {
121                         for(int x=0; x<newWidth; x++)
122                         {
123
124                                 if( x<(*imageWidth) && y<(*imageHeight) ){
125                                         imageData[(x+y*newWidth)*bytesPerPixel+0]=
126                                         bitmapData[( x+(rev_val-y)*(*imageWidth))*old_bytesPerPixel + 0];
127
128                                         imageData[(x+y*newWidth)*bytesPerPixel+1]=
129                                                 bitmapData[( x+(rev_val-y)*(*imageWidth))*old_bytesPerPixel + 1];
130
131                                         imageData[(x+y*newWidth)*bytesPerPixel+2]=
132                                                 bitmapData[( x+(rev_val-y)*(*imageWidth))*old_bytesPerPixel + 2];
133
134                                         if(bytesPerPixel==4) imageData[(x+y*newWidth)*bytesPerPixel+3]=
135                                                 alphaData[ x+(rev_val-y)*(*imageWidth) ];
136
137                                 }
138                                 else
139                                 {
140
141                                         imageData[(x+y*newWidth)*bytesPerPixel+0] = 0;
142                                         imageData[(x+y*newWidth)*bytesPerPixel+1] = 0;
143                                         imageData[(x+y*newWidth)*bytesPerPixel+2] = 0;
144                                         if(bytesPerPixel==4) imageData[(x+y*newWidth)*bytesPerPixel+3] = 0;
145                                 }
146
147                         }//next
148                 }//next
149
150
151                 glTexImage2D(GL_TEXTURE_2D,
152                                          0,
153                                          img->HasAlpha() ?  4 : 3,
154                                          newWidth,
155                                          newHeight,
156                                          0,
157                                          img->HasAlpha() ?  GL_RGBA : GL_RGB,
158                                          GL_UNSIGNED_BYTE,
159                                          imageData);
160
161                 (*textureWidth)=newWidth;
162                 (*textureHeight)=newHeight;
163
164                 delete [] imageData;
165         }
166
167         // set texture parameters as you wish
168         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // GL_LINEAR
169         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // GL_LINEAR
170
171         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
172         glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
173
174         return ID;
175
176 }