showimg.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. /****************************************************************************
  2. ** $Id: qt/showimg.cpp 3.3.8 edited Jan 11 14:37 $
  3. **
  4. ** Copyright (C) 1992-2007 Trolltech ASA. All rights reserved.
  5. **
  6. ** This file is part of an example program for Qt. This example
  7. ** program may be used, distributed and modified without limitation.
  8. **
  9. *****************************************************************************/
  10. #include "showimg.h"
  11. #include <QtGui/QMenuBar>
  12. #include <QtGui/QStatusBar>
  13. #include <QtGui/QFileDialog>
  14. #include <QtGui/QMessageBox>
  15. #include <QtGui/QLabel>
  16. #include <QtGui/QPainter>
  17. #include <QtGui/QApplication>
  18. #include <QtGui/QMouseEvent>
  19. #include <EIMInterfaceDLL.h>
  20. /*
  21. In the constructor, we just pass the standard parameters on to
  22. QWidget.
  23. The menu uses a single slot to simplify the process of adding
  24. more items to the options menu.
  25. */
  26. ImageViewer::ImageViewer( QWidget *parent, Qt::WindowFlags wFlags )
  27. : QMainWindow( parent, wFlags ),
  28. m_drawSegment( false ),
  29. m_initialized( false ),
  30. m_firstPoint( 1 )
  31. {
  32. pickx = -1;
  33. picky = -1;
  34. clickx = -1;
  35. clicky = -1;
  36. /*
  37. QMenu* menuFile = menuBar()->addMenu( "&File" );
  38. menuFile->addAction( "&Open...", this, SLOT(openFile()),
  39. Qt::CTRL + Qt::Key_O );
  40. menuFile->addSeparator();
  41. menuFile->addAction( "E&xit", qApp, SLOT(quit()), Qt::CTRL + Qt::Key_Q );
  42. results = new QLabel(this);
  43. results->setFrameStyle( QFrame::WinPanel | QFrame::Sunken );
  44. results->setFixedHeight( fontMetrics().height() + 4 );
  45. statusBar()->setFixedHeight( fontMetrics().height() + 4 );
  46. resize( 640, 480 );
  47. setMouseTracking( TRUE );
  48. */
  49. m_result.vect_adventitia = NULL;
  50. m_result.vect_intima = NULL;
  51. ClearResult();
  52. }
  53. ImageViewer::~ImageViewer()
  54. {
  55. ClearResult();
  56. }
  57. void ImageViewer::updateStatus()
  58. {
  59. if ( pm.size() == QSize( 0, 0 ) ) {
  60. if ( !filename.isEmpty() )
  61. statusBar()->showMessage("Could not load image");
  62. else
  63. statusBar()->showMessage("No image - select Open from File menu.");
  64. } else {
  65. QString message, moremsg;
  66. message.sprintf("%dx%d", image.width(), image.height());
  67. if ( pm.size() != pmScaled.size() ) {
  68. moremsg.sprintf(" [%dx%d]", pmScaled.width(),
  69. pmScaled.height());
  70. message += moremsg;
  71. }
  72. moremsg.sprintf(", %d bits ", image.depth());
  73. message += moremsg;
  74. if (image.valid(pickx,picky)) {
  75. moremsg.sprintf("(%d,%d)=#%0*x ",
  76. pickx, picky,
  77. image.hasAlphaChannel() ? 8 : 6,
  78. image.pixel(pickx,picky));
  79. message += moremsg;
  80. if ( !m_firstPoint )
  81. {
  82. QString evenMoreMsg;
  83. float d = imt::getDistanceToFirstPoint( pickx, picky );
  84. evenMoreMsg.sprintf(" - dist=%lf ", d );
  85. message += evenMoreMsg;
  86. }
  87. }
  88. if ( image.numColors() > 0 ) {
  89. if (image.valid(pickx,picky)) {
  90. moremsg.sprintf(", %d/%d colors", image.pixelIndex(pickx,picky),
  91. image.numColors());
  92. } else {
  93. moremsg.sprintf(", %d colors", image.numColors());
  94. }
  95. message += moremsg;
  96. }
  97. if ( image.hasAlphaChannel() ) {
  98. if ( image.depth() == 8 ) {
  99. int i;
  100. bool alpha[256];
  101. int nalpha=0;
  102. for (i=0; i<256; i++)
  103. alpha[i] = false;
  104. for (i=0; i<image.numColors(); i++) {
  105. int alevel = image.color(i) >> 24;
  106. if (!alpha[alevel]) {
  107. alpha[alevel] = true;
  108. nalpha++;
  109. }
  110. }
  111. moremsg.sprintf(", %d alpha levels", nalpha);
  112. } else {
  113. // Too many pixels to bother counting.
  114. moremsg = ", 8-bit alpha channel";
  115. }
  116. message += moremsg;
  117. }
  118. statusBar()->showMessage(message);
  119. }
  120. }
  121. void ImageViewer::updateResults()
  122. {
  123. QString message;
  124. if ( pm.size() == QSize( 0, 0 ) ) {
  125. message.sprintf( " " );
  126. } else {
  127. int n = m_result.numberOfPoints;
  128. if ( n )
  129. {
  130. int i, nValid = 0;
  131. message.sprintf( " " );
  132. for ( i = 0; i < n; i++ )
  133. {
  134. imt::Point p = m_result.vect_intima[ i ];
  135. if ( ( p.x >= 0 ) && ( p.y >= 0 ) )
  136. {
  137. nValid++;
  138. }
  139. }
  140. message.sprintf( "IMT: max=%.3lf ; mean=%.3lf ; std=%.3lf ; QI=%.3lf ; dist=%.3lf ; mean IT=%.3lf ; mean MT=%.3lf ; nValid=%d",
  141. m_result.imt_max,
  142. m_result.imt_mean,
  143. m_result.imt_standardDeviation,
  144. m_result.qualityIndex,
  145. m_result.distance,
  146. m_result.intima_mean,
  147. m_result.media_mean,
  148. nValid );
  149. }
  150. }
  151. results->setText( message );
  152. }
  153. /*
  154. This function is the slot for processing the Open menu item.
  155. */
  156. void ImageViewer::openFile()
  157. {
  158. QString newfilename = QFileDialog::getOpenFileName( this );
  159. if ( !newfilename.isEmpty() ) {
  160. m_initialized = false;
  161. m_firstPoint = 1;
  162. ClearResult();
  163. loadImage( newfilename ) ;
  164. repaint(); // show image in widget
  165. }
  166. }
  167. /*
  168. This function loads an image from a file and resizes the widget to
  169. exactly fit the image size. If the file was not found or the image
  170. format was unknown it will resize the widget to fit the errorText
  171. message (see above) displayed in the current font.
  172. Returns TRUE if the image was successfully loaded.
  173. */
  174. bool ImageViewer::loadImage( const QString& fileName )
  175. {
  176. filename = fileName;
  177. bool ok = false;
  178. if ( !filename.isEmpty() ) {
  179. QApplication::setOverrideCursor( QCursor( Qt::WaitCursor ) ); // this might take time
  180. ok = image.load(filename, 0);
  181. pickx = -1;
  182. clickx = -1;
  183. if ( ok )
  184. {
  185. m_initialized = imt::initializeFromRaw( (const char*)image.bits(), image.width(), image.height(),
  186. image.depth(), false, 0.1, 0.1 );
  187. }
  188. else
  189. {
  190. ok = m_initialized = imt::initializeFromFile( filename.toStdString().c_str() );
  191. if ( ok )
  192. {
  193. int w = imt::getImageWidth();
  194. int h = imt::getImageHeight();
  195. image = QImage( w, h, QImage::Format_RGB32 );
  196. ok = false;
  197. if ( !image.isNull() )
  198. {
  199. char* p = imt::getPixelArray();
  200. char* l = (char*)image.bits();
  201. int n = h * w;
  202. while ( n-- )
  203. {
  204. *l++ = *p++;
  205. *l++ = *p++;
  206. *l++ = *p++;
  207. *l++ = 0xFF;
  208. }
  209. ok = true;
  210. }
  211. }
  212. }
  213. if ( ok )
  214. ok = reconvertImage();
  215. if ( ok ) {
  216. int w = pm.width();
  217. int h = pm.height();
  218. const int reasonable_width = 128;
  219. if ( w < reasonable_width ) {
  220. // Integer scale up to something reasonable
  221. int multiply = ( reasonable_width + w - 1 ) / w;
  222. w *= multiply;
  223. h *= multiply;
  224. }
  225. h += menuBar()->heightForWidth(w) + statusBar()->height() + results->height();
  226. resize( w, h ); // we resize to fit image
  227. setFixedSize( w, h );
  228. } else {
  229. pm = pm.copy(0,0,0,0); // couldn't load image
  230. update();
  231. }
  232. QApplication::restoreOverrideCursor(); // restore original cursor
  233. }
  234. updateStatus();
  235. updateResults();
  236. return ok;
  237. }
  238. bool ImageViewer::reconvertImage()
  239. {
  240. bool success = false;
  241. if ( image.isNull() ) return false;
  242. QApplication::setOverrideCursor( QCursor( Qt::WaitCursor ) ); // this might take time
  243. pm = QPixmap::fromImage( image, Qt::PreferDither );
  244. if ( !pm.isNull() )
  245. {
  246. pmScaled = QPixmap();
  247. scale();
  248. resize( width(), height() );
  249. success = true; // load successful
  250. } else {
  251. pm = pm.copy(0,0,0,0); // couldn't load image
  252. }
  253. updateStatus();
  254. QApplication::restoreOverrideCursor(); // restore original cursor
  255. return success; // TRUE if loaded OK
  256. }
  257. /*
  258. This functions scales the pixmap in the member variable "pm" to fit the
  259. widget size and puts the resulting pixmap in the member variable "pmScaled".
  260. */
  261. void ImageViewer::scale()
  262. {
  263. int h = height() - menuBar()->heightForWidth( width() ) - statusBar()->height() - results->height();
  264. if ( image.isNull() ) return;
  265. QApplication::setOverrideCursor( QCursor( Qt::WaitCursor ) ); // this might take time
  266. if ( width() == pm.width() && h == pm.height() )
  267. { // no need to scale if widget
  268. pmScaled = pm; // size equals pixmap size
  269. } else {
  270. QMatrix m; // transformation matrix
  271. m.scale(((double)width())/pm.width(),// define scale factors
  272. ((double)h)/pm.height());
  273. pmScaled = pm.transformed( QTransform( m ) ); // create scaled pixmap
  274. }
  275. QApplication::restoreOverrideCursor(); // restore original cursor
  276. }
  277. /*
  278. The resize event handler, if a valid pixmap was loaded it will call
  279. scale() to fit the pixmap to the new widget size.
  280. */
  281. void ImageViewer::resizeEvent( QResizeEvent * )
  282. {
  283. int sheight = statusBar()->height();
  284. statusBar()->setGeometry(0, height() - statusBar()->height(),
  285. width(), statusBar()->height());
  286. results->setGeometry(0, height() - sheight - results->height(),
  287. width(), sheight);
  288. if ( pm.size() == QSize( 0, 0 ) ) // we couldn't load the image
  289. return;
  290. int h = height() - menuBar()->heightForWidth( width() ) - statusBar()->height() - results->height();
  291. if ( width() != pmScaled.width() || h != pmScaled.height())
  292. { // if new size,
  293. scale(); // scale pmScaled to window
  294. updateStatus();
  295. }
  296. }
  297. bool ImageViewer::convertEvent( QMouseEvent* e, int& x, int& y)
  298. {
  299. if ( pm.size() != QSize( 0, 0 ) ) {
  300. int h = height() - menuBar()->heightForWidth( width() ) - statusBar()->height() - results->height();
  301. int nx = e->x() * image.width() / width();
  302. int ny = (e->y()-menuBar()->heightForWidth( width() )) * image.height() / h;
  303. if (nx != x || ny != y ) {
  304. x = nx;
  305. y = ny;
  306. updateStatus();
  307. return TRUE;
  308. }
  309. }
  310. return false;
  311. }
  312. void ImageViewer::mousePressEvent( QMouseEvent* )
  313. {
  314. }
  315. void ImageViewer::mouseReleaseEvent( QMouseEvent* e )
  316. {
  317. convertEvent(e,pickx,picky);
  318. if ( m_initialized && ( e->button() & Qt::LeftButton ) )
  319. {
  320. if ( m_firstPoint )
  321. {
  322. if ( m_result.numberOfPoints )
  323. {
  324. update();
  325. }
  326. m_result.p0.x = pickx;
  327. m_result.p0.y = picky;
  328. QApplication::setOverrideCursor( QCursor( Qt::CrossCursor ) );
  329. imt::setFirstPoint( pickx, picky );
  330. m_drawSegment = true;
  331. }
  332. else
  333. {
  334. QApplication::restoreOverrideCursor();
  335. imt::setSecondPoint( pickx, picky, &m_result );
  336. m_drawSegment = false;
  337. update();
  338. }
  339. m_firstPoint ^= 1;
  340. updateResults();
  341. }
  342. }
  343. /*
  344. Record the pixel position of interest.
  345. */
  346. void ImageViewer::mouseMoveEvent( QMouseEvent* e )
  347. {
  348. if (convertEvent(e,pickx,picky)) {
  349. //if ((e->state()&LeftButton)) {
  350. if ( !m_firstPoint && ( pm.size() != QSize( 0, 0 ) ) ) {
  351. m_result.p1.x = pickx;
  352. m_result.p1.y = picky;
  353. update();
  354. }
  355. //}
  356. updateStatus();
  357. }
  358. }
  359. void ImageViewer::ClearResult()
  360. {
  361. m_result.imt_max = 0.0;
  362. m_result.imt_mean = 0.0;
  363. m_result.imt_standardDeviation = 0.0;
  364. m_result.intima_mean = 0.0;
  365. m_result.media_mean = 0.0;
  366. m_result.qualityIndex = 0.0;
  367. m_result.distance = 0.0;
  368. m_result.numberOfPoints = 0;
  369. if ( m_result.vect_adventitia )
  370. {
  371. delete[] m_result.vect_adventitia;
  372. m_result.vect_adventitia = NULL;
  373. }
  374. if ( m_result.vect_media )
  375. {
  376. delete[] m_result.vect_media;
  377. m_result.vect_media = NULL;
  378. }
  379. if ( m_result.vect_intima )
  380. {
  381. delete[] m_result.vect_intima;
  382. m_result.vect_intima = NULL;
  383. }
  384. }
  385. /*
  386. Draws the portion of the scaled pixmap that needs to be updated or prints
  387. an error message if no legal pixmap has been loaded.
  388. */
  389. void ImageViewer::paintEvent( QPaintEvent* )
  390. {
  391. if ( pm.size() != QSize( 0, 0 ) )
  392. {
  393. QPainter painter(this);
  394. int dh = menuBar()->heightForWidth( width() );
  395. painter.drawPixmap(0, dh, pmScaled);
  396. if ( m_drawSegment )
  397. {
  398. QColor bcolor( 0, 255, 0 );
  399. QPen pen( bcolor, 1 );
  400. painter.setPen( pen );
  401. imt::Point p0 = m_result.p0;
  402. imt::Point p1 = m_result.p1;
  403. painter.drawLine( p0.x, p0.y + dh, p1.x, p1.y + dh );
  404. }
  405. else
  406. {
  407. int n = m_result.numberOfPoints;
  408. if ( n )
  409. {
  410. int i;
  411. QColor vert( 0, 255, 0 );
  412. QColor jaune( 255, 255, 0 );
  413. QColor cyan( 255, 0, 255 );
  414. QPen penV( vert, 1 );
  415. QPen penJ( jaune, 1 );
  416. QPen penC( cyan, 1 );
  417. painter.setPen( penJ );
  418. for ( i = 0; i < n; i++ )
  419. {
  420. imt::Point p = m_result.vect_intima[ i ];
  421. if ( ( p.x >= 0 ) && ( p.y >= 0 ) )
  422. {
  423. painter.drawPoint( p.x, p.y + dh );
  424. }
  425. }
  426. painter.setPen( penC );
  427. for ( i = 0; i < n; i++ )
  428. {
  429. imt::Point p = m_result.vect_media[ i ];
  430. if ( ( p.x >= 0 ) && ( p.y >= 0 ) )
  431. {
  432. painter.drawPoint( p.x, p.y + dh );
  433. }
  434. }
  435. painter.setPen( penV );
  436. for ( i = 0; i < n; i++ )
  437. {
  438. imt::Point p = m_result.vect_adventitia[ i ];
  439. if ( ( p.x >= 0 ) && ( p.y >= 0 ) )
  440. {
  441. painter.drawPoint( p.x, p.y + dh );
  442. }
  443. }
  444. painter.drawLine( m_result.p0.x, m_result.p0.y + dh,
  445. m_result.p1.x, m_result.p1.y + dh );
  446. }
  447. }
  448. }
  449. }