00001 #include <assert.h>
00002 #include <ipFunc/mitkIpFunc.h>
00003 #include "widget.h"
00004 #include "texture.h"
00005 #include "image.h"
00006
00007 static unsigned int
00008 power2 (const unsigned int x)
00009 {
00010 unsigned int y = 1;
00011
00012 while (y < x)
00013 {
00014 y *= 2;
00015 }
00016 return y;
00017 }
00018
00019 const unsigned int iil4mitkImage::_bytes [] = {1, 2, 3, 4, 3,4};
00020
00021 iil4mitkImage::iil4mitkImage (unsigned int size)
00022 : _width (0), _height (0), _rx (0), _ry (0), _rw (0), _rh (0),
00023 _model (INTENSITY), _interpolation (false), _pixels (NULL),
00024 _internal (GL_LUMINANCE), _size(size)
00025 {
00026
00027 }
00028
00029 iil4mitkImage::~iil4mitkImage ()
00030 {
00031 clear ();
00032 }
00033
00034 void
00035 iil4mitkImage::setImage (const unsigned int width, const unsigned int height,
00036 const int model, unsigned char *data)
00037 {
00038 assert (width > 0);
00039 assert (height > 0);
00040
00041 _width = width;
00042 _height = height;
00043 _model = model;
00044 _pixels = data;
00045 invalidateTextures ();
00046 }
00047
00048 unsigned int
00049 iil4mitkImage::imageWidth() const
00050 {
00051 return _width;
00052 }
00053
00054 unsigned int
00055 iil4mitkImage::imageHeight () const
00056 {
00057 return _height;
00058 }
00059
00060 void
00061 iil4mitkImage::setRegion (const unsigned int x, const unsigned y,
00062 const unsigned w, const unsigned h)
00063 {
00064 assert (x + w <= _width);
00065 assert (y + h <= _height);
00066
00067 if ((_rx != x) || (_ry != y) || (_rw != w) || (_rh != h)) {
00068 _rx = x; _ry = y; _rw = w; _rh = h;
00069 invalidateTextures ();
00070 }
00071 }
00072
00073 unsigned int
00074 iil4mitkImage::regionX () const
00075 {
00076 return _rx;
00077 }
00078
00079 unsigned int
00080 iil4mitkImage::regionY () const
00081 {
00082 return _ry;
00083 }
00084
00085 unsigned int
00086 iil4mitkImage::regionWidth () const
00087 {
00088 return _rw;
00089 }
00090
00091 unsigned int
00092 iil4mitkImage::regionHeight () const
00093 {
00094 return _rh;
00095 }
00096
00097 void
00098 iil4mitkImage::clear ()
00099 {
00100 _width = _height = 0;
00101 _rx = _ry = _rw = _rh = 0;
00102 _model = INTENSITY;
00103 _pixels = NULL;
00104 _internal = GL_LUMINANCE;
00105
00106 std::map<void*,Textures*>::iterator i;
00107 for (i=_textures.begin(); i!=_textures.end(); ++i) {
00108 for (unsigned int j = 0; j < (*i).second->size (); j++) {
00109 delete (*(*i).second)[j];
00110 }
00111 delete i->second;
00112 }
00113 _textures.clear ();
00114 }
00115
00116 float
00117 iil4mitkImage::width () const
00118 {
00119 return (float) _rw;
00120 }
00121
00122 float
00123 iil4mitkImage::height () const
00124 {
00125 return (float) _rh;
00126 }
00127
00128 int
00129 iil4mitkImage::model () const
00130 {
00131 return _model;
00132 }
00133
00134 void
00135 iil4mitkImage::setInterpolation (const bool on)
00136 {
00137 _interpolation = on;
00138 }
00139
00140 bool
00141 iil4mitkImage::interpolation () const
00142 {
00143 return _interpolation;
00144 }
00145
00146 void
00147 iil4mitkImage::display (iil4mitkWidget* widget)
00148 {
00149 GLdouble planeX [] = {-1, 0, 0, regionWidth ()};
00150 GLdouble planeY [] = {0, -1, 0, regionHeight ()};
00151
00152 if (!visible ()
00153 || (constraint () && (widget != constraint ())))
00154 {
00155 return;
00156 }
00157
00158 if (_pixels)
00159 {
00160 assert (_rx + _rw <= _width);
00161 assert (_ry + _rh <= _height);
00162
00163 GLboolean texturing = glIsEnabled (GL_TEXTURE_2D);
00164 GLboolean blending = glIsEnabled (GL_BLEND);
00165
00166 glClipPlane (GL_CLIP_PLANE4, planeX);
00167 glEnable (GL_CLIP_PLANE4);
00168 glClipPlane (GL_CLIP_PLANE5, planeY);
00169 glEnable (GL_CLIP_PLANE5);
00170
00171 if ((_model == INTENSITY_ALPHA) || (_model == COLOR_ALPHA) || (_model == RGB) || (_model == RGBA))
00172 {
00173 glEnable (GL_BLEND);
00174 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00175 }
00176
00177 glEnable (GL_TEXTURE_2D);
00178 glMatrixMode (GL_MODELVIEW);
00179 glPushMatrix ();
00180 glColor4f (red (), green (), blue (), alpha ());
00181 glTranslatef (x (), y (), 0.0);
00182 drawTextures (widget);
00183 glPopMatrix ();
00184
00185 glDisable (GL_CLIP_PLANE4);
00186 glDisable (GL_CLIP_PLANE5);
00187
00188 if (texturing == GL_FALSE) glDisable (GL_TEXTURE_2D);
00189 if (blending == GL_FALSE) glDisable (GL_BLEND);
00190 }
00191 }
00192
00193 void iil4mitkImage::drawTextures (iil4mitkWidget* widget)
00194 {
00195 const unsigned int s = _size;
00196 unsigned int n, m;
00197
00198 n = (unsigned int) ceilf ((float) _rw / (float) (s - 2));
00199 m = (unsigned int) ceilf ((float) _rh / (float) (s - 2));
00200
00201
00202
00203 Textures* textures;
00204 {
00205 iil4mitkWidget* w;
00206 unsigned int available, total;
00207
00208
00209 w = (false ? NULL : widget);
00210 std::map<void*,Textures*>::iterator tex_it = _textures.find (w);
00211 if(tex_it!=_textures.end())
00212 textures = tex_it->second;
00213 else
00214 textures = NULL;
00215
00216 if (!textures) {
00217 textures = new Textures ();
00218 typedef std::pair <void*, std::vector<_iil4mitkTexture*>* > TexturePair;
00219 _textures.insert (TexturePair(w, textures));
00220 }
00221 available = textures->size ();
00222 total = n * m;
00223
00224 int iii;
00225 for (unsigned int i = available; i < total; i++)
00226 {
00227 textures->push_back(new _iil4mitkTexture (w));
00228 iii=textures->size ();
00229 }
00230 widget->MakeCurrent ();
00231 }
00232
00233
00234
00235 glScalef ((float) (s-2), (float) (s-2), 1.0);
00236 for (unsigned int i = 0; i < n; i++)
00237 {
00238 unsigned int pos [2];
00239 unsigned int len [2];
00240 unsigned int tex [2];
00241 float res [2];
00242
00243 pos [0] = _rx+i*(s-2);
00244 len [0] = (pos[0]+(s-2)>_rw ? _rw-pos[0] : s-2);
00245 tex [0] = power2(s);
00246 res [0] = 1.0f/tex[0];
00247 for (unsigned int j = 0; j < m; j++)
00248 {
00249 _iil4mitkTexture* texture;
00250
00251 texture = (*textures)[i*m+j];
00252 pos [1] = _ry+j*(s-2);
00253 len [1] = (pos[1]+(s-2)>_rh ? _rh-pos[1] : s-2);
00254 tex [1] = power2(s);
00255 res [1] = 1.0f/tex[1];
00256
00257
00258 if (true) {
00259
00260 texture->bind ();
00261
00262 texture->setSize (tex[0], tex[1]);
00263 texture->setModel (_model);
00264 texture->setInterpolation (_interpolation);
00265 if (!texture->isValid ())
00266 {
00267 updateTexture (texture, pos[0], pos[1], len[0], len[1]);
00268 }
00269
00270 glBegin (GL_QUADS);
00271 glTexCoord2f (res[0], res[1]); glVertex3f (0.0, 0.0, 0.0);
00272 glTexCoord2f (1.0-res[0], res[1]); glVertex3f (1.0, 0.0, 0.0);
00273 glTexCoord2f (1.0-res[0], 1.0-res[1]); glVertex3f (1.0, 1.0, 0.0);
00274 glTexCoord2f (res[0], 1.0-res[1]); glVertex3f (0.0, 1.0, 0.0);
00275 glEnd ();
00276 }
00277 glTranslatef (0.0, 1.0, 0.0);
00278 }
00279 glTranslatef (1.0, -((float) m), 0.0);
00280 }
00281 }
00282
00283 void
00284 iil4mitkImage::remove (iil4mitkWidget* widget)
00285 {
00286 std::map<void*,Textures*>::iterator i =
00287 _textures.find (widget);
00288 for (unsigned int j = 0; j < (*i).second->size (); j++)
00289 {
00290 delete (*(*i).second)[j];
00291 }
00292 delete i->second;
00293 _textures.erase(i);
00294 }
00295
00296 void
00297 iil4mitkImage::invalidateTextures ()
00298 {
00299 std::map<void*,Textures*>::iterator i;
00300 for (i=_textures.begin(); i!=_textures.end(); ++i)
00301 {
00302 for (unsigned int j = 0; j < (*i).second->size (); j++)
00303 {
00304 (*(*i).second)[j]->invalidate ();
00305 }
00306 }
00307 }
00308
00309 void
00310 iil4mitkImage::updateTexture (_iil4mitkTexture* texture, unsigned int x, unsigned int y, unsigned int w, unsigned int h)
00311 {
00312 unsigned int p2w = texture->width ();
00313 unsigned int p2h = texture->height ();
00314 unsigned int size = p2w * p2h * _bytes [_model];
00315 unsigned char *region = (unsigned char *) malloc (size * sizeof (unsigned char));
00316 unsigned int left = (x == 0 ? 0 : 1);
00317 unsigned int right = (x+w == _rw ? 0 : 1);
00318 unsigned int top = (y == 0 ? 0 : 1);
00319 unsigned int bottom = (y + h == _rh ? 0 : 1);
00320
00321 if (x == 0)
00322 {
00323 copyImage (x, y-top, 1, h+top+bottom, region, p2w, p2h, 0, 1-top);
00324 }
00325 else
00326 {
00327 copyImage (x-1, y-top, 1, h+top+bottom, region, p2w, p2h, 0, 1-top);
00328 }
00329 if (x+w == _rw)
00330 {
00331 copyImage (x+w-1, y-top, 1, h+top+bottom, region, p2w, p2h, w+1, 1-top);
00332 }
00333 else
00334 {
00335 copyImage (x+w, y-top, 1, h+top+bottom, region, p2w, p2h, w+1, 1-top);
00336 }
00337 if (y == 0)
00338 {
00339 copyImage (x-left, y, w+left+right, 1, region, p2w, p2h, 1-left, 0);
00340 }
00341 else
00342 {
00343 copyImage (x-left, y-1, w+left+right, 1, region, p2w, p2h, 1-left, 0);
00344 }
00345 if (y+h == _rh)
00346 {
00347 copyImage (x-left, y+h-1, w+left+right, 1, region, p2w, p2h, 1-left, h+1);
00348 }
00349 else
00350 {
00351 copyImage (x-left, y+h, w+left+right, 1, region, p2w, p2h, 1-left, h+1);
00352 }
00353 copyImage (x, y, w, h, region, p2w, p2h, 1, 1);
00354 texture->setData (region);
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371 free (region);
00372 }
00373
00374 void iil4mitkImage::copyImage(unsigned int x, unsigned int y, unsigned int w,
00375 unsigned int h, unsigned char* data, unsigned int width, unsigned int,
00376 unsigned int xoffset, unsigned int yoffset)
00377 {
00378 const unsigned int bytes = _bytes [_model];
00379 const unsigned char *src = _pixels + (y * _width + x) * bytes;
00380 unsigned char *dst = data + (yoffset * width + xoffset) * bytes;
00381
00382 for (unsigned int i = 0; i < h; i++)
00383 {
00384 memcpy (dst, src, w * bytes);
00385 src += _width * bytes;
00386 dst += width * bytes;
00387 }
00388 }
00389
00390 unsigned int
00391 iil4mitkImage::bpe ()
00392 {
00393 return _bytes [_model] * 8;
00394 }
00395
00396 unsigned char*
00397 iil4mitkImage::pixels ()
00398 {
00399 return _pixels;
00400 }
00401
00402 iil4mitkImage*
00403 iil4mitkImage::find (const iil4mitkItem* item)
00404 {
00405 iil4mitkImage* result = NULL;
00406
00407 if (!item) return (iil4mitkImage *) NULL;
00408
00409 if ( dynamic_cast<const iil4mitkImage*>(item)!=NULL ) {
00410 result = const_cast<iil4mitkImage*>(dynamic_cast<const iil4mitkImage*>(item));
00411 }
00412 return (iil4mitkImage *) result;
00413 }