author | alwin <alwin> | 2004-11-01 19:52:25 (UTC) |
---|---|---|
committer | alwin <alwin> | 2004-11-01 19:52:25 (UTC) |
commit | 2dc92f4bfe9e81edc2b0b24ecacf3bc44b344984 (patch) (side-by-side diff) | |
tree | b1d5661ea64931b6eeb2030ceb22532cef699a75 /libopie2/opiemm/oimagescrollview.cpp | |
parent | 5a41dcd5901badbd2e258b0a916fb012b6351eeb (diff) | |
download | opie-2dc92f4bfe9e81edc2b0b24ecacf3bc44b344984.zip opie-2dc92f4bfe9e81edc2b0b24ecacf3bc44b344984.tar.gz opie-2dc92f4bfe9e81edc2b0b24ecacf3bc44b344984.tar.bz2 |
exif class added (taken from opie-eye_slave and more c++ like reworked)
it is used in oimageview while loading jpegs checking BEFORE loading if the
image should be scaled loaded.
ToDo: documentation of the interface, remove it from opie-eye_slave (it should
use of course the library version)
Diffstat (limited to 'libopie2/opiemm/oimagescrollview.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r-- | libopie2/opiemm/oimagescrollview.cpp | 14 |
1 files changed, 10 insertions, 4 deletions
diff --git a/libopie2/opiemm/oimagescrollview.cpp b/libopie2/opiemm/oimagescrollview.cpp index 56be10b..37a1ad5 100644 --- a/libopie2/opiemm/oimagescrollview.cpp +++ b/libopie2/opiemm/oimagescrollview.cpp @@ -1,563 +1,569 @@ #include "oimagescrollview.h" #include <opie2/oimagezoomer.h> #include <opie2/odebug.h> #include <opie2/oapplication.h> #include <opie2/owait.h> +#include <opie2/opieexif.h> #include <qimage.h> #include <qlayout.h> /* for usage with the bitset */ #define AUTO_SCALE 0 #define AUTO_ROTATE 1 #define SHOW_ZOOMER 2 #define FIRST_RESIZE_DONE 3 #define IMAGE_IS_JPEG 4 #define IMAGE_SCALED_LOADED 5 #define SCROLLVIEW_BITSET_SIZE 6 namespace Opie { namespace MM { OImageScrollView::OImageScrollView( QWidget* parent, const char* name, WFlags f ) :QScrollView(parent,name,f|Qt::WRepaintNoErase ),_image_data(),_original_data(), m_states(SCROLLVIEW_BITSET_SIZE),m_lastName("") { _zoomer = 0; m_states[AUTO_SCALE]=true; m_states[AUTO_ROTATE]=true; m_states[FIRST_RESIZE_DONE]=false; m_states[IMAGE_IS_JPEG]=false; m_states[IMAGE_SCALED_LOADED]=false; m_states[SHOW_ZOOMER]=true; init(); } OImageScrollView::OImageScrollView (const QImage&img, QWidget * parent, const char * name, WFlags f,bool always_scale,bool rfit) :QScrollView(parent,name,f|Qt::WRepaintNoErase),_image_data(),_original_data(img), m_states(SCROLLVIEW_BITSET_SIZE),m_lastName("") { _zoomer = 0; m_states[AUTO_SCALE]=always_scale; m_states[AUTO_ROTATE]=rfit; m_states[FIRST_RESIZE_DONE]=false; m_states[IMAGE_IS_JPEG]=false; m_states[IMAGE_SCALED_LOADED]=false; m_states[SHOW_ZOOMER]=true; _original_data.convertDepth(QPixmap::defaultDepth()); _original_data.setAlphaBuffer(false); init(); } OImageScrollView::OImageScrollView (const QString&img, QWidget * parent, const char * name, WFlags f,bool always_scale,bool rfit) :QScrollView(parent,name,f|Qt::WRepaintNoErase),_image_data(),_original_data(),m_states(SCROLLVIEW_BITSET_SIZE),m_lastName("") { _zoomer = 0; m_states.resize(SCROLLVIEW_BITSET_SIZE); m_states[AUTO_SCALE]=always_scale; m_states[AUTO_ROTATE]=rfit; m_states[FIRST_RESIZE_DONE]=false; m_states[IMAGE_IS_JPEG]=false; m_states[IMAGE_SCALED_LOADED]=false; m_states[SHOW_ZOOMER]=true; init(); setImage(img); } void OImageScrollView::setImage(const QImage&img) { _image_data = QImage(); _original_data=img; _original_data.convertDepth(QPixmap::defaultDepth()); _original_data.setAlphaBuffer(false); m_lastName = ""; setImageIsJpeg(false); setImageScaledLoaded(false); if (FirstResizeDone()) { generateImage(); } } void OImageScrollView::loadJpeg(bool interncall) { if (m_lastName.isEmpty()) return; QImageIO iio( m_lastName, 0l ); QString param; bool real_load = false; if (AutoScale()) { if (!interncall) { + ExifData xf; + bool scanned = xf.scan(m_lastName); int wid, hei; wid = QApplication::desktop()->width(); hei = QApplication::desktop()->height(); if (hei>wid) { wid = hei; } else { hei = wid; } - param = QString( "Fast Shrink( 3 ) Scale( %1, %2, ScaleMin)" ).arg( wid ).arg( hei ); - odebug << "Load jpeg scaled \"" << param << "\"" << oendl; - iio.setParameters(param.latin1()); - setImageScaledLoaded(true); + if ( (scanned && (wid<xf.getWidth()||hei<xf.getHeight()))||!scanned ) { + param = QString( "Fast Shrink( 3 ) Scale( %1, %2, ScaleMin)" ).arg( wid ).arg( hei ); + odebug << "Load jpeg scaled \"" << param << "\"" << oendl; + iio.setParameters(param.latin1()); + setImageScaledLoaded(true); + } + real_load = true; } } else { if (ImageScaledLoaded()||!interncall) { odebug << "Load jpeg unscaled" << oendl; real_load = true; } setImageScaledLoaded(false); } if (real_load) { _original_data = iio.read() ? iio.image() : QImage(); } } void OImageScrollView::setImage( const QString& path ) { odebug << "load new image " << oendl; if (m_lastName == path) return; m_lastName = path; _original_data = QImage(); QString itype = QImage::imageFormat(m_lastName); odebug << "Image type = " << itype << oendl; if (itype == "JPEG") { setImageIsJpeg(true); loadJpeg(); } else { setImageIsJpeg(false); _original_data.load(path); _original_data.convertDepth(QPixmap::defaultDepth()); _original_data.setAlphaBuffer(false); } _image_data = QImage(); if (FirstResizeDone()) { generateImage(); if (isVisible()) viewport()->repaint(true); } } /* should be called every time the QImage changed it content */ void OImageScrollView::init() { odebug << "init " << oendl; /* * create the zoomer * and connect ther various signals */ _zoomer = new Opie::MM::OImageZoomer( this, "The Zoomer" ); connect(_zoomer, SIGNAL( zoomAreaRel(int,int)), this, SLOT(scrollBy(int,int)) ); connect(_zoomer, SIGNAL( zoomArea(int,int)), this, SLOT(center(int,int)) ); connect(this,SIGNAL(contentsMoving(int,int)), _zoomer, (SLOT(setVisiblePoint(int,int))) ); connect(this,SIGNAL(imageSizeChanged(const QSize&)), _zoomer, SLOT(setImageSize(const QSize&)) ); connect(this,SIGNAL(viewportSizeChanged(const QSize&)), _zoomer, SLOT(setViewPortSize(const QSize&)) ); setBackgroundColor(white); setFocusPolicy(QWidget::StrongFocus); setImageScaledLoaded(false); setImageIsJpeg(false); if (FirstResizeDone()) { m_last_rot = Rotate0; generateImage(); } else if (_original_data.size().isValid()) { if (image_fit_into(_original_data.size()) || !ShowZoomer()) _zoomer->hide(); resizeContents(_original_data.width(),_original_data.height()); } } void OImageScrollView::setAutoRotate(bool how) { /* to avoid double repaints */ if (AutoRotate() != how) { m_states.setBit(AUTO_ROTATE,how); _image_data = QImage(); generateImage(); } } bool OImageScrollView::AutoRotate()const { return m_states.testBit(AUTO_ROTATE); } void OImageScrollView::setAutoScaleRotate(bool scale, bool rotate) { m_states.setBit(AUTO_ROTATE,rotate); setAutoScale(scale); } void OImageScrollView::setAutoScale(bool how) { m_states.setBit(AUTO_SCALE,how); _image_data = QImage(); if (ImageIsJpeg() && how == false && ImageScaledLoaded()==true) { loadJpeg(true); } generateImage(); } bool OImageScrollView::AutoScale()const { return m_states.testBit(AUTO_SCALE); } OImageScrollView::~OImageScrollView() { } void OImageScrollView::rescaleImage(int w, int h) { if (_image_data.width()==w && _image_data.height()==h) { return; } double hs = (double)h / (double)_image_data.height() ; double ws = (double)w / (double)_image_data.width() ; double scaleFactor = (hs > ws) ? ws : hs; int smoothW = (int)(scaleFactor * _image_data.width()); int smoothH = (int)(scaleFactor * _image_data.height()); _image_data = _image_data.smoothScale(smoothW,smoothH); } void OImageScrollView::rotate_into_data(Rotation r) { /* realy - we must do this that way, 'cause when acting direct on _image_data the app will segfault :( */ QImage dest; int x, y; if ( _original_data.depth() > 8 ) { unsigned int *srcData, *destData; switch ( r ) { case Rotate90: dest.create(_original_data.height(), _original_data.width(), _original_data.depth()); for ( y=0; y < _original_data.height(); ++y ) { srcData = (unsigned int *)_original_data.scanLine(y); for ( x=0; x < _original_data.width(); ++x ) { destData = (unsigned int *)dest.scanLine(x); destData[_original_data.height()-y-1] = srcData[x]; } } break; case Rotate180: dest.create(_original_data.width(), _original_data.height(), _original_data.depth()); for ( y=0; y < _original_data.height(); ++y ) { srcData = (unsigned int *)_original_data.scanLine(y); destData = (unsigned int *)dest.scanLine(_original_data.height()-y-1); for ( x=0; x < _original_data.width(); ++x ) destData[_original_data.width()-x-1] = srcData[x]; } break; case Rotate270: dest.create(_original_data.height(), _original_data.width(), _original_data.depth()); for ( y=0; y < _original_data.height(); ++y ) { srcData = (unsigned int *)_original_data.scanLine(y); for ( x=0; x < _original_data.width(); ++x ) { destData = (unsigned int *)dest.scanLine(_original_data.width()-x-1); destData[y] = srcData[x]; } } break; default: dest = _original_data; break; } } else { unsigned char *srcData, *destData; unsigned int *srcTable, *destTable; switch ( r ) { case Rotate90: dest.create(_original_data.height(), _original_data.width(), _original_data.depth()); dest.setNumColors(_original_data.numColors()); srcTable = (unsigned int *)_original_data.colorTable(); destTable = (unsigned int *)dest.colorTable(); for ( x=0; x < _original_data.numColors(); ++x ) destTable[x] = srcTable[x]; for ( y=0; y < _original_data.height(); ++y ) { srcData = (unsigned char *)_original_data.scanLine(y); for ( x=0; x < _original_data.width(); ++x ) { destData = (unsigned char *)dest.scanLine(x); destData[_original_data.height()-y-1] = srcData[x]; } } break; case Rotate180: dest.create(_original_data.width(), _original_data.height(), _original_data.depth()); dest.setNumColors(_original_data.numColors()); srcTable = (unsigned int *)_original_data.colorTable(); destTable = (unsigned int *)dest.colorTable(); for ( x=0; x < _original_data.numColors(); ++x ) destTable[x] = srcTable[x]; for ( y=0; y < _original_data.height(); ++y ) { srcData = (unsigned char *)_original_data.scanLine(y); destData = (unsigned char *)dest.scanLine(_original_data.height()-y-1); for ( x=0; x < _original_data.width(); ++x ) destData[_original_data.width()-x-1] = srcData[x]; } break; case Rotate270: dest.create(_original_data.height(), _original_data.width(), _original_data.depth()); dest.setNumColors(_original_data.numColors()); srcTable = (unsigned int *)_original_data.colorTable(); destTable = (unsigned int *)dest.colorTable(); for ( x=0; x < _original_data.numColors(); ++x ) destTable[x] = srcTable[x]; for ( y=0; y < _original_data.height(); ++y ) { srcData = (unsigned char *)_original_data.scanLine(y); for ( x=0; x < _original_data.width(); ++x ) { destData = (unsigned char *)dest.scanLine(_original_data.width()-x-1); destData[y] = srcData[x]; } } break; default: dest = _original_data; break; } } _image_data = dest; } void OImageScrollView::generateImage() { Rotation r = Rotate0; _pdata = QPixmap(); if (_original_data.isNull()) { emit imageSizeChanged( _image_data.size() ); if (_zoomer) _zoomer->setImage( _image_data ); return; } if (width()>height()&&_original_data.width()<_original_data.height() || width()<height()&&_original_data.width()>_original_data.height()) { if (AutoRotate()) r = Rotate90; } int twidth,theight; odebug << " r = " << r << oendl; if (AutoScale() && (_original_data.width()>width() || _original_data.height() > height()) ) { if (!_image_data.size().isValid()||width()>_image_data.width()||height()>_image_data.height()) { odebug << "Rescaling data" << oendl; if (r==Rotate0) { _image_data = _original_data; } else { rotate_into_data(r); } } rescaleImage(width(),height()); } else if (!FirstResizeDone()||r!=m_last_rot||_image_data.width()==0) { if (r==Rotate0) { _image_data = _original_data; } else { rotate_into_data(r); } m_last_rot = r; } _pdata.convertFromImage(_image_data); twidth = _image_data.width(); theight = _image_data.height(); /* * update the zoomer */ check_zoomer(); emit imageSizeChanged( _image_data.size() ); rescaleImage( 128, 128 ); resizeContents(twidth,theight); /* * move scrollbar */ if (_zoomer) { _zoomer->setGeometry( viewport()->width()-_image_data.width()/2, viewport()->height()-_image_data.height()/2, _image_data.width()/2, _image_data.height()/2 ); _zoomer->setImage( _image_data ); } /* * invalidate */ _image_data=QImage(); if (isVisible()) { updateContents(contentsX(),contentsY(),width(),height()); } } void OImageScrollView::resizeEvent(QResizeEvent * e) { odebug << "OImageScrollView resizeEvent (" << e->size() << " - " << e->oldSize() << oendl; QScrollView::resizeEvent(e); if (e->oldSize()==e->size()||!isUpdatesEnabled ()) return; generateImage(); setFirstResizeDone(true); emit viewportSizeChanged( viewport()->size() ); } void OImageScrollView::keyPressEvent(QKeyEvent * e) { if (!e) return; int dx = horizontalScrollBar()->lineStep(); int dy = verticalScrollBar()->lineStep(); if (e->key()==Qt::Key_Right) { scrollBy(dx,0); e->accept(); } else if (e->key()==Qt::Key_Left) { scrollBy(0-dx,0); e->accept(); } else if (e->key()==Qt::Key_Up) { scrollBy(0,0-dy); e->accept(); } else if (e->key()==Qt::Key_Down) { scrollBy(0,dy); e->accept(); } else { e->ignore(); } QScrollView::keyPressEvent(e); } void OImageScrollView::drawContents(QPainter * p, int clipx, int clipy, int clipw, int cliph) { if (!_pdata.size().isValid()) { p->fillRect(clipx,clipy,clipw,cliph, backgroundColor()); return; } int w = clipw; int h = cliph; int x = clipx; int y = clipy; bool erase = false; if (w>_pdata.width()) { w = _pdata.width()-x; erase=true; } if (h>_pdata.height()) { h = _pdata.height()-y; erase=true; } if (!erase && (clipy+cliph>_pdata.height()||clipx+clipw>_pdata.width())) { erase = true; } if (erase||_original_data.hasAlphaBuffer()) { p->fillRect(clipx,clipy,clipw,cliph, backgroundColor()); } if (w>0 && h>0&&x<_pdata.width()&&y<_pdata.height()) { p->drawPixmap(clipx,clipy,_pdata,x,y,w,h); } } /* using the real geometry points and not the translated points is wanted! */ void OImageScrollView::viewportMouseMoveEvent(QMouseEvent* e) { int mx, my; mx = e->x(); my = e->y(); if (_mouseStartPosX!=-1 && _mouseStartPosY!=-1) { int diffx = _mouseStartPosX-mx; int diffy = _mouseStartPosY-my; scrollBy(diffx,diffy); } _mouseStartPosX=mx; _mouseStartPosY=my; } void OImageScrollView::contentsMousePressEvent ( QMouseEvent * e) { odebug << " X and Y " << e->x() << " " << e->y() << oendl; /* this marks the beginning of a possible mouse move. Due internal reasons of QT the geometry values here may real differ from that set in MoveEvent (I don't know why). For getting them in real context, we use the first move-event to set the start position ;) */ _mouseStartPosX = -1; _mouseStartPosY = -1; } void OImageScrollView::setDestructiveClose() { WFlags fl = getWFlags(); /* clear it just in case */ fl &= ~WDestructiveClose; fl |= WDestructiveClose; setWFlags( fl ); } bool OImageScrollView::image_fit_into(const QSize&s ) { if (s.width()>width()||s.height()>height()) { return false; } return true; } void OImageScrollView::setShowZoomer(bool how) { m_states.setBit(SHOW_ZOOMER,how); check_zoomer(); } bool OImageScrollView::ShowZoomer()const { return m_states.testBit(SHOW_ZOOMER); } void OImageScrollView::check_zoomer() { if (!_zoomer) return; if ( (!ShowZoomer()||image_fit_into(_pdata.size()) ) && _zoomer->isVisible()) { _zoomer->hide(); } else if ( ShowZoomer() && !image_fit_into(_pdata.size()) && _zoomer->isHidden()){ _zoomer->show(); } } bool OImageScrollView::FirstResizeDone()const { return m_states.testBit(FIRST_RESIZE_DONE); } void OImageScrollView::setFirstResizeDone(bool how) { m_states.setBit(FIRST_RESIZE_DONE,how); } bool OImageScrollView::ImageIsJpeg()const { return m_states.testBit(IMAGE_IS_JPEG); } void OImageScrollView::setImageIsJpeg(bool how) { m_states.setBit(IMAGE_IS_JPEG,how); } bool OImageScrollView::ImageScaledLoaded()const { return m_states.testBit(IMAGE_SCALED_LOADED); } void OImageScrollView::setImageScaledLoaded(bool how) { m_states.setBit(IMAGE_SCALED_LOADED,how); } } // namespace MM } // namespace Opie |