/**************************************************************************** ** $Id: qt/showimg.cpp 3.3.8 edited Jan 11 14:37 $ ** ** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved. ** ** This file is part of an example program for Qt. This example ** program may be used, distributed and modified without limitation. ** *****************************************************************************/ #include "showimg.h" #include #include #include #include #include #include #include #include #include /* In the constructor, we just pass the standard parameters on to QWidget. The menu uses a single slot to simplify the process of adding more items to the options menu. */ ImageViewer::ImageViewer( QWidget *parent, Qt::WindowFlags wFlags ) : QMainWindow( parent, wFlags ), m_drawSegment( false ), m_initialized( false ), m_firstPoint( 1 ) { pickx = -1; picky = -1; clickx = -1; clicky = -1; /* QMenu* menuFile = menuBar()->addMenu( "&File" ); menuFile->addAction( "&Open...", this, SLOT(openFile()), Qt::CTRL + Qt::Key_O ); menuFile->addSeparator(); menuFile->addAction( "E&xit", qApp, SLOT(quit()), Qt::CTRL + Qt::Key_Q ); results = new QLabel(this); results->setFrameStyle( QFrame::WinPanel | QFrame::Sunken ); results->setFixedHeight( fontMetrics().height() + 4 ); statusBar()->setFixedHeight( fontMetrics().height() + 4 ); resize( 640, 480 ); setMouseTracking( TRUE ); */ m_result.vect_adventitia = NULL; m_result.vect_intima = NULL; ClearResult(); } ImageViewer::~ImageViewer() { ClearResult(); } void ImageViewer::updateStatus() { if ( pm.size() == QSize( 0, 0 ) ) { if ( !filename.isEmpty() ) statusBar()->showMessage("Could not load image"); else statusBar()->showMessage("No image - select Open from File menu."); } else { QString message, moremsg; message.sprintf("%dx%d", image.width(), image.height()); if ( pm.size() != pmScaled.size() ) { moremsg.sprintf(" [%dx%d]", pmScaled.width(), pmScaled.height()); message += moremsg; } moremsg.sprintf(", %d bits ", image.depth()); message += moremsg; if (image.valid(pickx,picky)) { moremsg.sprintf("(%d,%d)=#%0*x ", pickx, picky, image.hasAlphaChannel() ? 8 : 6, image.pixel(pickx,picky)); message += moremsg; if ( !m_firstPoint ) { QString evenMoreMsg; float d = imt::getDistanceToFirstPoint( pickx, picky ); evenMoreMsg.sprintf(" - dist=%lf ", d ); message += evenMoreMsg; } } if ( image.numColors() > 0 ) { if (image.valid(pickx,picky)) { moremsg.sprintf(", %d/%d colors", image.pixelIndex(pickx,picky), image.numColors()); } else { moremsg.sprintf(", %d colors", image.numColors()); } message += moremsg; } if ( image.hasAlphaChannel() ) { if ( image.depth() == 8 ) { int i; bool alpha[256]; int nalpha=0; for (i=0; i<256; i++) alpha[i] = false; for (i=0; i> 24; if (!alpha[alevel]) { alpha[alevel] = true; nalpha++; } } moremsg.sprintf(", %d alpha levels", nalpha); } else { // Too many pixels to bother counting. moremsg = ", 8-bit alpha channel"; } message += moremsg; } statusBar()->showMessage(message); } } void ImageViewer::updateResults() { QString message; if ( pm.size() == QSize( 0, 0 ) ) { message.sprintf( " " ); } else { int n = m_result.numberOfPoints; if ( n ) { int i, nValid = 0; message.sprintf( " " ); for ( i = 0; i < n; i++ ) { imt::Point p = m_result.vect_intima[ i ]; if ( ( p.x >= 0 ) && ( p.y >= 0 ) ) { nValid++; } } message.sprintf( "IMT: max=%.3lf ; mean=%.3lf ; std=%.3lf ; QI=%.3lf ; dist=%.3lf ; mean IT=%.3lf ; mean MT=%.3lf ; nValid=%d", m_result.imt_max, m_result.imt_mean, m_result.imt_standardDeviation, m_result.qualityIndex, m_result.distance, m_result.intima_mean, m_result.media_mean, nValid ); } } results->setText( message ); } /* This function is the slot for processing the Open menu item. */ void ImageViewer::openFile() { QString newfilename = QFileDialog::getOpenFileName( this ); if ( !newfilename.isEmpty() ) { m_initialized = false; m_firstPoint = 1; ClearResult(); loadImage( newfilename ) ; repaint(); // show image in widget } } /* This function loads an image from a file and resizes the widget to exactly fit the image size. If the file was not found or the image format was unknown it will resize the widget to fit the errorText message (see above) displayed in the current font. Returns TRUE if the image was successfully loaded. */ bool ImageViewer::loadImage( const QString& fileName ) { filename = fileName; bool ok = false; if ( !filename.isEmpty() ) { QApplication::setOverrideCursor( QCursor( Qt::WaitCursor ) ); // this might take time ok = image.load(filename, 0); pickx = -1; clickx = -1; if ( ok ) { m_initialized = imt::initializeFromRaw( (const char*)image.bits(), image.width(), image.height(), image.depth(), false, 0.1, 0.1 ); } else { ok = m_initialized = imt::initializeFromFile( filename.toStdString().c_str() ); if ( ok ) { int w = imt::getImageWidth(); int h = imt::getImageHeight(); image = QImage( w, h, QImage::Format_RGB32 ); ok = false; if ( !image.isNull() ) { char* p = imt::getPixelArray(); char* l = (char*)image.bits(); int n = h * w; while ( n-- ) { *l++ = *p++; *l++ = *p++; *l++ = *p++; *l++ = 0xFF; } ok = true; } } } if ( ok ) ok = reconvertImage(); if ( ok ) { int w = pm.width(); int h = pm.height(); const int reasonable_width = 128; if ( w < reasonable_width ) { // Integer scale up to something reasonable int multiply = ( reasonable_width + w - 1 ) / w; w *= multiply; h *= multiply; } h += menuBar()->heightForWidth(w) + statusBar()->height() + results->height(); resize( w, h ); // we resize to fit image setFixedSize( w, h ); } else { pm = pm.copy(0,0,0,0); // couldn't load image update(); } QApplication::restoreOverrideCursor(); // restore original cursor } updateStatus(); updateResults(); return ok; } bool ImageViewer::reconvertImage() { bool success = false; if ( image.isNull() ) return false; QApplication::setOverrideCursor( QCursor( Qt::WaitCursor ) ); // this might take time pm = QPixmap::fromImage( image, Qt::PreferDither ); if ( !pm.isNull() ) { pmScaled = QPixmap(); scale(); resize( width(), height() ); success = true; // load successful } else { pm = pm.copy(0,0,0,0); // couldn't load image } updateStatus(); QApplication::restoreOverrideCursor(); // restore original cursor return success; // TRUE if loaded OK } /* This functions scales the pixmap in the member variable "pm" to fit the widget size and puts the resulting pixmap in the member variable "pmScaled". */ void ImageViewer::scale() { int h = height() - menuBar()->heightForWidth( width() ) - statusBar()->height() - results->height(); if ( image.isNull() ) return; QApplication::setOverrideCursor( QCursor( Qt::WaitCursor ) ); // this might take time if ( width() == pm.width() && h == pm.height() ) { // no need to scale if widget pmScaled = pm; // size equals pixmap size } else { QMatrix m; // transformation matrix m.scale(((double)width())/pm.width(),// define scale factors ((double)h)/pm.height()); pmScaled = pm.transformed( QTransform( m ) ); // create scaled pixmap } QApplication::restoreOverrideCursor(); // restore original cursor } /* The resize event handler, if a valid pixmap was loaded it will call scale() to fit the pixmap to the new widget size. */ void ImageViewer::resizeEvent( QResizeEvent * ) { int sheight = statusBar()->height(); statusBar()->setGeometry(0, height() - statusBar()->height(), width(), statusBar()->height()); results->setGeometry(0, height() - sheight - results->height(), width(), sheight); if ( pm.size() == QSize( 0, 0 ) ) // we couldn't load the image return; int h = height() - menuBar()->heightForWidth( width() ) - statusBar()->height() - results->height(); if ( width() != pmScaled.width() || h != pmScaled.height()) { // if new size, scale(); // scale pmScaled to window updateStatus(); } } bool ImageViewer::convertEvent( QMouseEvent* e, int& x, int& y) { if ( pm.size() != QSize( 0, 0 ) ) { int h = height() - menuBar()->heightForWidth( width() ) - statusBar()->height() - results->height(); int nx = e->x() * image.width() / width(); int ny = (e->y()-menuBar()->heightForWidth( width() )) * image.height() / h; if (nx != x || ny != y ) { x = nx; y = ny; updateStatus(); return TRUE; } } return false; } void ImageViewer::mousePressEvent( QMouseEvent* ) { } void ImageViewer::mouseReleaseEvent( QMouseEvent* e ) { convertEvent(e,pickx,picky); if ( m_initialized && ( e->button() & Qt::LeftButton ) ) { if ( m_firstPoint ) { if ( m_result.numberOfPoints ) { update(); } m_result.p0.x = pickx; m_result.p0.y = picky; QApplication::setOverrideCursor( QCursor( Qt::CrossCursor ) ); imt::setFirstPoint( pickx, picky ); m_drawSegment = true; } else { QApplication::restoreOverrideCursor(); imt::setSecondPoint( pickx, picky, &m_result ); m_drawSegment = false; update(); } m_firstPoint ^= 1; updateResults(); } } /* Record the pixel position of interest. */ void ImageViewer::mouseMoveEvent( QMouseEvent* e ) { if (convertEvent(e,pickx,picky)) { //if ((e->state()&LeftButton)) { if ( !m_firstPoint && ( pm.size() != QSize( 0, 0 ) ) ) { m_result.p1.x = pickx; m_result.p1.y = picky; update(); } //} updateStatus(); } } void ImageViewer::ClearResult() { m_result.imt_max = 0.0; m_result.imt_mean = 0.0; m_result.imt_standardDeviation = 0.0; m_result.intima_mean = 0.0; m_result.media_mean = 0.0; m_result.qualityIndex = 0.0; m_result.distance = 0.0; m_result.numberOfPoints = 0; if ( m_result.vect_adventitia ) { delete[] m_result.vect_adventitia; m_result.vect_adventitia = NULL; } if ( m_result.vect_media ) { delete[] m_result.vect_media; m_result.vect_media = NULL; } if ( m_result.vect_intima ) { delete[] m_result.vect_intima; m_result.vect_intima = NULL; } } /* Draws the portion of the scaled pixmap that needs to be updated or prints an error message if no legal pixmap has been loaded. */ void ImageViewer::paintEvent( QPaintEvent* ) { if ( pm.size() != QSize( 0, 0 ) ) { QPainter painter(this); int dh = menuBar()->heightForWidth( width() ); painter.drawPixmap(0, dh, pmScaled); if ( m_drawSegment ) { QColor bcolor( 0, 255, 0 ); QPen pen( bcolor, 1 ); painter.setPen( pen ); imt::Point p0 = m_result.p0; imt::Point p1 = m_result.p1; painter.drawLine( p0.x, p0.y + dh, p1.x, p1.y + dh ); } else { int n = m_result.numberOfPoints; if ( n ) { int i; QColor vert( 0, 255, 0 ); QColor jaune( 255, 255, 0 ); QColor cyan( 255, 0, 255 ); QPen penV( vert, 1 ); QPen penJ( jaune, 1 ); QPen penC( cyan, 1 ); painter.setPen( penJ ); for ( i = 0; i < n; i++ ) { imt::Point p = m_result.vect_intima[ i ]; if ( ( p.x >= 0 ) && ( p.y >= 0 ) ) { painter.drawPoint( p.x, p.y + dh ); } } painter.setPen( penC ); for ( i = 0; i < n; i++ ) { imt::Point p = m_result.vect_media[ i ]; if ( ( p.x >= 0 ) && ( p.y >= 0 ) ) { painter.drawPoint( p.x, p.y + dh ); } } painter.setPen( penV ); for ( i = 0; i < n; i++ ) { imt::Point p = m_result.vect_adventitia[ i ]; if ( ( p.x >= 0 ) && ( p.y >= 0 ) ) { painter.drawPoint( p.x, p.y + dh ); } } painter.drawLine( m_result.p0.x, m_result.p0.y + dh, m_result.p1.x, m_result.p1.y + dh ); } } } }