00001 #include <assert.h>
00002 #include "texture.h"
00003 #include "picimage.h"
00004 #include <cmath>
00005
00006 iil4mitkPicImage::iil4mitkPicImage (unsigned int size)
00007 : iil4mitkImage(size), _pic (NULL), _min (0.0), _max (0.0), _colors (NULL), _binary (false), _mask (false), _outline(false), _outlineWidth(1.0)
00008 {
00009 }
00010
00011 iil4mitkPicImage::~iil4mitkPicImage ()
00012 {
00013 }
00014
00015 void
00016 iil4mitkPicImage::setImage (mitkIpPicDescriptor* pic, int model)
00017 {
00018 assert (pic);
00019 assert (pic->dim >= 2);
00020
00021 _pic = pic;
00022 iil4mitkImage::setImage (pic->n[0], pic->n[1], model, (unsigned char *) pic->data);
00023 }
00024
00025 mitkIpPicDescriptor*
00026 iil4mitkPicImage::image () const
00027 {
00028 return _pic;
00029 }
00030
00031 void
00032 iil4mitkPicImage::setExtrema (const float minimum, const float maximum)
00033 {
00034
00035
00036 _min = minimum;
00037 _max = maximum;
00038 invalidateTextures ();
00039 }
00040
00041 void
00042 iil4mitkPicImage::setWindow (const float level, const float window)
00043 {
00044
00045 _min = level - window / 2.0;
00046 _max = _min + window;
00047 invalidateTextures ();
00048 }
00049
00050 float
00051 iil4mitkPicImage::minimum () const
00052 {
00053 return _min;
00054 }
00055
00056 float
00057 iil4mitkPicImage::maximum () const
00058 {
00059 return _max;
00060 }
00061
00062 float
00063 iil4mitkPicImage::level () const
00064 {
00065 return (_min + _max) / 2.0;
00066 }
00067
00068 float
00069 iil4mitkPicImage::window () const
00070 {
00071 return (_max - _min);
00072 }
00073
00074 void
00075 iil4mitkPicImage::setOpacityExtrema (const float minimum, const float maximum)
00076 {
00077
00078
00079 _minOpac = minimum;
00080 _maxOpac = maximum;
00081 invalidateTextures ();
00082 }
00083
00084 void
00085 iil4mitkPicImage::setOpacityWindow (const float level, const float window)
00086 {
00087
00088 _minOpac = level - window / 2.0;
00089 _maxOpac = _minOpac + window;
00090 invalidateTextures ();
00091 }
00092
00093 float
00094 iil4mitkPicImage::minimumOpacity () const
00095 {
00096 return _minOpac;
00097 }
00098
00099 float
00100 iil4mitkPicImage::maximumOpacity () const
00101 {
00102 return _maxOpac;
00103 }
00104
00105 float
00106 iil4mitkPicImage::levelOpacity () const
00107 {
00108 return (_minOpac + _maxOpac) / 2.0;
00109 }
00110
00111 float
00112 iil4mitkPicImage::windowOpacity () const
00113 {
00114 return (_maxOpac - _minOpac);
00115 }
00116
00117 void
00118 iil4mitkPicImage::setColors (const unsigned char* colors)
00119 {
00120 _colors = colors;
00121 }
00122
00123 const unsigned char*
00124 iil4mitkPicImage::colors () const
00125 {
00126 return _colors;
00127 }
00128
00129 void
00130 iil4mitkPicImage::setBinary (const bool on)
00131 {
00132 if (_binary != on) {
00133 if (on) {
00134 _mask = false;
00135 }
00136 _binary = on;
00137 invalidateTextures ();
00138 }
00139 }
00140
00141 bool
00142 iil4mitkPicImage::binary () const
00143 {
00144 return _binary;
00145 }
00146
00147 void
00148 iil4mitkPicImage::setOutline (const bool on)
00149 {
00150 if (_binary) {
00151 _outline = on;
00152 }
00153 }
00154
00155 void
00156 iil4mitkPicImage::setOutlineWidth(float width)
00157 {
00158 if (_binary) {
00159 _outlineWidth = width;
00160 }
00161 }
00162
00163
00164 bool
00165 iil4mitkPicImage::outline () const
00166 {
00167 return _outline;
00168 }
00169
00170 void
00171 iil4mitkPicImage::setMask (const bool on)
00172 {
00173 if (_mask != on) {
00174 if (on) {
00175 _binary = false;
00176 }
00177 _mask = on;
00178 invalidateTextures ();
00179 }
00180 }
00181
00182 bool
00183 iil4mitkPicImage::mask () const
00184 {
00185 return _mask;
00186 }
00187
00188 void
00189 iil4mitkPicImage::clear ()
00190 {
00191 _pic = NULL;
00192 _min = _max = 0.0;
00193 _minOpac = _maxOpac = 0.0;
00194 _colors = NULL;
00195 _binary = false;
00196 _mask = false;
00197 _outline = false;
00198 iil4mitkImage::clear ();
00199 }
00200
00201 iil4mitkPicImage*
00202 iil4mitkPicImage::find (const iil4mitkItem* item)
00203 {
00204 iil4mitkPicImage* result = NULL;
00205
00206 if (!item) return NULL;
00207
00208 if ( dynamic_cast<const iil4mitkPicImage*>(item)!=NULL ) {
00209 result = const_cast<iil4mitkPicImage*>(dynamic_cast<const iil4mitkPicImage*>(item));
00210 }
00211 return result;
00212 }
00213
00214 #define MASK_INTENSITIES(TYPE, PIC) \
00215 { \
00216 TYPE* source = (TYPE *) src; \
00217 unsigned char* dest = dst; \
00218 register float a; \
00219 if (model () == INTENSITY) \
00220 while (dest < eol) { \
00221 a = source [0] * scale - bias; \
00222 *dest = (a > 255.0 ? 0 : (a < 0.0 ? 0 : 255)); \
00223 source++; \
00224 dest++; \
00225 } else \
00226 if (model () == INTENSITY_ALPHA) \
00227 while (dest < eol) { \
00228 a = source [0] * scale - bias; \
00229 dest [1] = dest [0] = (a > 255.0 ? 0 : (a < 0.0 ? 0 : 255)); \
00230 source++; \
00231 dest += 2; \
00232 } \
00233 }
00234
00235 #define BINARY_INTENSITIES(TYPE, PIC) \
00236 { \
00237 TYPE* source = (TYPE *) src; \
00238 unsigned char* dest = dst; \
00239 register float a; \
00240 if (model () == INTENSITY) \
00241 while (dest < eol) { \
00242 a = source [0] * scale - bias; \
00243 *dest = (a > 255.0 ? 255 : (a < 0.0 ? 0 : 255)); \
00244 source++; \
00245 dest++; \
00246 } else \
00247 if (model () == INTENSITY_ALPHA) \
00248 while (dest < eol) { \
00249 a = source [0] * scale - bias; \
00250 dest [0] = (a > 255.0 ? 255 : (a < 0.0 ? 0 : 255)); \
00251 dest [1] = (a > 0.0 ? 255 : 0); \
00252 source++; \
00253 dest += 2; \
00254 } \
00255 }
00256
00257 #define LIMIT_INTENSITIES(TYPE, PIC) \
00258 { \
00259 TYPE* source = (TYPE *) src; \
00260 unsigned char* dest = dst; \
00261 register unsigned int i; \
00262 register float a,b,c,d; \
00263 if (model () == INTENSITY) \
00264 while (dest < eol) { \
00265 a = source [0] * scale - bias; \
00266 *dest = (a > 255.0 ? 255 : (a < 0.0 ? 0 : (unsigned char) a)); \
00267 source++; \
00268 dest++; \
00269 } else \
00270 if (model () == INTENSITY_ALPHA) \
00271 while (dest < eol) { \
00272 a = source [0] * scale - bias; \
00273 dest [0] = (a > 255.0 ? 255 : (a < 0.0 ? 0 : (unsigned char) a)); \
00274 dest [1] = (a > 0.0 ? 255 : 0); \
00275 source++; \
00276 dest += 2; \
00277 } else \
00278 if ((model () == COLOR) && _colors) \
00279 while (dest < eol) { \
00280 a = source [0] * scale - bias; \
00281 i = (a > 255.0 ? 255 : (a < 0.0 ? 0 : (unsigned char) a)); \
00282 dest [0] = _colors [i*3]; \
00283 dest [1] = _colors [i*3+1]; \
00284 dest [2] = _colors [i*3+2]; \
00285 source++; \
00286 dest += 3; \
00287 } else \
00288 if ((model () == COLOR_ALPHA) && _colors) \
00289 while (dest < eol) { \
00290 a = source [0] * scale - bias; \
00291 i = (a > 255.0 ? 255 : (a < 0.0 ? 0 : (unsigned char) a)); \
00292 dest [0] = _colors [i*4 ]; \
00293 dest [1] = _colors [i*4+1]; \
00294 dest [2] = _colors [i*4+2]; \
00295 dest [3] = _colors [i*4+3]; \
00296 source++; \
00297 dest += 4; \
00298 } else \
00299 if ((model () == COLOR) && !_colors) \
00300 while (dest < eol) { \
00301 a = source [0] * scale - bias; \
00302 b = source [slice] * scale - bias; \
00303 c = source [2*slice] * scale - bias; \
00304 dest [0] = (a > 255.0 ? 255 : (a < 0.0 ? 0 : (unsigned char) a)); \
00305 dest [1] = (b > 255.0 ? 255 : (b < 0.0 ? 0 : (unsigned char) b)); \
00306 dest [2] = (c > 255.0 ? 255 : (c < 0.0 ? 0 : (unsigned char) c)); \
00307 source++; \
00308 dest += 3; \
00309 } \
00310 if ((model () == COLOR_ALPHA) && !_colors) \
00311 { \
00312 a = source [0] * scale - bias; \
00313 b = source [slice] * scale - bias; \
00314 c = source [2*slice] * scale - bias; \
00315 d = source [3*slice] * scale - bias; \
00316 dest [0] = (a > 255.0 ? 255 : (a < 0.0 ? 0 : (unsigned char) a)); \
00317 dest [1] = (b > 255.0 ? 255 : (b < 0.0 ? 0 : (unsigned char) b)); \
00318 dest [2] = (c > 255.0 ? 255 : (c < 0.0 ? 0 : (unsigned char) c)); \
00319 dest [3] = (d > 255.0 ? 255 : (d < 0.0 ? 0 : (unsigned char) d)); \
00320 source++; \
00321 dest += 4; \
00322 } \
00323 }
00324
00325
00326 #ifdef USE_MMX
00327 #define MAXSHORT 32767
00328 static void extrema (unsigned char* dst, short* src, const unsigned int num, const short minimum, const short maximum)
00329 {
00330 const short low = -1024;
00331 const short up = MAXSHORT - (maximum - low);
00332 const short down = (minimum - low) + up;
00333 const short scale = (255.0f/(float) (maximum-minimum)) * 256;
00334 const short values [] = {
00335 low,
00336 low,
00337 low,
00338 low,
00339 up,
00340 up,
00341 up,
00342 up,
00343 down,
00344 down,
00345 down,
00346 down,
00347 scale,
00348 scale,
00349 scale,
00350 scale
00351 };
00352 const unsigned int n = num / 16;
00353
00354 __asm__ __volatile__ (
00355 ".align 16 \n\t"
00356 "l1: \n\t"
00357 "prefetcht0 64(%1) \n\t"
00358
00359 "movq (%1),%%mm0 \n\t"
00360 "movq 8(%1),%%mm1 \n\t"
00361 "psubsw (%2),%%mm0 \n\t"
00362 "psubsw (%2),%%mm1 \n\t"
00363 "paddsw 8(%2),%%mm0 \n\t"
00364 "paddsw 8(%2),%%mm1 \n\t"
00365 "psubusw 16(%2),%%mm0 \n\t"
00366 "psubusw 16(%2),%%mm1 \n\t"
00367 "pmullw 24(%2),%%mm0 \n\t"
00368 "pmullw 24(%2),%%mm1 \n\t"
00369 "psrlw $8,%%mm0 \n\t"
00370 "psrlw $8,%%mm1 \n\t"
00371 "packuswb %%mm1,%%mm0 \n\t"
00372 "movntq %%mm0,(%0) \n\t"
00373
00374 "movq 16(%1),%%mm2 \n\t"
00375 "movq 24(%1),%%mm3 \n\t"
00376 "psubsw (%2),%%mm2 \n\t"
00377 "psubsw (%2),%%mm3 \n\t"
00378 "paddsw 8(%2),%%mm2 \n\t"
00379 "paddsw 8(%2),%%mm3 \n\t"
00380 "psubusw 16(%2),%%mm2 \n\t"
00381 "psubusw 16(%2),%%mm3 \n\t"
00382 "pmullw 24(%2),%%mm2 \n\t"
00383 "pmullw 24(%2),%%mm3 \n\t"
00384 "psrlw $8,%%mm2 \n\t"
00385 "psrlw $8,%%mm3 \n\t"
00386 "packuswb %%mm3,%%mm2 \n\t"
00387 "movntq %%mm2,8(%0) \n\t"
00388
00389 "emms \n\t"
00390 "add $16,%0 \n\t"
00391 "add $32,%1 \n\t"
00392 "dec %3 \n\t"
00393 "jnz l1 \n\t"
00394 "emms \n\t"
00395 :
00396 :"r" (dst), "r" (src), "r" (values), "r" (n)
00397 );
00398 }
00399 #endif
00400
00401 #ifndef PIC_IMAGE_PI
00402 #define PIC_IMAGE_PI 3.141592653589
00403 #endif
00404
00405
00406
00407 template<class T>
00408 void RGBtoHSI(T* RGB, T* HSI) {
00409 T R = RGB[0],
00410 G = RGB[1],
00411 B = RGB[2],
00412 nR = (R<0?0:(R>255?255:R))/255,
00413 nG = (G<0?0:(G>255?255:G))/255,
00414 nB = (B<0?0:(B>255?255:B))/255,
00415 m = nR<nG?(nR<nB?nR:nB):(nG<nB?nG:nB),
00416 theta = (T)(std::acos(0.5f*((nR-nG)+(nR-nB))/std::sqrt(std::pow(nR-nG,2)+(nR-nB)*(nG-nB)))*180/PIC_IMAGE_PI),
00417 sum = nR + nG + nB;
00418 T H = 0, S = 0, I = 0;
00419 if (theta>0) H = (nB<=nG)?theta:360-theta;
00420 if (sum>0) S = 1 - 3/sum*m;
00421 I = sum/3;
00422 HSI[0] = (T)H;
00423 HSI[1] = (T)S;
00424 HSI[2] = (T)I;
00425 }
00426
00427
00428 template<class T>
00429 void HSItoRGB(T* HSI, T* RGB) {
00430 T H = (T)HSI[0],
00431 S = (T)HSI[1],
00432 I = (T)HSI[2],
00433 a = I*(1-S),
00434 R = 0, G = 0, B = 0;
00435 if (H<120) {
00436 B = a;
00437 R = (T)(I*(1+S*std::cos(H*PIC_IMAGE_PI/180)/std::cos((60-H)*PIC_IMAGE_PI/180)));
00438 G = 3*I-(R+B);
00439 } else if (H<240) {
00440 H-=120;
00441 R = a;
00442 G = (T)(I*(1+S*std::cos(H*PIC_IMAGE_PI/180)/std::cos((60-H)*PIC_IMAGE_PI/180)));
00443 B = 3*I-(R+G);
00444 } else {
00445 H-=240;
00446 G = a;
00447 B = (T)(I*(1+S*std::cos(H*PIC_IMAGE_PI/180)/std::cos((60-H)*PIC_IMAGE_PI/180)));
00448 R = 3*I-(G+B);
00449 }
00450 R*=255; G*=255; B*=255;
00451 RGB[0] = (T)(R<0?0:(R>255?255:R));
00452 RGB[1] = (T)(G<0?0:(G>255?255:G));
00453 RGB[2] = (T)(B<0?0:(B>255?255:B));
00454 }
00455
00456 void iil4mitkPicImage::copyImage (unsigned int x, unsigned int y, unsigned int w, unsigned int h, unsigned char* data, unsigned int width, unsigned int, unsigned int xoffset, unsigned int yoffset)
00457 {
00458 assert (_pic);
00459
00460
00461 unsigned int slice = _pic->n[0] * _pic->n[1] * (_pic->bpe / 8);
00462 float scale = (_max -_min > 0 ? 255.0 / (_max - _min) : 0.0);
00463 float bias = _min * scale;
00464 float scaleOpac = (_maxOpac -_minOpac > 0 ? 255.0 / (_maxOpac - _minOpac) : 0.0);
00465 float biasOpac = _minOpac * scaleOpac;
00466 unsigned char *src = (unsigned char *) _pic->data + (y * _pic->n[0] + x) * (_pic->bpe/8);
00467 unsigned char *dst = data + (yoffset * width + xoffset) * (bpe () / 8);
00468 unsigned char *eol = dst + w * (bpe () / 8);
00469
00470
00471 for (unsigned int i = 0; i < h; i++) {
00472
00473
00474
00475 if (model () == RGB)
00476 {
00477 unsigned char* source = (unsigned char *) src;
00478 unsigned char* dest = dst;
00479 while (dest < eol)
00480 {
00481 if(_min!=0 || _max!=255)
00482 {
00483
00484 double rgb[3], hsi[3];
00485 rgb[0] = source[0];
00486 rgb[1] = source[1];
00487 rgb[2] = source[2];
00488 RGBtoHSI<double>(rgb,hsi);
00489 hsi[2] = hsi[2] * 255.0 * scale - bias;
00490 hsi[2] = (hsi[2] > 255.0 ? 255 : (hsi[2] < 0.0 ? 0 : hsi[2]));
00491 hsi[2] /= 255.0;
00492 HSItoRGB<double>(hsi,rgb);
00493 dest[0] = (unsigned char)rgb[0];
00494 dest[1] = (unsigned char)rgb[1];
00495 dest[2] = (unsigned char)rgb[2];
00496 source+=3;
00497 dest+=3;
00498 }
00499 else
00500 {
00501 *dest = *source;
00502 ++source;
00503 ++dest;
00504 }
00505 }
00506 }
00507 else if (model () == RGBA)
00508 {
00509 unsigned char* source = (unsigned char *) src;
00510 unsigned char* dest = dst;
00511 while (dest < eol)
00512 {
00513 if(_min!=0 || _max!=255 || _minOpac!=0 || _maxOpac!=255)
00514 {
00515 double rgb[3], alpha, hsi[3];
00516
00517
00518 rgb[0] = source[0];
00519 rgb[1] = source[1];
00520 rgb[2] = source[2];
00521 alpha = source[3];
00522 RGBtoHSI<double>(rgb,hsi);
00523 hsi[2] = hsi[2] * 255.0 * scale - bias;
00524 hsi[2] = (hsi[2] > 255.0 ? 255 : (hsi[2] < 0.0 ? 0 : hsi[2]));
00525 hsi[2] /= 255.0;
00526 HSItoRGB<double>(hsi,rgb);
00527
00528
00529 alpha = alpha * scaleOpac - biasOpac;
00530 alpha = (alpha > 255.0 ? 255 : (alpha < 0.0 ? 0 : alpha));
00531
00532 dest[0] = (unsigned char)rgb[0];
00533 dest[1] = (unsigned char)rgb[1];
00534 dest[2] = (unsigned char)rgb[2];
00535 dest[3] = (unsigned char)alpha;
00536
00537 source+=4;
00538 dest+=4;
00539 }
00540 else
00541 {
00542 *dest = *source;
00543 ++source;
00544 ++dest;
00545 }
00546 }
00547 } else
00548 if (mask ()) {
00549 mitkIpPicFORALL(MASK_INTENSITIES, _pic);
00550 } else
00551 if (binary ()) {
00552 mitkIpPicFORALL(BINARY_INTENSITIES, _pic);
00553 } else {
00554 #ifdef USE_MMX
00555 if (mitkIpPicDR(_pic->type, _pic->bpe) == mitkIpPicDR(mitkIpPicInt, 16)) {
00556 unsigned char* d = dst;
00557 unsigned char* s = src;
00558 if (w / 16) {
00559 extrema (dst, (short *) src, w, (short) _min, (short) _max);
00560 }
00561 if (w % 16) {
00562 mitkIpPicFORALL(LIMIT_INTENSITIES, _pic);
00563 dst = d;
00564 src = s;
00565 }
00566 } else {
00567 mitkIpPicFORALL(LIMIT_INTENSITIES, _pic);
00568 }
00569 #else
00570 mitkIpPicFORALL(LIMIT_INTENSITIES, _pic);
00571 #endif
00572 }
00573
00574
00575
00576 src += _pic->n[0] * (_pic->bpe/8);
00577 dst += width * (bpe () / 8);
00578 eol = dst + w * (bpe () / 8);
00579 }
00580 }
00581
00582
00583 void
00584 iil4mitkPicImage::display (iil4mitkWidget* widget)
00585 {
00586 if (!_outline) {
00587 iil4mitkImage::display( widget );
00588 }
00589 else {
00590 glMatrixMode (GL_MODELVIEW);
00591 glPushMatrix ();
00592 glColor4f ( red(), green(), blue(), alpha() );
00593
00594 glTranslatef( x(), y(), 0.0 );
00595 glLineWidth(_outlineWidth);
00596 glBegin( GL_LINES );
00597
00598 int line = _pic->n[0];
00599 float fLine = (float)line;
00600 float x=0.0, y=0.0;
00601 mitkIpInt1_t *current;
00602 mitkIpInt1_t *end = ((mitkIpInt1_t*)_pic->data) + (_pic->n[0]*_pic->n[1]);
00603 int ii = 0, nn = _pic->n[0]*_pic->n[1];
00604 for (current = (mitkIpInt1_t*)_pic->data; current<end; current++, ii++) {
00605 if (*current != 0) {
00606 if (ii >= line && *(current-line) == 0) {
00607 glVertex3f( x, y, 0.0 );
00608 glVertex3f( x+1.0, y, 0.0 );
00609 }
00610 if (ii <= nn-line && *(current+line) == 0) {
00611 glVertex3f( x, y+1.0, 0.0 );
00612 glVertex3f( x+1.0, y+1.0, 0.0 );
00613 }
00614 if (ii > 1 && *(current-1) == 0) {
00615 glVertex3f( x, y, 0.0 );
00616 glVertex3f( x, y+1.0, 0.0 );
00617 }
00618 if (ii < nn-1 && *(current+1) == 0) {
00619 glVertex3f( x+1.0, y, 0.0 );
00620 glVertex3f( x+1.0, y+1.0, 0.0 );
00621 }
00622 }
00623 x += 1.0;
00624 if (x >= fLine) {
00625 x = 0.0;
00626 y += 1.0;
00627 }
00628 }
00629 glEnd ();
00630 glLineWidth(1.0f);
00631 glPopMatrix ();
00632 }
00633 }