Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
SceneBGImage.cpp
1 #include "SceneBGImage.hh"
2 
3 #include <bias_config.h>
4 #include <Gui/biasgl.h>
5 #include <Base/Image/ImageConvert.hh>
6 #include <Base/Image/ImageIO.hh>
7 //#include <Base/Debug/TimeMeasure.hh>
8 #include <Filter/Rescale.hh>
9 #include <Base/Common/FileHandling.hh>
10 
11 using namespace std;
12 using namespace BIAS;
13 
14 SceneBGImage::
15 SceneBGImage()
16 {
17  IsInitialized_ = false;
18  IsActive_ = true;
19  BackgroundImageTex_ = 0;
20  ImgWidth_ = ImgHeight_ = 0;
21  MaxTextureSize_ = 0;
22  MinFilter_ = GL_NEAREST;
23  MagFilter_ = GL_NEAREST;
24 }
25 
26 
27 int SceneBGImage::
28 SetImage(const Image<unsigned char> &img)
29 {
30  //TimeMeasure timer;
31  //timer.Start();
32  Image <unsigned char> tmp[2];
33  unsigned char current=0,next=1;
34  if((img.GetColorModel() != ImageBase::CM_Grey) &&
35  (img.GetColorModel() != ImageBase::CM_RGB) &&
36  (img.GetColorModel() != ImageBase::CM_BGR) ) {
37  if(ImageConvert::ToRGB(img, tmp[current])!= 0) {
38  BIASERR("Unsupported color model");
39  return -1;
40  }
41  }else{
42  // take copy even if rgb, because PadToPowerOfTwo() will modify image
43  // stringstream sstr;
44  //sstr << "SceneBGImage::SetImage() StorageTypes: img = " << img.GetStorageType() << ", tmp = " << tmp[current].GetStorageType();
45  // cout << sstr.str() << endl;
46  //BEXCEPTION( sstr.str() );
47  tmp[current]=img;
48  }
49  if (MaxTextureSize_ == 0)
50  glGetIntegerv(GL_MAX_TEXTURE_SIZE,&MaxTextureSize_);
51  // cout <<"OpenGL reports MAX_TEXTURE_SIZE: "<<MaxTextureSize_<<endl;
52  // max_texture_size = 2048; // be conservative
53  if (tmp[current].GetWidth()>(unsigned)MaxTextureSize_
54  || tmp[current].GetHeight()>(unsigned)MaxTextureSize_){
55  // BIASERR("image too big, downsampling");
56  // downsample
58  do {
59  if (rescale.DownsampleBy2(tmp[current],tmp[next])!=0){
60  BIASERR("error downsampling");
61  }
62  // swap current and next indeces
63  unsigned char ttt=next;
64  next = current;
65  current = ttt;
66  } while (tmp[current].GetWidth()>(unsigned)MaxTextureSize_ ||
67  tmp[current].GetHeight()>(unsigned)MaxTextureSize_);
68 
69  }
70 
71  // timer.Stop();
72  // cout << "SceneBGImage: rescale: "<<timer.GetRealTime()<<" us\n";
73  // timer.Reset();
74  // timer.Start();
75 
76  if(tmp[current].GetWidth() != ImgWidth_
77  || tmp[current].GetHeight()!= ImgHeight_){
78  return InitializeTexture_(tmp[current]);
79  }
80 
81  if (!IsInitialized_){
82  return InitializeTexture_(tmp[current]);
83  } else {
84  // check width and height and eventually reinit texture
85  glBindTexture(GL_TEXTURE_2D, BackgroundImageTex_);
86 
87  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
88  glPixelStorei(GL_PACK_ALIGNMENT, 1);
89 
90  // need to be power of two
91  tmp[current].PadToPowerOfTwo(255);
92  // timer.Stop();
93  // cout << "SceneBGImage: pad: "<<timer.GetRealTime()<<" us\n";
94  // timer.Reset();
95  // timer.Start();
96  {GLenum err = glGetError(); if (err != GL_NO_ERROR) { BIASERR("OpenGL Error before TexSubImage: " << gluErrorString(err));}}
97 
98  if (tmp[current].GetChannelCount() ==3){
99  switch(tmp[current].GetColorModel()){
100  case ImageBase::CM_RGB:
101  glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0,tmp[current].GetWidth(),
102  tmp[current].GetHeight(), GL_RGB, GL_UNSIGNED_BYTE,
103  tmp[current].GetImageData());
104  break;
105  case ImageBase::CM_BGR:
106  glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0,tmp[current].GetWidth(),
107  tmp[current].GetHeight(), GL_BGR, GL_UNSIGNED_BYTE,
108  tmp[current].GetImageData());
109  break;
110  default:
111  cerr << "invalid color model\n";
112  ABORT;
113  break;
114  }
115  }
116  else if (tmp[current].GetChannelCount() ==1)
117  glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0,tmp[current].GetWidth(),
118  tmp[current].GetHeight(), GL_LUMINANCE, GL_UNSIGNED_BYTE,
119  tmp[current].GetImageData());
120  else {
121  BIASERR("Can not handle texture with "<<tmp[current].GetChannelCount()
122  <<" channels and Colormodel:"<<tmp[current].GetColorModel());
123  return -1;
124  }
125  {GLenum err = glGetError(); if (err != GL_NO_ERROR) { BIASERR("OpenGL Error after TexSubImage: " << gluErrorString(err));}}
126 
127  }
128  // timer.Stop();
129  // cout << "SceneBGImage: texture: "<<timer.GetRealTime()<<" us\n";
130  // timer.Reset();
131  // timer.Start();
132 
133  return 0;
134 }
135 
136 int SceneBGImage::
137 InitializeTexture_(Image<unsigned char> img)
138 {
139  Image<unsigned char> imgtmp;
140 
141  //convert if necessary
142  if((img.GetColorModel() != ImageBase::CM_Grey) &&
143  (img.GetColorModel() != ImageBase::CM_RGB)) {
144  if(ImageConvert::ToRGB(img, imgtmp)!= 0) {
145  BIASERR("Unsupported color model");
146  return -1;
147  }
148  }else{
149  // take copy even if rgb, because PadToPowerOfTwo() will modify image
150  imgtmp=img;
151  }
152 
153  //ignores 0's and names that do not correspond to existing textures
154  glDeleteTextures(1, &BackgroundImageTex_);
155  glGenTextures(1, &BackgroundImageTex_);
156  float maxtexcoordX, maxtexcoordY;
157 
158  // save orig image size to detect changed input data
159  ImgWidth_ = imgtmp.GetWidth();
160  ImgHeight_ = imgtmp.GetHeight();
161  if(ImgWidth_ == 0 || ImgHeight_ == 0) {
162  BIASERR("Image has zero dimension! Moving to uninitialized state.");
163  IsInitialized_ = false;
164  return -1;
165  }
166  // cout <<"downsampled imagesize:"<<img.GetWidth()<<" x "<<img.GetHeight()<<endl;
167  // img is a copy, so we can modify it
168  img.PadToPowerOfTwo(255);
169 
170  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
171  glPixelStorei(GL_PACK_ALIGNMENT, 1);
172 
173  glBindTexture(GL_TEXTURE_2D, BackgroundImageTex_);
174 
175  if (img.GetChannelCount() == 3){
176  switch (img.GetColorModel()){
177  case ImageBase::CM_RGB:
178  glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, img.GetWidth(),img.GetHeight() , 0,
179  GL_RGB,GL_UNSIGNED_BYTE, img.GetImageData());
180  break;
181  case ImageBase::CM_BGR:
182  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, img.GetWidth(),img.GetHeight() , 0,
183  GL_BGR, GL_UNSIGNED_BYTE, img.GetImageData());
184  break;
185  default:
186  cerr << "unsupported color model\n";
187  ABORT;
188  break;
189  }
190  }
191  else if (img.GetChannelCount() == 1)
192  glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, imgtmp.GetWidth(),imgtmp.GetHeight() , 0,
193  GL_LUMINANCE,GL_UNSIGNED_BYTE, imgtmp.GetImageData());
194  else {
195  BIASERR("Can not handle texture with "<<imgtmp.GetChannelCount()
196  <<" channels");
197  return -1;
198  }
199  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
200  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
201  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
202  // GL_NEAREST disables filtering and thus results in exactly the same image
203  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, MagFilter_);
204  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, MinFilter_);
205 
206  maxtexcoordX = float(ImgWidth_)/float(img.GetWidth());
207  maxtexcoordY = float(ImgHeight_)/float(img.GetHeight());
208 // cout <<"ImgSize: "<<ImgWidth_<<" x "<<ImgHeight_<<endl;
209 // cout <<"Padded ImgSize: "<<img.GetWidth()<<" x "<<img.GetHeight()<<endl;
210 // cout <<"maxtexcoord: "<<maxtexcoordX<<" x "<<maxtexcoordY<<endl;
211  TexCoord_[0][0] = 0.0;
212  TexCoord_[0][1] = 0.0;
213 
214  TexCoord_[1][0] = maxtexcoordX;
215  TexCoord_[1][1] = 0.0;
216 
217  TexCoord_[2][0] = maxtexcoordX;
218  TexCoord_[2][1] = maxtexcoordY ;
219 
220  TexCoord_[3][0] = 0.0;
221  TexCoord_[3][1] = maxtexcoordY;
222 
223 // for (unsigned int i=0;i<4;i++)
224 // cout <<"TexCoord["<<i<<"]: "<<TexCoord_[i]<<endl;
225 
226  IsInitialized_ = true;
227  return 0;
228 }
229 
230 
231 
232 
233 
234 void SceneBGImage::
235 Draw()
236 {
237  // CALLINFO
238  if (!IsInitialized_) {
239  BIASERR("BGScene not initialized");
240  return;
241  }
242 
243  glPushAttrib(GL_DEPTH_BUFFER_BIT | GL_TEXTURE_BIT);
244 
245  glMatrixMode(GL_MODELVIEW);
246  glPushMatrix();
247  glLoadIdentity();
248 
249  glMatrixMode(GL_PROJECTION);
250  glPushMatrix();
251  glLoadIdentity();
252 
253  glDepthFunc(GL_LEQUAL);
254 
255  /* Specification and reference agree in description of glOrtho:
256  * give distances of z clipping planes to eye point here. Will
257  * mirror distance value, because the virtual camera is looking into
258  * direction of decreasing z-coordinates, hence positive z-Clipping plane
259  * distances will manifest into clipping planes lying at negative z-values
260  * in the scene! (Reason: Negative vertex coordinates have to be
261  * mapped to the z-values interval of [0,1] in the end. Projection matrix
262  * together with homogenization shall map to normalized device coords. No
263  * mirroring is done during ndc to window-coord mapping.
264  * (see OpenGL Specification 2.0, p.40ff))
265  *
266  * Briefly: specify positive value n, f -> get planes lying at -n, -f,
267  * while camera is looking in direction of -z!
268  *
269  * refer to glOrtho reference or OpenGL Specification 2.0, p.45f. */
270  glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
271 
272  glDepthMask(GL_FALSE);
273 
274  glEnable(GL_TEXTURE_2D);
275  glEnable(GL_BLEND);
276  glBlendFunc(GL_ONE_MINUS_DST_ALPHA, GL_DST_ALPHA);
277 
278  glBindTexture(GL_TEXTURE_2D,BackgroundImageTex_);
279 
280  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
281  glDisable(GL_TEXTURE_GEN_S);
282  glDisable(GL_TEXTURE_GEN_T);
283  glMatrixMode(GL_TEXTURE);
284  glLoadIdentity();
285 
286  glBegin(GL_QUADS);
287  glTexCoord2fv(TexCoord_[0].GetData());
288  glVertex3f(-1.0, 1.0, -1.0);
289  glTexCoord2fv(TexCoord_[3].GetData());
290  glVertex3f(-1.0, -1.0, -1.0);
291  glTexCoord2fv(TexCoord_[2].GetData());
292  glVertex3f(1.0, -1.0, -1.0);
293  glTexCoord2fv(TexCoord_[1].GetData());
294  glVertex3f(1.0, 1.0, -1.0);
295  glEnd();
296 
297  glMatrixMode(GL_PROJECTION);
298  glPopMatrix();
299  glMatrixMode(GL_MODELVIEW);
300  glPopMatrix();
301  glPopAttrib(); //GL_DEPTH_BUFFER_BIT | GL_TEXTURE_BIT
302  glDisable(GL_BLEND);
303 }
304 
305 
306 void SceneBGImage::
307 SetMinMagFilter(int MinFilter,int MagFilter)
308 {
309  MagFilter_ = MagFilter;
310  MinFilter_ = MinFilter;
311  if (IsInitialized_) {
312  glBindTexture(GL_TEXTURE_2D,BackgroundImageTex_);
313  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, MagFilter_);
314  glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, MinFilter_);
315  }
316 }
unsigned int GetWidth() const
Definition: ImageBase.hh:312
unsigned int GetChannelCount() const
returns the number of Color channels, e.g.
Definition: ImageBase.hh:382
unsigned int GetHeight() const
Definition: ImageBase.hh:319
const StorageType * GetImageData() const
overloaded GetImageData() from ImageBase
Definition: Image.hh:137
enum EColorModel GetColorModel() const
Definition: ImageBase.hh:407
int DownsampleBy2(const Image< InputStorageType > &src, Image< OutputStorageType > &dst)
Takes the source image that has to have a defined ROI.
Definition: Rescale.cpp:322
int PadToPowerOfTwo(BIAS::ImageBase &dest, const int &padVal=0) const
increase the size of this image to next power of two (e.g.
Definition: ImageBase.cpp:1154