-rw-r--r-- | noncore/multimedia/camera/camera.pro | 6 | ||||
-rw-r--r-- | noncore/multimedia/camera/imageio.cpp | 55 | ||||
-rw-r--r-- | noncore/multimedia/camera/imageio.h | 26 | ||||
-rw-r--r-- | noncore/multimedia/camera/mainwindow.cpp | 198 | ||||
-rw-r--r-- | noncore/multimedia/camera/mainwindow.h | 19 | ||||
-rw-r--r-- | noncore/multimedia/camera/previewwidget.cpp | 14 | ||||
-rw-r--r-- | noncore/multimedia/camera/previewwidget.h | 3 | ||||
-rw-r--r-- | noncore/multimedia/camera/zcameraio.cpp | 100 | ||||
-rw-r--r-- | noncore/multimedia/camera/zcameraio.h | 11 |
9 files changed, 396 insertions, 36 deletions
diff --git a/noncore/multimedia/camera/camera.pro b/noncore/multimedia/camera/camera.pro index ffd5f37..8aedcea 100644 --- a/noncore/multimedia/camera/camera.pro +++ b/noncore/multimedia/camera/camera.pro @@ -5,9 +5,11 @@ TEMPLATE = app CONFIG = qt warn_on debug -HEADERS = zcameraio.h \ +HEADERS = imageio.h \ + zcameraio.h \ previewwidget.h \ mainwindow.h -SOURCES = zcameraio.cpp \ +SOURCES = imageio.cpp \ + zcameraio.cpp \ previewwidget.cpp \ mainwindow.cpp \ diff --git a/noncore/multimedia/camera/imageio.cpp b/noncore/multimedia/camera/imageio.cpp new file mode 100644 index 0000000..f8f5dd0 --- a/dev/null +++ b/noncore/multimedia/camera/imageio.cpp @@ -0,0 +1,55 @@ +/********************************************************************** +** Copyright (C) 2002 Michael 'Mickey' Lauer. All rights reserved. +** +** This file is part of Opie Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +**********************************************************************/ + +#include "imageio.h" + +#include <opie2/odebug.h> +#include <qimage.h> + + +void bufferToImage( int _width, int _height, unsigned char* bp, QImage* image ) +{ + unsigned char* p; + + image->create( _width, _height, 16 ); + for ( int i = 0; i < _height; ++i ) + { + p = image->scanLine( i ); + for ( int j = 0; j < _width; j++ ) + { + *p = *bp; + p++; + bp++; + *p = *bp; + p++; + bp++; + } + } +} + + +void imageToFile( QImage* i, const QString& name, const QString& format, int quality ) +{ + QImage im = i->convertDepth( 32 ); + bool result = im.save( name, format, quality ); + if ( !result ) + { + oerr << "imageio-Problem while writing." << oendl; + } + else + { + odebug << format << "-image has been successfully captured" << oendl; + } +}
\ No newline at end of file diff --git a/noncore/multimedia/camera/imageio.h b/noncore/multimedia/camera/imageio.h new file mode 100644 index 0000000..8dba2ed --- a/dev/null +++ b/noncore/multimedia/camera/imageio.h @@ -0,0 +1,26 @@ +/********************************************************************** +** Copyright (C) 2003 Michael 'Mickey' Lauer. All rights reserved. +** +** This file is part of Opie Environment. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +**********************************************************************/ + +#ifndef IMAGEIO_H +#define IMAGEIO_H + +#include <qstring.h> + +class QImage; + +void bufferToImage( int _width, int height, unsigned char* bp, QImage* image ); +void imageToFile( QImage* i, const QString& name, const QString& format, int quality ); + +#endif diff --git a/noncore/multimedia/camera/mainwindow.cpp b/noncore/multimedia/camera/mainwindow.cpp index 8e89039..6141fd1 100644 --- a/noncore/multimedia/camera/mainwindow.cpp +++ b/noncore/multimedia/camera/mainwindow.cpp @@ -17,4 +17,5 @@ #include "previewwidget.h" #include "zcameraio.h" +#include "imageio.h" #include <qapplication.h> @@ -28,6 +29,8 @@ #include <qlabel.h> #include <qpopupmenu.h> +#include <qprogressbar.h> #include <qpushbutton.h> #include <qmessagebox.h> +#include <qlayout.h> #include <qdirectpainter_qws.h> #include <qpe/global.h> @@ -37,11 +40,18 @@ #include <opie/odevice.h> using namespace Opie; - #include <opie2/odebug.h> #include <assert.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> + +#define CAPTUREFILE "/tmp/capture.dat" CameraMainWindow::CameraMainWindow( QWidget * parent, const char * name, WFlags f ) - :QMainWindow( parent, name, f ), _pics( 0 ) + :QMainWindow( parent, name, f ), _capturing( false ), _pics( 0 ) { #ifdef QT_NO_DEBUG @@ -79,4 +89,7 @@ CameraMainWindow::CameraMainWindow( QWidget * parent, const char * name, WFlags connect( ZCameraIO::instance(), SIGNAL( shutterClicked() ), this, SLOT( shutterClicked() ) ); + + updateCaption(); + }; @@ -90,4 +103,5 @@ void CameraMainWindow::init() { // TODO: Save this stuff in config + flip = 'A'; // auto quality = 50; zoom = 1; @@ -122,4 +136,12 @@ void CameraMainWindow::init() new QAction( "x 2", 0, 0, zoomg, 0, true ); + flipg = new QActionGroup( 0, "flip", true ); + flipg->setToggleAction( true ); + ( new QAction( "Auto (recommended)", 0, 0, flipg, 0, true ) )->setOn( true ); + new QAction( "0 (always off)", 0, 0, flipg, 0, true ); + new QAction( "X (always horizontal)", 0, 0, flipg, 0, true ); + new QAction( "Y (always vertical)", 0, 0, flipg, 0, true ); + new QAction( "* (always both)", 0, 0, flipg, 0, true ); + outputg = new QActionGroup( 0, "output", true ); outputg->setToggleAction( true ); @@ -127,9 +149,12 @@ void CameraMainWindow::init() new QAction( "PNG", 0, 0, outputg, 0, true ); new QAction( "BMP", 0, 0, outputg, 0, true ); + new QAction( "AVI", 0, 0, outputg, 0, true ); connect( resog, SIGNAL( selected(QAction*) ), this, SLOT( resoMenuItemClicked(QAction*) ) ); connect( qualityg, SIGNAL( selected(QAction*) ), this, SLOT( qualityMenuItemClicked(QAction*) ) ); connect( zoomg, SIGNAL( selected(QAction*) ), this, SLOT( zoomMenuItemClicked(QAction*) ) ); + connect( flipg, SIGNAL( selected(QAction*) ), this, SLOT( flipMenuItemClicked(QAction*) ) ); connect( outputg, SIGNAL( selected(QAction*) ), this, SLOT( outputMenuItemClicked(QAction*) ) ); + } @@ -170,4 +195,5 @@ void CameraMainWindow::changeZoom( int zoom ) } + void CameraMainWindow::showContextMenu() { @@ -180,4 +206,8 @@ void CameraMainWindow::showContextMenu() qualityg->addTo( &quality ); + QPopupMenu flip; + flip.setCheckable( true ); + flipg->addTo( &flip ); + QPopupMenu zoom; zoom.setCheckable( true ); @@ -191,4 +221,5 @@ void CameraMainWindow::showContextMenu() m.insertItem( "&Resolution", &reso ); m.insertItem( "&Zoom", &zoom ); + m.insertItem( "&Flip", &flip ); m.insertItem( "&Quality", &quality ); m.insertItem( "&Output As", &output ); @@ -202,4 +233,5 @@ void CameraMainWindow::resoMenuItemClicked( QAction* a ) captureY = a->text().right(3).toInt(); odebug << "Capture Resolution now: " << captureX << ", " << captureY << oendl; + updateCaption(); } @@ -209,4 +241,5 @@ void CameraMainWindow::qualityMenuItemClicked( QAction* a ) quality = a->text().left(3).toInt(); odebug << "Quality now: " << quality << oendl; + updateCaption(); } @@ -214,7 +247,27 @@ void CameraMainWindow::qualityMenuItemClicked( QAction* a ) void CameraMainWindow::zoomMenuItemClicked( QAction* a ) { - zoom = QString( a->text()[2] ).toInt(); + zoom = QString( a->text().at(2) ).toInt(); odebug << "Zoom now: " << zoom << oendl; ZCameraIO::instance()->setZoom( zoom ); + updateCaption(); +} + + +void CameraMainWindow::flipMenuItemClicked( QAction* a ) +{ + flip = QString( a->text().at(0) ); + odebug << "Flip now: " << flip << oendl; + if ( flip == "A" ) + ZCameraIO::instance()->setFlip( ZCameraIO::AUTOMATICFLIP ); + else if ( flip == "0" ) + ZCameraIO::instance()->setFlip( ZCameraIO::XNOFLIP | ZCameraIO::YNOFLIP ); + else if ( flip == "X" ) + ZCameraIO::instance()->setFlip( ZCameraIO::XFLIP ); + else if ( flip == "Y" ) + ZCameraIO::instance()->setFlip( ZCameraIO::YFLIP ); + else if ( flip == "*" ) + ZCameraIO::instance()->setFlip( ZCameraIO::XFLIP | ZCameraIO::YFLIP ); + + updateCaption(); } @@ -224,4 +277,5 @@ void CameraMainWindow::outputMenuItemClicked( QAction* a ) captureFormat = a->text(); odebug << "Output format now: " << captureFormat << oendl; + updateCaption(); } @@ -229,9 +283,23 @@ void CameraMainWindow::outputMenuItemClicked( QAction* a ) void CameraMainWindow::shutterClicked() { - Global::statusMessage( "CAPTURING..." ); - qApp->processEvents(); + if ( captureFormat != "AVI" ) // capture one photo per shutterClick + { + Global::statusMessage( "CAPTURING..." ); + qApp->processEvents(); - odebug << "Shutter has been pressed" << oendl; - ODevice::inst()->touchSound(); + odebug << "Shutter has been pressed" << oendl; + ODevice::inst()->touchSound(); + + performCapture( captureFormat ); + } + else // capture video! start with one shutter click and stop with the next + { + !_capturing ? startVideoCapture() : stopVideoCapture(); + } +} + + +void CameraMainWindow::performCapture( const QString& format ) +{ QString name; name.sprintf( "/tmp/image-%d_%d_%d_q%d.%s", _pics++, captureX, captureY, quality, (const char*) captureFormat.lower() ); @@ -239,5 +307,5 @@ void CameraMainWindow::shutterClicked() ZCameraIO::instance()->captureFrame( captureX, captureY, zoom, &i ); QImage im = i.convertDepth( 32 ); - bool result = im.save( name, captureFormat, quality ); + bool result = im.save( name, format, quality ); if ( !result ) { @@ -252,2 +320,116 @@ void CameraMainWindow::shutterClicked() } + +void CameraMainWindow::startVideoCapture() +{ + //ODevice::inst()->touchSound(); + ODevice::inst()->setLedState( Led_Mail, Led_BlinkSlow ); + + _capturefd = ::open( CAPTUREFILE, O_WRONLY | O_CREAT ); + if ( _capturefd == -1 ) + { + owarn << "can't open capture file: " << strerror(errno) << oendl; + return; + } + + _capturebuf = new unsigned char[captureX*captureY*2]; + _capturing = true; + _videopics = 0; + updateCaption(); + _time.start(); + preview->setRefreshingRate( 1000 ); + startTimer( 100 ); // too fast but that is ok +} + + +void CameraMainWindow::timerEvent( QTimerEvent* ) +{ + if ( !_capturing ) + { + owarn << "timer event in CameraMainWindow without capturing video ?" << oendl; + return; + } + + ZCameraIO::instance()->captureFrame( captureX, captureY, zoom, _capturebuf ); + _videopics++; + ::write( _capturefd, _capturebuf, captureX*captureY*2 ); + setCaption( QString().sprintf( "Capturing %dx%d @ %.2f fps %d", + captureX, captureY, 1000.0 / (_time.elapsed()/_videopics), _videopics ) ); +} + + +void CameraMainWindow::stopVideoCapture() +{ + killTimers(); + //ODevice::inst()->touchSound(); + ODevice::inst()->setLedState( Led_Mail, Led_Off ); + _capturing = false; + updateCaption(); + ::close( _capturefd ); + + //postProcessVideo(); + + #ifndef QT_NO_DEBUG + preview->setRefreshingRate( 1500 ); + #else + preview->setRefreshingRate( 200 ); + #endif + + //delete[] _capturebuf; //FIXME: close memory leak +} + +void CameraMainWindow::postProcessVideo() +{ + preview->setRefreshingRate( 0 ); + + /* + + QDialog* fr = new QDialog( this, "splash" ); //, false, QWidget::WStyle_NoBorder | QWidget::WStyle_Customize ); + fr->setCaption( "Please wait..." ); + QVBoxLayout* box = new QVBoxLayout( fr, 2, 2 ); + QProgressBar* bar = new QProgressBar( fr ); + bar->setCenterIndicator( true ); + bar->setTotalSteps( _videopics-1 ); + QLabel* label = new QLabel( "Post processing frame bla/bla", fr ); + box->addWidget( bar ); + box->addWidget( label ); + fr->show(); + qApp->processEvents(); + + for ( int i = 0; i < _videopics; ++i ) + { + label->setText( QString().sprintf( "Post processing frame %d / %d", i+1, _videopics ) ); + bar->setProgress( i ); + qApp->processEvents(); + } + + */ + + int infd = ::open( CAPTUREFILE, O_RDONLY ); + if ( infd == -1 ) + { + owarn << "couldn't open capture file: " << strerror(errno) << oendl; + return; + } + + int outfd = ::open( "/tmp/output.avi", O_WRONLY ); + if ( outfd == -1 ) + { + owarn << "couldn't open output file: " << strerror(errno) << oendl; + return; + } + + + + +} + +void CameraMainWindow::updateCaption() +{ + if ( !_capturing ) + setCaption( QString().sprintf( "Opie-Camera: %dx%d %s q%d z%d (%s)", captureX, captureY, (const char*) captureFormat.lower(), quality, zoom, (const char*) flip ) ); + else + setCaption( "Opie-Camera: => CAPTURING <=" ); +} + + diff --git a/noncore/multimedia/camera/mainwindow.h b/noncore/multimedia/camera/mainwindow.h index 7a12452..ad8d1b1 100644 --- a/noncore/multimedia/camera/mainwindow.h +++ b/noncore/multimedia/camera/mainwindow.h @@ -21,8 +21,10 @@ #include <qimage.h> #include <qpixmap.h> +#include <qdatetime.h> class QAction; class QActionGroup; class QIconSet; +class QTimerEvent; class QToolButton; class QLabel; @@ -46,9 +48,18 @@ class CameraMainWindow: public QMainWindow void qualityMenuItemClicked( QAction* ); void zoomMenuItemClicked( QAction* ); + void flipMenuItemClicked( QAction* ); void outputMenuItemClicked( QAction* ); void shutterClicked(); + void updateCaption(); + protected: void init(); + void startVideoCapture(); + void stopVideoCapture(); + void postProcessVideo(); + void performCapture( const QString& ); + + virtual void timerEvent( QTimerEvent* ); private: @@ -60,6 +71,8 @@ class CameraMainWindow: public QMainWindow QActionGroup* qualityg; QActionGroup* zoomg; + QActionGroup* flipg; QActionGroup* outputg; + QString flip; int quality; int zoom; @@ -68,5 +81,11 @@ class CameraMainWindow: public QMainWindow QString captureFormat; + bool _capturing; int _pics; + + QTime _time; + int _videopics; + int _capturefd; + unsigned char* _capturebuf; }; diff --git a/noncore/multimedia/camera/previewwidget.cpp b/noncore/multimedia/camera/previewwidget.cpp index f87dcc9..08330d0 100644 --- a/noncore/multimedia/camera/previewwidget.cpp +++ b/noncore/multimedia/camera/previewwidget.cpp @@ -73,2 +73,16 @@ void PreviewWidget::mousePressEvent( QMouseEvent* ) } + +void PreviewWidget::setRefreshingRate( int ms ) +{ + killTimers(); + if ( ms ) + startTimer( ms ); +} + + +void PreviewWidget::refresh() +{ + QTimerEvent t( 10 ); // event id is meaningless in this case + timerEvent( &t ); +} diff --git a/noncore/multimedia/camera/previewwidget.h b/noncore/multimedia/camera/previewwidget.h index dada301..d37f80f 100644 --- a/noncore/multimedia/camera/previewwidget.h +++ b/noncore/multimedia/camera/previewwidget.h @@ -32,4 +32,7 @@ class PreviewWidget: public QLabel virtual ~PreviewWidget(); + void setRefreshingRate( int ms ); + void refresh(); + protected: virtual void timerEvent( QTimerEvent* ); diff --git a/noncore/multimedia/camera/zcameraio.cpp b/noncore/multimedia/camera/zcameraio.cpp index 9af0c25..1c449e7 100644 --- a/noncore/multimedia/camera/zcameraio.cpp +++ b/noncore/multimedia/camera/zcameraio.cpp @@ -45,5 +45,7 @@ ZCameraIO* ZCameraIO::instance() ZCameraIO::ZCameraIO() - :_height( 0 ), _width( 0 ), _zoom( 0 ), _rot( 0 ), _readlen( 0 ) + : _pressed( false ), _height( 0 ), _width( 0 ), _zoom( 0 ), + _flip( -1 ), _rot( 0 ), _readlen( 0 ) + { _driver = ::open( SHARPZDC, O_RDWR ); @@ -85,16 +87,22 @@ bool ZCameraIO::isOpen() const bool ZCameraIO::isShutterPressed() { - if ( _timer->elapsed() < 1000 ) //TODO: make this customizable? - { - clearShutterLatch(); - return false; - } if ( _status[0] == 'S' ) { - _timer->restart(); - clearShutterLatch(); - return true; + if ( !_pressed ) // wasn't pressed before, but is now! + { + _pressed = true; + _timer->start(); + return true; + } + + if ( _timer->elapsed() > 2000 ) // the press is pretty old now + { + clearShutterLatch(); + _status[0] = 's'; + _pressed = false; + } } - else return false; + + return false; } @@ -150,9 +158,18 @@ void ZCameraIO::setReadMode( int mode ) { read( _status, 4 ); - if ( isShutterPressed() ) emit shutterClicked(); + if ( isShutterPressed() ) + { + emit shutterClicked(); + } } } +void ZCameraIO::setFlip( int flip ) +{ + _flip = flip; +} + + void ZCameraIO::clearShutterLatch() { @@ -199,13 +216,23 @@ bool ZCameraIO::snapshot( QImage* image ) odebug << "rotation = " << _rot << oendl; - if ( _rot ) // Portrait + int readmode; + if ( _flip == -1 ) // AUTO { - setReadMode( IMAGE | isFinderReversed() ? XFLIP | YFLIP : 0 ); + if ( _rot ) // Portrait + { + readmode = IMAGE | isFinderReversed() ? XFLIP | YFLIP : 0; + } + else // Landscape + { + readmode = IMAGE | XFLIP | YFLIP; + } } - else // Landscape + else // OVERRIDE { - setReadMode( IMAGE | XFLIP | YFLIP ); //isFinderReversed() ? 0 : XFLIP ); + readmode = IMAGE | _flip; } + setReadMode( readmode ); + char buf[_readlen]; char* bp = buf; @@ -235,16 +262,29 @@ bool ZCameraIO::snapshot( QImage* image ) bool ZCameraIO::snapshot( unsigned char* buf ) { - setReadMode( IMAGE | XFLIP | YFLIP ); + setReadMode( STATUS ); - read( (char*) buf, _readlen ); + odebug << "finder reversed = " << isFinderReversed() << oendl; + odebug << "rotation = " << _rot << oendl; - /* //TESTCODE - int fd = open( "/tmp/cam", O_RDONLY ); - if ( ::read( fd, (char*) buf, 76800 ) != 76800 ) - owarn << "Couldn't read image from /dev/sharp_zdc" << oendl; - // TESTCODE */ + int readmode; + if ( _flip == -1 ) // AUTO + { + if ( _rot ) // Portrait + { + readmode = IMAGE | isFinderReversed() ? XFLIP | YFLIP : 0; + } + else // Landscape + { + readmode = IMAGE | XFLIP | YFLIP; + } + } + else // OVERRIDE + { + readmode = IMAGE | _flip; + } + setReadMode( readmode ); + read( (char*) buf, _readlen ); - return true; } @@ -263,2 +303,16 @@ void ZCameraIO::captureFrame( int w, int h, int zoom, QImage* image ) +void ZCameraIO::captureFrame( int w, int h, int zoom, unsigned char* buf ) +{ + //FIXME: this is too slow + int pw = _width; + int ph = _height; + if ( _rot ) + setCaptureFrame( h, w, zoom*256, true ); + else + setCaptureFrame( w, h, zoom*256, false ); + + snapshot( buf ); + setCaptureFrame( pw, ph, _zoom, _rot ); +} + diff --git a/noncore/multimedia/camera/zcameraio.h b/noncore/multimedia/camera/zcameraio.h index edce143..3352a5e 100644 --- a/noncore/multimedia/camera/zcameraio.h +++ b/noncore/multimedia/camera/zcameraio.h @@ -34,5 +34,6 @@ class ZCameraIO : public QObject FASTER = 0, BETTER = 2, XNOFLIP = 0, XFLIP = 4, - YNOFLIP = 0, YFLIP = 8 + YNOFLIP = 0, YFLIP = 8, + AUTOMATICFLIP = -1 }; @@ -42,4 +43,5 @@ class ZCameraIO : public QObject bool setZoom( int zoom = 0 ); void setReadMode( int = IMAGE | XFLIP | YFLIP ); + void setFlip( int flip ); bool isShutterPressed(); // not const, because it calls clearShutterLatch @@ -48,6 +50,6 @@ class ZCameraIO : public QObject bool isFinderReversed() const; - bool snapshot( unsigned char* ); - bool snapshot( QImage* ); + bool snapshot( QImage* image ); + bool snapshot( unsigned char* buf ); // high level interface @@ -55,4 +57,5 @@ class ZCameraIO : public QObject static ZCameraIO* instance(); void captureFrame( int w, int h, int zoom, QImage* image ); + void captureFrame( int w, int h, int zoom, unsigned char* buf ); protected: @@ -69,8 +72,10 @@ class ZCameraIO : public QObject int _driver; char _status[4]; + bool _pressed; static ZCameraIO* _instance; int _height; int _width; int _zoom; + int _flip; bool _rot; int _readlen; |