#include #include #include #include #include #include using std::string; namespace icl{ GLPaintEngine::GLPaintEngine(QGLWidget *widget): // {{{ open m_poWidget(widget),m_bBCIAutoFlag(false), m_oFont(QFont("Arial",30)), m_poImageBufferForIncompatibleDepth(0){ widget->makeCurrent(); glMatrixMode(GL_MODELVIEW); glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ACCUM_BUFFER_BIT); QSize sz(widget->size()); glViewport(0, 0, sz.width(), sz.height()); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, sz.width(), sz.height(), 0, -999999, 999999); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); glDisable(GL_DEPTH_TEST); memset(m_afFillColor,0,3*sizeof(float)); for(int i=0;i<4;m_afLineColor[i++]=255); memset(m_aiBCI,0,3*sizeof(int)); } // }}} GLPaintEngine::~GLPaintEngine(){ // {{{ open if(m_poImageBufferForIncompatibleDepth) delete m_poImageBufferForIncompatibleDepth; glFlush(); } // }}} void GLPaintEngine::fontsize(int size){ // {{{ open m_oFont.setPointSize(size); } // }}} void GLPaintEngine::font(string name, int size, PaintEngine::TextWeight weight, PaintEngine::TextStyle style){ // {{{ open m_oFont.setFamily(name.c_str()); m_oFont.setPointSize(size); m_oFont.setStyle(style == PaintEngine::StyleNormal ? QFont::StyleNormal : style == PaintEngine::StyleItalic ? QFont::StyleItalic : QFont::StyleOblique); m_oFont.setWeight(weight == PaintEngine::Light ? QFont::Light : weight == PaintEngine::Normal ? QFont::Normal : weight == PaintEngine::DemiBold ? QFont::DemiBold : weight == PaintEngine::Bold ? QFont::Bold : QFont::Black); } // }}} void GLPaintEngine::color(int r, int g, int b, int a){ // {{{ open m_afLineColor[0] = (float)r/255.0; m_afLineColor[1] = (float)g/255.0; m_afLineColor[2] = (float)b/255.0; m_afLineColor[3] = (float)a/255.0; } // }}} void GLPaintEngine::fill(int r, int g, int b, int a){ // {{{ open m_afFillColor[0] = (float)r/255.0; m_afFillColor[1] = (float)g/255.0; m_afFillColor[2] = (float)b/255.0; m_afFillColor[3] = (float)a/255.0; } // }}} void GLPaintEngine::line(const Point &a, const Point &b){ // {{{ open glColor4fv(m_afLineColor); glBegin(GL_LINES); glVertex2f(a.x,a.y); glVertex2f(b.x,b.y); glEnd(); } // }}} void GLPaintEngine::point(const Point &p){ // {{{ open glColor4fv(m_afLineColor); glBegin(GL_POINTS); glVertex2f((GLfloat)p.x,(GLfloat)p.y); glEnd(); } // }}} void GLPaintEngine::image(const Rect &r,ImgBase *image, PaintEngine::AlignMode mode){ // {{{ open Size s = image->getSize(); setupRasterEngine(r,s,mode); setPackAlignment(image->getDepth(),s.width); if(!m_bBCIAutoFlag){ setupPixelTransfer(image->getDepth(),m_aiBCI[0],m_aiBCI[1],m_aiBCI[2]); }else{ // automatic adjustment of brightness and contrast float fScaleRGB,fBiasRGB; // auto adaption switch (image->getDepth()){ case depth8u:{ icl8u tMin,tMax; image->asImg()->getMinMax(tMin,tMax); fScaleRGB = (tMax == tMin) ? 255 : 255.0/(tMax-tMin); fBiasRGB = (- fScaleRGB * tMin)/255.0; break; } case depth16s:{ static const icl16s _max = (65536/2-1); icl16s tMin,tMax; image->asImg()->getMinMax(tMin,tMax); fScaleRGB = (tMax == tMin) ? _max : _max/(tMax-tMin); fBiasRGB = (- fScaleRGB * tMin)/255.0; break; } case depth32s:{ // drawn as float icl32s tMin,tMax; image->asImg()->getMinMax(tMin,tMax); fScaleRGB = (tMax == tMin) ? 255 : 255/(tMax-tMin); fBiasRGB = (- fScaleRGB * tMin)/255.0; break; } case depth32f:{ icl32f tMin,tMax; image->asImg()->getMinMax(tMin,tMax); fScaleRGB = (tMax == tMin) ? 255 : 255.0/(tMax-tMin); fBiasRGB = (- fScaleRGB * tMin)/255.0; fScaleRGB /= 255.0; break; } case depth64f:{ // drawn as float icl64f tMin,tMax; image->asImg()->getMinMax(tMin,tMax); fScaleRGB = (tMax == tMin) ? 255 : 255.0/(tMax-tMin); fBiasRGB = (- fScaleRGB * tMin)/255.0; fScaleRGB /= 255.0; break; } default: ICL_INVALID_FORMAT; break; } glPixelTransferf(GL_RED_SCALE,fScaleRGB); glPixelTransferf(GL_GREEN_SCALE,fScaleRGB); glPixelTransferf(GL_BLUE_SCALE,fScaleRGB); glPixelTransferf(GL_RED_BIAS,fBiasRGB); glPixelTransferf(GL_GREEN_BIAS,fBiasRGB); glPixelTransferf(GL_BLUE_BIAS,fBiasRGB); } // old // GLenum datatype = image->getDepth() == depth8u ? GL_UNSIGNED_BYTE : GL_FLOAT; // TODO_depth // end old GLenum datatype; switch(image->getDepth()){ case depth8u: datatype = GL_UNSIGNED_BYTE; break; case depth16s: datatype = GL_SHORT; break; case depth32s: case depth32f: case depth64f: datatype = GL_FLOAT; break; } static GLenum CHANNELS[4] = {GL_RED,GL_GREEN,GL_BLUE,GL_ALPHA}; ImgBase *drawImage=image; if(image->getDepth() == depth32s || image->getDepth() == depth64f){ // use fallback image conversion before drawing, as "int" and "double" are not supported yet ensureCompatible((ImgBase**)&m_poImageBufferForIncompatibleDepth,depth32f,image->getParams()); drawImage = m_poImageBufferForIncompatibleDepth; image->deepCopy(drawImage); } if(drawImage->getChannels() > 1){ for(int i=0;i<4 && igetChannels();i++){ glColorMask(i==0,i==1,i==2,i==3); glDrawPixels(s.width,s.height,CHANNELS[i],datatype,drawImage->getDataPtr(i)); } glColorMask(1,1,1,1); }else if(drawImage->getChannels() > 0){ glColorMask(1,1,1,0); glDrawPixels(s.width,s.height,GL_LUMINANCE,datatype,drawImage->getDataPtr(0)); } } // }}} void GLPaintEngine::image(const Rect &r,const QImage &image, PaintEngine::AlignMode mode){ // {{{ open setupPixelTransfer(depth8u,m_aiBCI[0],m_aiBCI[1],m_aiBCI[2]); glPixelStorei(GL_UNPACK_ALIGNMENT,4); setupRasterEngine(r, Size(image.width(),image.height()),mode); glDrawPixels(image.width(),image.height(),GL_RGBA,GL_UNSIGNED_BYTE,image.bits()); } // }}} void GLPaintEngine::rect(const Rect &r){ // {{{ open glColor4fv(m_afFillColor); glBegin(GL_QUADS); glVertex2f((GLfloat)r.x,(GLfloat)r.y); glVertex2f((GLfloat)r.right(),(GLfloat)r.y); glVertex2f((GLfloat)r.right(),(GLfloat)r.bottom()); glVertex2f((GLfloat)r.x,(GLfloat)r.bottom()); glEnd(); glColor4fv(m_afLineColor); glBegin(GL_LINE_LOOP); glVertex2f((GLfloat)r.x,(GLfloat)r.y); glVertex2f((GLfloat)r.right(),(GLfloat)r.y); glVertex2f((GLfloat)r.right(),(GLfloat)r.bottom()); glVertex2f((GLfloat)r.x,(GLfloat)r.bottom()); glEnd(); point(Point(r.right(),r.top())); } // }}} void GLPaintEngine::ellipse(const Rect &r){ // {{{ open glColor4fv(m_afFillColor); GLfloat w2 = 0.5*(r.width); GLfloat h2= 0.5*(r.height); GLfloat cx = r.x+w2; GLfloat cy = r.y+h2; static const GLint NSTEPS = 32; static const GLfloat D_ARC = (2*M_PI)/NSTEPS; glBegin(GL_POLYGON); for(int i=0;i0) c*=10; fScaleRGB*=(1.0+c); fBiasRGB-=c/2; glPixelTransferf(GL_RED_SCALE,fScaleRGB); glPixelTransferf(GL_GREEN_SCALE,fScaleRGB); glPixelTransferf(GL_BLUE_SCALE,fScaleRGB); glPixelTransferf(GL_RED_BIAS,fBiasRGB); glPixelTransferf(GL_GREEN_BIAS,fBiasRGB); glPixelTransferf(GL_BLUE_BIAS,fBiasRGB); } // }}} }