summaryrefslogtreecommitdiff
path: root/libopie2/opiemm/oimagescrollview.cpp
Side-by-side diff
Diffstat (limited to 'libopie2/opiemm/oimagescrollview.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--libopie2/opiemm/oimagescrollview.cpp5
1 files changed, 4 insertions, 1 deletions
diff --git a/libopie2/opiemm/oimagescrollview.cpp b/libopie2/opiemm/oimagescrollview.cpp
index 10da823..76f50e1 100644
--- a/libopie2/opiemm/oimagescrollview.cpp
+++ b/libopie2/opiemm/oimagescrollview.cpp
@@ -16,529 +16,532 @@
#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;
_newImage = 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);
_newImage = true;
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;
_newImage = 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);
_newImage = true;
if (FirstResizeDone()) {
generateImage();
}
}
void OImageScrollView::loadJpeg(bool interncall)
{
if (m_lastName.isEmpty()) return;
QImageIO iio( m_lastName, 0l );
QString param;
bool real_load = false;
_newImage = true;
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;
}
if ( (scanned && (wid<xf.getWidth()||hei<xf.getHeight()))||!scanned ) {
param = QString( "Fast Shrink( 3 ) Scale( %1, %2, ScaleMin)" ).arg( wid ).arg( hei );
iio.setParameters(param.latin1());
setImageScaledLoaded(true);
}
real_load = true;
}
} else {
if (ImageScaledLoaded()||!interncall) {
real_load = true;
}
setImageScaledLoaded(false);
}
if (real_load) {
_original_data = iio.read() ? iio.image() : QImage();
}
}
void OImageScrollView::setImage( const QString& path ) {
if (m_lastName == path) return;
m_lastName = path;
_newImage = true;
_original_data = QImage();
QString itype = QImage::imageFormat(m_lastName);
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()
{
/*
* 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());
}
_intensity = 0;
}
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);
}
+ _newImage = 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;
}
}
_newImage = true;
_image_data = dest;
}
// yes - sorry - it is NOT gamma it is just BRIGHTNESS. Alwin
void OImageScrollView::apply_gamma(int aValue)
{
- if (!_image_data.size().isValid()) return;
+ if (aValue==0 || !_image_data.size().isValid()) return;
float percent = ((float)aValue/100.0);
+ /* make sure working on a copy */
+ _image_data.detach();
int segColors = _image_data.depth() > 8 ? 256 : _image_data.numColors();
/* must be - otherwise it displays some ... strange colors */
if (segColors<256) segColors=256;
unsigned char *segTbl = new unsigned char[segColors];
int pixels = _image_data.depth()>8?_image_data.width()*_image_data.height() : _image_data.numColors();
bool brighten = (percent >= 0);
if ( percent < 0 ) {
percent = -percent;
}
unsigned int *data = _image_data.depth() > 8 ? (unsigned int *)_image_data.bits() :
(unsigned int *)_image_data.colorTable();
int tmp = 0;
if (brighten) {
for ( int i=0; i < segColors; ++i )
{
tmp = (int)(i*percent);
if ( tmp > 255 )
tmp = 255;
segTbl[i] = tmp;
}
} else {
for ( int i=0; i < segColors; ++i )
{
tmp = (int)(i*percent);
if ( tmp < 0 )
tmp = 0;
segTbl[i] = tmp;
}
}
if (brighten) {
for ( int i=0; i < pixels; ++i )
{
int r = qRed(data[i]);
int g = qGreen(data[i]);
int b = qBlue(data[i]);
int a = qAlpha(data[i]);
r = r + segTbl[r] > 255 ? 255 : r + segTbl[r];
g = g + segTbl[g] > 255 ? 255 : g + segTbl[g];
b = b + segTbl[b] > 255 ? 255 : b + segTbl[b];
data[i] = qRgba(r, g, b,a);
}
} else {
for ( int i=0; i < pixels; ++i )
{
int r = qRed(data[i]);
int g = qGreen(data[i]);
int b = qBlue(data[i]);
int a = qAlpha(data[i]);
r = r - segTbl[r] < 0 ? 0 : r - segTbl[r];
g = g - segTbl[g] < 0 ? 0 : g - segTbl[g];
b = b - segTbl[b] < 0 ? 0 : b - segTbl[b];
data[i] = qRgba(r, g, b, a);
}
}
delete [] segTbl;
}
const int OImageScrollView::Intensity()const
{
return _intensity;
}
int OImageScrollView::setIntensity(int value,bool reload)
{
int oldi = _intensity;
_intensity = value;
if (!_pdata.size().isValid()) {
return _intensity;
}
if (!reload) {
_image_data = _pdata.convertToImage();
apply_gamma(_intensity-oldi);
_pdata.convertFromImage(_image_data);
/*
* invalidate
*/
_image_data=QImage();
if (isVisible()) {
updateContents(contentsX(),contentsY(),width(),height());
}
} else {
_newImage = true;
generateImage();
}
return _intensity;
}
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;
if (AutoScale() && (_original_data.width()>width() || _original_data.height() > height()) ) {
if (!_image_data.size().isValid()||width()>_image_data.width()||height()>_image_data.height()) {
if (r==Rotate0) {
_image_data = _original_data;
} else {
rotate_into_data(r);
}
_newImage = true;
}
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;
}
if (_newImage) {
apply_gamma(_intensity);
_newImage = false;
}
_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)
{
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();
}