summaryrefslogtreecommitdiff
authoralwin <alwin>2004-04-14 12:39:03 (UTC)
committer alwin <alwin>2004-04-14 12:39:03 (UTC)
commit4f78995cbb47f78e68eb40d9a86a6a0dcdc576eb (patch) (side-by-side diff)
tree24f22c258d4fac1924c0be938dca7a5b52a5a3d4
parent3ed50198400e432b308ca58178f562e2e256de0e (diff)
downloadopie-4f78995cbb47f78e68eb40d9a86a6a0dcdc576eb.zip
opie-4f78995cbb47f78e68eb40d9a86a6a0dcdc576eb.tar.gz
opie-4f78995cbb47f78e68eb40d9a86a6a0dcdc576eb.tar.bz2
jpegs will be loaded scaled if needed for a faster preview loading
Diffstat (more/less context) (show whitespace changes)
-rw-r--r--noncore/graphics/opie-eye/gui/imagescrollview.cpp74
-rw-r--r--noncore/graphics/opie-eye/gui/imagescrollview.h3
2 files changed, 77 insertions, 0 deletions
diff --git a/noncore/graphics/opie-eye/gui/imagescrollview.cpp b/noncore/graphics/opie-eye/gui/imagescrollview.cpp
index 2f16d82..d034ee0 100644
--- a/noncore/graphics/opie-eye/gui/imagescrollview.cpp
+++ b/noncore/graphics/opie-eye/gui/imagescrollview.cpp
@@ -1,426 +1,500 @@
#include "imagescrollview.h"
#include <opie2/odebug.h>
+#include <opie2/oapplication.h>
+#include <opie2/owait.h>
using namespace Opie::Core;
#include <qimage.h>
#include <qlayout.h>
+#include <qpe/qcopenvelope_qws.h>
ImageScrollView::ImageScrollView( QWidget* parent, const char* name, WFlags f )
:QScrollView(parent,name,f|Qt::WRepaintNoErase ),_image_data(),_original_data(),scale_to_fit(true),
rotate_to_fit(true),show_zoomer(true),first_resize_done(false),m_lastName("")
{
init();
}
ImageScrollView::ImageScrollView (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),scale_to_fit(always_scale),
rotate_to_fit(rfit),show_zoomer(true),first_resize_done(false),m_lastName("")
{
_original_data.convertDepth(QPixmap::defaultDepth());
_original_data.setAlphaBuffer(false);
init();
}
ImageScrollView::ImageScrollView (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(),scale_to_fit(always_scale),
rotate_to_fit(rfit),show_zoomer(true),first_resize_done(false),m_lastName("")
{
init();
setImage(img);
}
void ImageScrollView::setImage(const QImage&img)
{
_image_data = QImage();
_original_data=img;
_original_data.convertDepth(QPixmap::defaultDepth());
_original_data.setAlphaBuffer(false);
m_lastName = "";
+ image_is_jpeg = false;
+ image_scaled_loaded = false;
if (first_resize_done) {
generateImage();
}
}
+void ImageScrollView::loadJpeg(bool interncall)
+{
+ if (m_lastName.isEmpty()) return;
+ QImageIO iio( m_lastName, 0l );
+ QString param;
+ bool real_load = false;
+ if (scale_to_fit) {
+ if (!interncall) {
+ int wid, hei;
+ wid = QApplication::desktop()->width();
+ hei = QApplication::desktop()->height();
+ if (hei>wid) {
+ wid = hei;
+ } else {
+ hei = wid;
+ }
+ param = QString( "Fast Shrink( 7 ) Scale( %1, %2, ScaleFree)" ).arg( wid ).arg( hei );
+ odebug << "Load jpeg scaled \"" << param << "\"" << oendl;
+ iio.setParameters(param.latin1());
+ image_scaled_loaded = true;
+ real_load = true;
+ }
+ } else {
+ if (image_scaled_loaded||!interncall) {
+ odebug << "Load jpeg unscaled" << oendl;
+ real_load = true;
+ }
+ image_scaled_loaded = false;
+ }
+ if (real_load) {
+ {
+ QCopEnvelope( "QPE/System", "busy()" );
+ }
+ _original_data = iio.read() ? iio.image() : QImage();
+ {
+ QCopEnvelope env( "QPE/System", "notBusy(QString)" );
+ env << "Image loaded";
+ }
+ }
+}
+
void ImageScrollView::setImage( const QString& path ) {
odebug << "load new image " << oendl;
if (m_lastName == path) return;
m_lastName = path;
+ QString itype = QImage::imageFormat(m_lastName);
+ odebug << "Image type = " << itype << oendl;
+ if (itype == "JPEG") {
+ image_is_jpeg = true;
+ loadJpeg();
+ } else {
+ {
+ QCopEnvelope( "QPE/System", "busy()" );
+ }
+ image_is_jpeg = false;
_original_data.load(path);
_original_data.convertDepth(QPixmap::defaultDepth());
_original_data.setAlphaBuffer(false);
+ {
+ QCopEnvelope env( "QPE/System", "notBusy(QString)" );
+ env << "Image loaded";
+ }
+ }
_image_data = QImage();
if (first_resize_done) {
generateImage();
}
}
/* should be called every time the QImage changed it content */
void ImageScrollView::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(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&)) );
viewport()->setBackgroundColor(white);
setFocusPolicy(QWidget::StrongFocus);
+ image_scaled_loaded = false;
+ image_is_jpeg = false;
if (first_resize_done) {
last_rot = Rotate0;
generateImage();
} else if (_original_data.size().isValid()) {
if (image_fit_into(_original_data.size()) || !show_zoomer) _zoomer->hide();
resizeContents(_original_data.width(),_original_data.height());
}
}
void ImageScrollView::setAutoRotate(bool how)
{
/* to avoid double repaints */
if (rotate_to_fit != how) {
rotate_to_fit = how;
_image_data = QImage();
generateImage();
}
}
void ImageScrollView::setAutoScale(bool how)
{
scale_to_fit = how;
if (!how) {
rotate_to_fit = false;
}
_image_data = QImage();
+ if (image_is_jpeg && how == false && image_scaled_loaded==true) {
+ loadJpeg(true);
+ }
generateImage();
}
ImageScrollView::~ImageScrollView()
{
}
void ImageScrollView::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 ImageScrollView::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 ImageScrollView::generateImage()
{
Rotation r = Rotate0;
+ {
+ QCopEnvelope( "QPE/System", "busy()" );
+ }
if (width()>height()&&_original_data.width()<_original_data.height() ||
width()<height()&&_original_data.width()>_original_data.height()) {
if (rotate_to_fit) r = Rotate90;
}
+
odebug << " r = " << r << oendl;
if (scale_to_fit) {
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());
resizeContents(_image_data.width(),_image_data.height());
} else if (!first_resize_done||r!=last_rot||_image_data.width()==0) {
if (r==Rotate0) {
_image_data = _original_data;
} else {
rotate_into_data(r);
}
last_rot = r;
resizeContents(_image_data.width(),_image_data.height());
}
_pdata.convertFromImage(_image_data);
/*
* update the zoomer
*/
check_zoomer();
emit imageSizeChanged( _image_data.size() );
rescaleImage( 128, 128 );
/*
* move scrollbar
*/
_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();
+ {
+ QCopEnvelope env( "QPE/System", "notBusy(QString)" );
+ env << "Image generated";
+ }
}
void ImageScrollView::resizeEvent(QResizeEvent * e)
{
odebug << "ImageScrollView resizeEvent" << oendl;
QScrollView::resizeEvent(e);
generateImage();
first_resize_done = true;
emit viewportSizeChanged( viewport()->size() );
}
void ImageScrollView::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 ImageScrollView::drawContents(QPainter * p, int clipx, int clipy, int clipw, int cliph)
{
int w = clipw;
int h = cliph;
int x = clipx;
int y = clipy;
bool erase = false;
if (!_pdata.size().isValid()) {
p->fillRect(clipx,clipy,clipw,cliph,white);
return;
}
if (w>_pdata.width()) {
w=_pdata.width();
x = 0;
erase = true;
} else if (x+w>_pdata.width()){
x = _pdata.width()-w;
}
if (h>_pdata.height()) {
h=_pdata.height();
y = 0;
erase = true;
} else if (y+h>_pdata.height()){
y = _pdata.height()-h;
}
if (erase||_original_data.hasAlphaBuffer()) {
p->fillRect(clipx,clipy,clipw,cliph,white);
}
p->drawPixmap(clipx,clipy,_pdata,x,y,w,h);
}
/* using the real geometry points and not the translated points is wanted! */
void ImageScrollView::viewportMouseMoveEvent(QMouseEvent* e)
{
odebug << "Move X and Y " << e->x() << " " << e->y() << oendl;
int mx, my;
mx = e->x();
my = e->y();
if (_mouseStartPosX!=-1 && _mouseStartPosY!=-1) {
int diffx = _mouseStartPosX-mx;
int diffy = _mouseStartPosY-my;
#if 0
QScrollBar*xbar = horizontalScrollBar();
QScrollBar*ybar = verticalScrollBar();
if (xbar->value()+diffx>xbar->maxValue()) {
diffx = xbar->maxValue()-xbar->value();
} else if (xbar->value()+diffx<0) {
diffx=0-xbar->value();
}
if (ybar->value()+diffy>ybar->maxValue()) {
diffy = ybar->maxValue()-ybar->value();
} else if (ybar->value()+diffy<0) {
diffy=0-ybar->value();
}
#endif
scrollBy(diffx,diffy);
}
_mouseStartPosX=mx;
_mouseStartPosY=my;
}
void ImageScrollView::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 ImageScrollView::setDestructiveClose() {
WFlags fl = getWFlags();
/* clear it just in case */
fl &= ~WDestructiveClose;
fl |= WDestructiveClose;
setWFlags( fl );
}
bool ImageScrollView::image_fit_into(const QSize&s )
{
if (s.width()>width()||s.height()>height()) {
return false;
}
return true;
}
void ImageScrollView::setShowZoomer(bool how)
{
show_zoomer = how;
check_zoomer();
}
void ImageScrollView::check_zoomer()
{
if ( (!show_zoomer||image_fit_into(_pdata.size()) ) && _zoomer->isVisible()) {
_zoomer->hide();
} else if ( show_zoomer && !image_fit_into(_pdata.size()) && _zoomer->isHidden()){
_zoomer->show();
}
}
diff --git a/noncore/graphics/opie-eye/gui/imagescrollview.h b/noncore/graphics/opie-eye/gui/imagescrollview.h
index e209dfb..f6e187d 100644
--- a/noncore/graphics/opie-eye/gui/imagescrollview.h
+++ b/noncore/graphics/opie-eye/gui/imagescrollview.h
@@ -1,75 +1,78 @@
#ifndef _IMAGE_SCROLL_VIEW_H
#define _IMAGE_SCROLL_VIEW_H
#include <lib/oimagezoomer.h>
#include <qscrollview.h>
#include <qimage.h>
#include <qpixmap.h>
#include <qstring.h>
#include <qdialog.h>
class QPainter;
class ImageScrollView:public QScrollView
{
Q_OBJECT
public:
ImageScrollView( QWidget* parent, const char* name = 0, WFlags fl = 0 );
ImageScrollView (const QImage&, QWidget * parent=0, const char * name=0, WFlags f=0,bool always_scale=false,bool rfit=false );
ImageScrollView (const QString&, QWidget * parent=0, const char * name=0, WFlags f=0,bool always_scale=false,bool rfit=false );
virtual ~ImageScrollView();
virtual void setImage(const QImage&);
virtual void setImage( const QString& path );
virtual void setDestructiveClose();
virtual void setAutoRotate(bool);
virtual void setAutoScale(bool);
virtual void setShowZoomer(bool);
enum Rotation {
Rotate0,
Rotate90,
Rotate180,
Rotate270
};
signals:
void sig_return();
void imageSizeChanged( const QSize& );
void viewportSizeChanged( const QSize& );
protected:
virtual void drawContents ( QPainter * p, int clipx, int clipy, int clipw, int cliph );
void init();
Opie::MM::OImageZoomer *_zoomer;
QImage _image_data;
QImage _original_data;
QPixmap _pdata;
int _mouseStartPosX,_mouseStartPosY;
bool scale_to_fit;
bool rotate_to_fit;
bool show_zoomer;
bool first_resize_done;
+ bool image_is_jpeg;
+ bool image_scaled_loaded;
Rotation last_rot;
QString m_lastName;
virtual void rescaleImage(int w, int h);
virtual void rotate_into_data(Rotation r);
virtual void generateImage();
+ virtual void loadJpeg(bool interncall = false);
bool image_fit_into(const QSize&s);
void check_zoomer();
protected slots:
virtual void viewportMouseMoveEvent(QMouseEvent* e);
virtual void contentsMousePressEvent ( QMouseEvent * e);
virtual void resizeEvent(QResizeEvent * e);
virtual void keyPressEvent(QKeyEvent * e);
};
#endif