From 1616915ff77fd6207dc6f3af2bd0a89654a18669 Mon Sep 17 00:00:00 2001
From: 020535 <020535@07accd87-1e0b-0410-939d-c05d8a058e03>
Date: Thu, 11 Jun 2009 21:51:43 +0000
Subject: [PATCH] Cleared out a load of uneeded stuff. No longer using a
 "canvas" element or a layout. Now, this is a clean widget. Removed the
 button. No real reason to keep it as a part of the widget. The paintEvent now
 correctly draws directly on the widget. Changed Ilp2QImage, no longer makes a
 clone of the IplImage. Changes to painting, the conversion mechanism, and
 clearing out unneded stuff removed a bad memory-leak, leaking somewhere
 around 5.10MBytes/second previously, now leaks one frame when "dying
 unclean"..

git-svn-id: https://dilbert.hig.no/svn/student/020535/qopencamwidget/trunk@171 07accd87-1e0b-0410-939d-c05d8a058e03
---
 qopencamwidget.cpp | 123 +++++++++++----------------------------------
 qopencamwidget.h   |   8 +--
 2 files changed, 29 insertions(+), 102 deletions(-)

diff --git a/qopencamwidget.cpp b/qopencamwidget.cpp
index cd5d1b2..e5358f5 100644
--- a/qopencamwidget.cpp
+++ b/qopencamwidget.cpp
@@ -1,7 +1,6 @@
 /*
- This file is one part of two, that together make
- QOpenCamWidget, a Qt 4 widget that displays video input 
- from a webcam, along with an optional snapshot button.
+ This file is one part of two, that together make QOpenCamWidget, 
+ a Qt 4 widget that displays video input from a webcam.
 
  Copyright (C) 2009 Jon Langseth
 
@@ -48,10 +47,14 @@
  * \code
  * QOpenCamWidget *cw = new QOpenCamWidget(this);
  * if ( cw->grabCapture(-1) ) {
- *   cw->setSnapshotVisible(true);
  *   cw->startCapture();
  * }
  * connect( cw, SIGNAL(imageReady(QImage)), this, SLOT(saveImage(QImage)));
+ * 
+ * QPushButton *trigger = new QPushButton(this);
+ * trigger->setText("Take picture");
+ * connect( trigger, SIGNAL(clicked()), cw, SLOT(startSnap()));
+ *
  * \endcode
  *
  * \param *parent The parent widget containing this widget, defaults to NULL.
@@ -60,72 +63,21 @@
 QOpenCamWidget::QOpenCamWidget(QWidget *parent) 
 	: QWidget(parent) 
 {
-	// private CvCapture *nextFrame from class definition
+	// Setting sane default values (i.e. NULL) for 
+	// private CvCapture *nextFrame  and
+	// private QTimer    *frametimer from class definition
 	nextFrame = NULL;
-	// private QTimer *frametimer from class definition
 	frametimer = NULL;
-	// private QVBoxLayout *layout from class definition
-	layout = new QVBoxLayout(this);
-	
-	// private QLabel *canvas from class definition
-	canvas = new QLabel(this);
-	canvas->setMinimumSize(200, 100);
-	canvas->setAlignment(Qt::AlignCenter);
-
-	// private QPushButton *trigger from class definition
-	trigger = new QPushButton(this);
-	trigger->setText("Take picture");
-	trigger->setEnabled(false);
-	trigger->hide();
-
-	// private bool trigger_active from class definition
-	trigger_active = false;
-
-	layout->addWidget(canvas);
-	this->setLayout(layout);
 }
 
 QOpenCamWidget::~QOpenCamWidget(void)
 {
 	cvReleaseCapture( &capture );
-	delete canvas;
-	delete trigger;
 }
 // ------------------------------------------------------------- //
 // Public methods (not signals/slots)
 // ------------------------------------------------------------- //
 
-/*! 
- * \brief Changes the visibility of the optional built-in "Take snapshot" button.
- *
- * The widget contains a push-button that optionally can be displayed. When
- * visible, this button is located at the bottom of the widget, and causes
- * the SLOT QOpenCamWidget::startSnap to be triggered when clicked.
- *
- * \param visible True makes the button display, and trigger, 
- *                false turns the feature off. False, i.e. no button, is default.
- * 
- **/
-void 
-QOpenCamWidget::setSnapshotVisible(bool visible)
-{
-	// Checking both parameter and private "sanity" variable,
-	// as a sanity- and error-control
-	if ( visible && !trigger_active )
-	{
-		connect( trigger, SIGNAL(clicked()), this, SLOT(startSnap()));
-		layout->addWidget(trigger);
-		trigger->show();
-		trigger_active = true;
-	}
-	if ( !visible && trigger_active )
-	{
-		layout->removeWidget(trigger);
-		disconnect( trigger, SIGNAL(clicked()), 0, 0 );
-		trigger->hide();
-		trigger_active = false;
-	}
-}
 /*!
  * \brief A paint event is a request to repaint all or part of a widget. 
  *
@@ -148,22 +100,18 @@ QOpenCamWidget::paintEvent ( QPaintEvent * event )
 		
 	if ( nextFrame )
 	{
-		// Using this objects painter to draw the image
-		// causes a cute, but not desired effect..
-		//paint->drawImage(event->rect(), *nextFrame);
-
-		// Until I find a better solution on how to do the
-		// redraw of the image, setPixmap on the canvas
-		// does do the job. This may cause a performance
-		// penalty though, and is considered a FIXME
-		// Another drawback is that the widget does not resize..
-		canvas->setPixmap( QPixmap::fromImage(*nextFrame) );
+		// To make the widget as blazingly fast as possible
+		// we output the last captured frame direclty onto
+		// the widget area.
+		paint->drawImage(event->rect(), *nextFrame);
 	}
 	else
 	{
-		canvas->setText("No data, check/test camera");
+     		paint->drawText(event->rect(),"No data, check/test camera");
 	}
 	paint->end();
+	// Clean up..
+	delete(paint);
 }
 
 
@@ -192,9 +140,8 @@ QOpenCamWidget::grabCapture(int source)
         IplImage *image = cvRetrieveFrame(capture);
         QSize t_size = QSize(image->width,image->height);
 
-        qDebug() << "Device image format: " << image->width << "x" << image->height;
-	canvas->setMinimumSize(t_size);
-	canvas->setMaximumSize(t_size);
+	this->setMinimumSize(t_size);
+	this->setMaximumSize(t_size);
 
 	return true;
 }
@@ -217,9 +164,8 @@ void
 QOpenCamWidget::startCapture(void)
 {
 	frametimer = new QTimer(this);
-        frametimer->start(70);
+        frametimer->start(50);
         connect(frametimer,SIGNAL(timeout()), this,SLOT(grabFrame()));
-	trigger->setEnabled(true);
 }
 
 /*!
@@ -238,15 +184,13 @@ QOpenCamWidget::startCapture(void)
  *
  **/
 QImage* 
-QOpenCamWidget::Ipl2QImage(const IplImage *img)
+QOpenCamWidget::Ipl2QImage(IplImage *img)
 {
-	IplImage *tmp=cvCloneImage(img);
-	cvConvertImage(img,tmp, CV_CVTIMG_SWAP_RB  );
-	QImage * qimage = new QImage(reinterpret_cast<uchar*>(tmp->imageData),
-			tmp->width,
-			tmp->height,
-			3* tmp->width,
-			QImage::Format_RGB888);
+	cvConvertImage(img,img, CV_CVTIMG_SWAP_RB);
+	QImage * qimage = new QImage(
+		reinterpret_cast<uchar*>(img->imageData),
+		img->width, img->height,
+		3* img->width, QImage::Format_RGB888);
 	return qimage;
 
 }
@@ -265,16 +209,11 @@ QOpenCamWidget::Ipl2QImage(const IplImage *img)
  **/
 void QOpenCamWidget::grabFrame(void)
 {
-	if ( !capture )
-	{
-		qDebug() << "Capture device not ready!";
-		return;
-	}
+	if ( !capture ) { qDebug() << "Capture device not ready!"; return; }
 
 	cvGrabFrame(capture);
 
 	IplImage *iplimage = cvRetrieveFrame(capture);
-
 	if (iplimage)
 	{
 		nextFrame = Ipl2QImage(iplimage);
@@ -283,6 +222,7 @@ void QOpenCamWidget::grabFrame(void)
 	{
 		nextFrame =  NULL;
 	}
+
 	update();
 }
 
@@ -293,11 +233,6 @@ void QOpenCamWidget::grabFrame(void)
  * stopped, and the last displayed frame is "captured", and made
  * available through the emitting of the class imageReady SIGNAL.
  *
- * With the "Take snapshot" button visible (setSnapshotVisible(true)),
- * this SLOT is triggered when the user clicks on the trigger button.
- * If you do not wish to use the internal trigger button, you
- * will have to add a different mechanism to trigger this SLOT.
- *
  * It is possible, though I would not recommend, to use repeated
  * triggering of this slot to do repeated frame-capture, and thus
  * make a form of "Animation" or "Video" capture.
@@ -309,8 +244,6 @@ void QOpenCamWidget::startSnap(void)
 		if (frametimer->isActive())
 		{
 			frametimer->stop();
-			qDebug() << "SNAP!";
-
 			emit imageReady(QImage(*nextFrame));
 			frametimer->start();
 		}
diff --git a/qopencamwidget.h b/qopencamwidget.h
index ef93a15..560d78b 100644
--- a/qopencamwidget.h
+++ b/qopencamwidget.h
@@ -35,11 +35,6 @@ class QOpenCamWidget
 		CvCapture   *capture;
 		QTimer      *frametimer;
 		QImage      *nextFrame;
-		//QImage      *snapshot;
-		QLabel      *canvas;
-		QVBoxLayout *layout;
-		QPushButton *trigger;
-		bool trigger_active;
 
 	public:
 		// Defaults, standard elements ;)
@@ -50,10 +45,9 @@ class QOpenCamWidget
     		void paintEvent ( QPaintEvent * event );
 
 		// Public methods specific to this class
-		void setSnapshotVisible( bool visible );
 		bool grabCapture(int source);
 		void startCapture(void);
-		QImage* Ipl2QImage(const IplImage *img);
+		QImage* Ipl2QImage(IplImage *img);
 
 	public slots:
 		void grabFrame(void);
-- 
2.39.2