-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 @@ -1,23 +1,25 @@ MOC_DIR = ./moc OBJECTS_DIR = ./obj DESTDIR = $(OPIEDIR)/bin 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 \ main.cpp INCLUDEPATH += $(OPIEDIR)/include DEPENDPATH += $(OPIEDIR)/include LIBS += -lqpe -lopie -lopiecore2 INTERFACES = TARGET = opiecam include ( $(OPIEDIR)/include.pro ) 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 @@ -3,59 +3,69 @@ ** ** 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 "mainwindow.h" #include "previewwidget.h" #include "zcameraio.h" +#include "imageio.h" #include <qapplication.h> #include <qaction.h> #include <qvbox.h> #include <qcombobox.h> #include <qcursor.h> #include <qdatastream.h> #include <qfile.h> #include <qimage.h> #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> #include <qpe/resource.h> #include <qpe/qcopenvelope_qws.h> #include <opie/ofiledialog.h> #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 if ( !ZCameraIO::instance()->isOpen() ) { QVBox* v = new QVBox( this ); v->setMargin( 10 ); QLabel* l1 = new QLabel( v ); l1->setPixmap( Resource::loadPixmap( "camera/error" ) ); QLabel* l2 = new QLabel( v ); l2->setText( "<b>Sorry. could not detect your camera :-(</b><p>" "* Is the sharpzdc_cs module loaded ?<br>" "* Is /dev/sharpzdc read/writable ?<p>" ); connect( new QPushButton( "Exit", v ), SIGNAL( clicked() ), this, SLOT( close() ) ); setCentralWidget( v ); return; } @@ -65,85 +75,100 @@ CameraMainWindow::CameraMainWindow( QWidget * parent, const char * name, WFlags _rotation = 270; //TODO: grab these from the actual settings preview = new PreviewWidget( this, "camera preview widget" ); //setCentralWidget( preview ); <--- don't do this! preview->resize( QSize( 240, 288 ) ); preview->show(); // construct a System Channel to receive setRotation messages _sysChannel = new QCopChannel( "QPE/System", this ); connect( _sysChannel, SIGNAL( received( const QCString&, const QByteArray& ) ), this, SLOT( systemMessage( const QCString&, const QByteArray& ) ) ); connect( preview, SIGNAL( contextMenuRequested() ), this, SLOT( showContextMenu() ) ); connect( ZCameraIO::instance(), SIGNAL( shutterClicked() ), this, SLOT( shutterClicked() ) ); + + updateCaption(); + }; CameraMainWindow::~CameraMainWindow() { } void CameraMainWindow::init() { // TODO: Save this stuff in config + flip = 'A'; // auto quality = 50; zoom = 1; captureX = 640; captureY = 480; captureFormat = "JPEG"; resog = new QActionGroup( 0, "reso", true ); resog->setToggleAction( true ); new QAction( " 64 x 48", 0, 0, resog, 0, true ); new QAction( "128 x 96", 0, 0, resog, 0, true ); new QAction( "192 x 144", 0, 0, resog, 0, true ); new QAction( "256 x 192", 0, 0, resog, 0, true ); new QAction( "320 x 240", 0, 0, resog, 0, true ); new QAction( "384 x 288", 0, 0, resog, 0, true ); new QAction( "448 x 336", 0, 0, resog, 0, true ); new QAction( "512 x 384", 0, 0, resog, 0, true ); new QAction( "576 x 432", 0, 0, resog, 0, true ); ( new QAction( "640 x 480", 0, 0, resog, 0, true ) )->setOn( true ); qualityg = new QActionGroup( 0, "quality", true ); qualityg->setToggleAction( true ); new QAction( " 0 (minimal)", 0, 0, qualityg, 0, true ); new QAction( " 25 (low)", 0, 0, qualityg, 0, true ); ( new QAction( " 50 (good)", 0, 0, qualityg, 0, true ) )->setOn( true ); new QAction( " 75 (better)", 0, 0, qualityg, 0, true ); new QAction( "100 (best)", 0, 0, qualityg, 0, true ); zoomg = new QActionGroup( 0, "zoom", true ); zoomg->setToggleAction( true ); ( new QAction( "x 1", 0, 0, zoomg, 0, true ) )->setOn( true ); 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 ); ( new QAction( "JPEG", 0, 0, outputg, 0, true ) )->setOn( true ); 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*) ) ); + } void CameraMainWindow::systemMessage( const QCString& msg, const QByteArray& data ) { QDataStream stream( data, IO_ReadOnly ); odebug << "received system message: " << msg << oendl; if ( msg == "setCurrentRotation(int)" ) { stream >> _rotation; odebug << "received setCurrentRotation(" << _rotation << ")" << oendl; switch ( _rotation ) { case 270: preview->resize( QSize( 240, 288 ) ); break; case 180: preview->resize( QSize( 320, 208 ) ); break; @@ -156,98 +181,255 @@ void CameraMainWindow::systemMessage( const QCString& msg, const QByteArray& dat void CameraMainWindow::changeZoom( int zoom ) { int z; switch ( zoom ) { case 0: z = 128; break; case 1: z = 256; break; case 2: z = 512; break; default: assert( 0 ); break; } ZCameraIO::instance()->setCaptureFrame( 240, 160, z ); } + void CameraMainWindow::showContextMenu() { QPopupMenu reso; reso.setCheckable( true ); resog->addTo( &reso ); QPopupMenu quality; quality.setCheckable( true ); qualityg->addTo( &quality ); + QPopupMenu flip; + flip.setCheckable( true ); + flipg->addTo( &flip ); + QPopupMenu zoom; zoom.setCheckable( true ); zoomg->addTo( &zoom ); QPopupMenu output; output.setCheckable( true ); outputg->addTo( &output ); QPopupMenu m( this ); m.insertItem( "&Resolution", &reso ); m.insertItem( "&Zoom", &zoom ); + m.insertItem( "&Flip", &flip ); m.insertItem( "&Quality", &quality ); m.insertItem( "&Output As", &output ); m.exec( QCursor::pos() ); } void CameraMainWindow::resoMenuItemClicked( QAction* a ) { captureX = a->text().left(3).toInt(); captureY = a->text().right(3).toInt(); odebug << "Capture Resolution now: " << captureX << ", " << captureY << oendl; + updateCaption(); } void CameraMainWindow::qualityMenuItemClicked( QAction* a ) { quality = a->text().left(3).toInt(); odebug << "Quality now: " << quality << oendl; + updateCaption(); } 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(); } void CameraMainWindow::outputMenuItemClicked( QAction* a ) { captureFormat = a->text(); odebug << "Output format now: " << captureFormat << oendl; + updateCaption(); } 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() ); QImage i; 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 ) { oerr << "imageio-Problem while writing." << oendl; Global::statusMessage( "Error!" ); } else { odebug << captureFormat << "-image has been successfully captured" << oendl; Global::statusMessage( "Ok." ); } } + +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 @@ -7,67 +7,86 @@ ** 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 MAINWINDOW_H #define MAINWINDOW_H #include <qmainwindow.h> #include <qdatetime.h> #include <qimage.h> #include <qpixmap.h> +#include <qdatetime.h> class QAction; class QActionGroup; class QIconSet; +class QTimerEvent; class QToolButton; class QLabel; class MainWindowBase; class QCopChannel; class PreviewWidget; class CameraMainWindow: public QMainWindow { Q_OBJECT public: CameraMainWindow( QWidget * parent = 0, const char * name = "mainwindow", WFlags f = 0 ); virtual ~CameraMainWindow(); public slots: void changeZoom( int ); void systemMessage( const QCString&, const QByteArray& ); void showContextMenu(); void resoMenuItemClicked( QAction* ); 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: PreviewWidget* preview; int _rotation; QCopChannel* _sysChannel; QActionGroup* resog; QActionGroup* qualityg; QActionGroup* zoomg; + QActionGroup* flipg; QActionGroup* outputg; + QString flip; int quality; int zoom; int captureX; int captureY; QString captureFormat; + bool _capturing; int _pics; + + QTime _time; + int _videopics; + int _capturefd; + unsigned char* _capturebuf; }; #endif 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 @@ -59,16 +59,30 @@ void PreviewWidget::timerEvent( QTimerEvent* ) //QDirectPainter fb( this ); //ZCameraIO::instance()->snapshot( fb.frameBuffer() ); if ( ZCameraIO::instance()->snapshot( &i ) ) { p.convertFromImage( i ); setPixmap( p ); } } void PreviewWidget::mousePressEvent( QMouseEvent* ) { emit contextMenuRequested(); } + +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 @@ -18,30 +18,33 @@ #include <qlabel.h> #include <qimage.h> #include <qpixmap.h> class QTimerEvent; class QResizeEvent; class PreviewWidget: public QLabel { Q_OBJECT public: PreviewWidget( QWidget * parent = 0, const char * name = 0, WFlags f = 0 ); virtual ~PreviewWidget(); + void setRefreshingRate( int ms ); + void refresh(); + protected: virtual void timerEvent( QTimerEvent* ); virtual void resizeEvent( QResizeEvent* ); virtual void mousePressEvent( QMouseEvent* ); signals: void contextMenuRequested(); private: QPixmap p; QImage i; }; #endif 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 @@ -31,33 +31,35 @@ #define SHARPZDC "/dev/sharp_zdc" ZCameraIO* ZCameraIO::_instance = 0; ZCameraIO* ZCameraIO::instance() { if ( !ZCameraIO::_instance ) { odebug << "Creating ZCameraIO::_instance" << oendl; ZCameraIO::_instance = new ZCameraIO(); } return 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 ); if ( _driver == -1 ) oerr << "Can't open camera driver: " << strerror(errno) << oendl; else init(); } void ZCameraIO::init() { if ( ZCameraIO::_instance ) ofatal << "Don't create more than one ZCameraIO instances." << oendl; else { _timer = new QTime(); @@ -71,44 +73,50 @@ ZCameraIO::~ZCameraIO() if ( _driver != -1 ) { setReadMode( 0 ); ::close( _driver ); } } bool ZCameraIO::isOpen() const { return _driver != -1; } 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; } bool ZCameraIO::isFinderReversed() const { return _status[1] == 'M'; } bool ZCameraIO::isCapturing() const { return _status[2] == 'C'; } bool ZCameraIO::isAvailable() const @@ -136,37 +144,46 @@ bool ZCameraIO::setCaptureFrame( int width, int height, int zoom, bool rot ) bool ZCameraIO::setZoom( int zoom ) { return setCaptureFrame( _width, _height, zoom*256, _rot ); } void ZCameraIO::setReadMode( int mode ) { char b[10]; sprintf( b, "M=%d", mode ); write( b, mode <= 9 ? 3 : 4 ); if ( mode & STATUS ) // STATUS bit is set { read( _status, 4 ); - if ( isShutterPressed() ) emit shutterClicked(); + if ( isShutterPressed() ) + { + emit shutterClicked(); + } } } +void ZCameraIO::setFlip( int flip ) +{ + _flip = flip; +} + + void ZCameraIO::clearShutterLatch() { write( "B", 1 ); } bool ZCameraIO::read( char* b, int len ) { #ifndef NO_TIMING QTime t; t.start(); #endif int rlen = ::read( _driver, b, len ); #ifndef NO_TIMING int time = t.elapsed(); #else @@ -185,80 +202,117 @@ bool ZCameraIO::write( char* buf, int len ) if ( !len ) len = strlen( buf ); odebug << "writing '" << buf << "' to driver." << oendl; return ::write( _driver, buf, len ) == len; } bool ZCameraIO::snapshot( QImage* image ) { setReadMode( STATUS ); odebug << "finder reversed = " << isFinderReversed() << oendl; 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; unsigned char* p; read( bp, _readlen ); 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++; } } return true; } 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; } void ZCameraIO::captureFrame( int w, int h, int zoom, QImage* image ) { int pw = _width; int ph = _height; if ( _rot ) setCaptureFrame( h, w, zoom*256, true ); else setCaptureFrame( w, h, zoom*256, false ); snapshot( image ); setCaptureFrame( pw, ph, _zoom, _rot ); } +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 @@ -20,62 +20,67 @@ class QImage; class QTime; class ZCameraIO : public QObject { Q_OBJECT public: virtual ~ZCameraIO(); enum ReadMode { IMAGE = 0, STATUS = 1, FASTER = 0, BETTER = 2, XNOFLIP = 0, XFLIP = 4, - YNOFLIP = 0, YFLIP = 8 + YNOFLIP = 0, YFLIP = 8, + AUTOMATICFLIP = -1 }; // low level interface bool setCaptureFrame( int w, int h, int zoom = 256, bool rot = true ); bool setZoom( int zoom = 0 ); void setReadMode( int = IMAGE | XFLIP | YFLIP ); + void setFlip( int flip ); bool isShutterPressed(); // not const, because it calls clearShutterLatch bool isAvailable() const; bool isCapturing() const; bool isFinderReversed() const; - bool snapshot( unsigned char* ); - bool snapshot( QImage* ); + bool snapshot( QImage* image ); + bool snapshot( unsigned char* buf ); // high level interface bool isOpen() const; 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: ZCameraIO(); void clearShutterLatch(); void init(); bool read( char*, int ); bool write( char*, int = 0 ); signals: void shutterClicked(); private: int _driver; char _status[4]; + bool _pressed; static ZCameraIO* _instance; int _height; int _width; int _zoom; + int _flip; bool _rot; int _readlen; QTime* _timer; }; #endif |