summaryrefslogtreecommitdiff
Side-by-side diff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--noncore/multimedia/camera/camera.pro6
-rw-r--r--noncore/multimedia/camera/imageio.cpp55
-rw-r--r--noncore/multimedia/camera/imageio.h26
-rw-r--r--noncore/multimedia/camera/mainwindow.cpp198
-rw-r--r--noncore/multimedia/camera/mainwindow.h19
-rw-r--r--noncore/multimedia/camera/previewwidget.cpp14
-rw-r--r--noncore/multimedia/camera/previewwidget.h3
-rw-r--r--noncore/multimedia/camera/zcameraio.cpp100
-rw-r--r--noncore/multimedia/camera/zcameraio.h11
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;