[SOLVED] Cursor and image coordinates(problem with scaling)
-
wrote on 9 May 2011, 10:42 last edited by
I have an MDI Application. Each child window is QWidget based class. This class(ImageWidget class) contains scroll area and QLabel in this area. In Qlabel we have image (like in Qt examples Image viewer) and I have zoomIn and zoomOut, normalSize functions there. So I add a function to process the image, and need actually know coordinates of image selected pixel by cursor coordinates:
@void ImageWidget::mousePressEvent( QMouseEvent * event )
{
int x = event->pos().x();
int y = event->pos().y();// Calculate scale and image sizes
int h = m_imageLabel->height();
int w = m_imageLabel->width();if(x>w || y>h)
return;x = x/m_scaleFactor;
y = y/m_scaleFactor;QRgb pixel = m_image.pixel(x,y);
QColor color = QColor::fromRgb(pixel);
}@
So if my image is zoomed out I can get right coordinates by dividing current coordinates(each of it x and y) to scale factor. But if image is zoomed in and it's new size more then size of widgets this method don't work and I get wrong coordinates. what can I do now ? -
wrote on 9 May 2011, 10:59 last edited by
Hi Anticross,
Make x and y doubles
make m_scaleFactor a double with 1.0 = 100 %
make m_scaleFactor > 1.0 zoomed in and < 1.0 scaled out and use:
@
x *= m_scaleFactor;
y *= m_scaleFactor;
@ -
wrote on 9 May 2011, 11:30 last edited by
I modified it and now it looks like this:
@void ImageWidget::mousePressEvent( QMouseEvent * event )
{
double x = event->pos().x();
double y = event->pos().y();// Calculate scale and image sizes
double h = m_imageLabel->height();
double w = m_imageLabel->width();if(x>w || y>h)
return;if(h>size().height() || w>size().width())
{
m_scaleFactor = 1.0;
}x *= m_scaleFactor;
y *= m_scaleFactor;QRgb pixel = m_image.pixel(x,y);
QColor color = QColor::fromRgb(pixel);
}@ but I still have wrong coords(sometimes with some offset from right coords).
-
wrote on 9 May 2011, 14:41 last edited by
The whole source of ImageViever class is
*.cpp:
@#include "ImageWidget.h"//-----------------------------------------------------------------------------
ImageWidget::ImageWidget( QWidget * parent, const QString & filename ) : QWidget(parent)
{
m_imageLabel = new QLabel();
m_imageLabel->setBackgroundRole(QPalette::Base);
m_imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
m_imageLabel->setScaledContents(true);m_scrollArea = new QScrollArea(this);
m_scrollArea->setBackgroundRole(QPalette::Dark);
m_scrollArea->setWidget(m_imageLabel);QVBoxLayout * layout = new QVBoxLayout();
layout->addWidget(m_scrollArea);
setLayout(layout);setWindowTitle(filename);
resize(500, 400);// open file
m_image = QImage(filename);
if (m_image.isNull()) {
QMessageBox::information(this, tr("Warning"),
tr("Cannot load %1.").arg(filename));
return;
}m_imageLabel->setPixmap(QPixmap::fromImage(m_image));
m_scaleFactor = 1.0;
normalSize();m_pixelatorFlag = false;
//connect(parent->ui.actionPixelator, SIGNAL(triggered()), this, SLOT(pixelatorOn()));
}
//-----------------------------------------------------------------------------
void ImageWidget::zoomIn()
{scaleImage(1.25);
}
//-----------------------------------------------------------------------------
void ImageWidget::zoomOut()
{
scaleImage(0.8);
}
//-----------------------------------------------------------------------------
void ImageWidget::normalSize()
{
m_imageLabel->adjustSize();
m_scaleFactor = 1.0;
}
//-----------------------------------------------------------------------------
void ImageWidget::fitToWindow( bool fitToWindow )
{
m_scrollArea->setWidgetResizable(fitToWindow);
if (!fitToWindow) {
normalSize();
}
}
//-----------------------------------------------------------------------------
void ImageWidget::scaleImage( double factor )
{
Q_ASSERT(m_imageLabel->pixmap());
m_scaleFactor *= factor;
m_imageLabel->resize(m_scaleFactor * m_imageLabel->pixmap()->size());adjustScrollBar(m_scrollArea->horizontalScrollBar(), factor);
adjustScrollBar(m_scrollArea->verticalScrollBar(), factor);
}
//-----------------------------------------------------------------------------
void ImageWidget::adjustScrollBar( QScrollBar *scrollBar, double factor )
{
scrollBar->setValue(int(factor * scrollBar->value()- ((factor - 1) * scrollBar->pageStep()/2)));
}
//-----------------------------------------------------------------------------
void ImageWidget::mousePressEvent( QMouseEvent * event )
{
double x = event->pos().x();
double y = event->pos().y();
// Calculate scale and image sizes
double h = m_imageLabel->height();
double w = m_imageLabel->width();if(x>w || y>h)
return;if(h>size().height() || w>size().width())
{
m_scaleFactor = 1.0;
}x *= m_scaleFactor;
y *= m_scaleFactor;QRgb pixel = m_image.pixel(x,y);
QColor color = QColor::fromRgb(pixel);
emit colorSelected(color.name(),x,y);
proccessImage(color,false);
}
//-----------------------------------------------------------------------------
void ImageWidget::proccessImage(QColor color, bool inverse)
{
// Search algorithmQImage image = m_image;
int difference = 20;for(int y = 0; y < image.height(); y++)
{
for(int x = 0; x < image.width(); x++)
{
QRgb currentPixel = image.pixel(x,y);if( qAbs(qRed(currentPixel) - color.red()) > difference &&
qAbs(qGreen(currentPixel) - color.green()) > difference &&
qAbs(qBlue(currentPixel) - color.blue()) > difference)
{
if(!inverse)
image.setPixel(x,y,qRgb(255,255,255));
}
else
{
if(inverse)
image.setPixel(x,y,qRgb(255,255,255));
}
}
}
m_imageLabel->setPixmap(QPixmap::fromImage(image));
}
//-----------------------------------------------------------------------------
void ImageWidget::pixelatorOn()
{
// QAction * act = (QAction *)QObject::sender();
//
// if(act == NULL)
// return;
//
// if(act->isChecked())
// m_pixelatorFlag = true;
// else
// m_pixelatorFlag = false;
}
//-----------------------------------------------------------------------------
@
*.h:
@#ifndef IMAGEWIDGET_H
#define IMAGEWIDGET_H#include <QWidget>
#include <QScrollBar>
#include <QScrollArea>
#include <QLabel>
#include <QMessageBox>
#include <QVBoxLayout>
#include <QMouseEvent>
#include <QColor>class ImageWidget : public QWidget
{
Q_OBJECTQLabel *m_imageLabel;
QScrollArea *m_scrollArea;
double m_scaleFactor;
QImage m_image;
bool m_pixelatorFlag;public:
ImageWidget(QWidget * parent, const QString & filename);
void zoomIn();
void zoomOut();
void normalSize();
void fitToWindow(bool fitToWindow);private:
void scaleImage(double factor);
void adjustScrollBar(QScrollBar *scrollBar, double factor);
void proccessImage(QColor color, bool inverse);protected:
void mousePressEvent(QMouseEvent * event);public slots:
void pixelatorOn();signals:
void colorSelected(const QString & color, int x, int y);};
#endif//IMAGEWIDGET_H
@Maybe I miss something when editing qt example and thats why I get wrong coords ?
- ((factor - 1) * scrollBar->pageStep()/2)));
-
wrote on 9 May 2011, 14:49 last edited by
You handle the mouse event with coordinates of teh ImageWidget class, but the picture is displayed in a subwidget. Map the coordinates to the label and it should work.
-
wrote on 9 May 2011, 15:07 last edited by
I replace 84-85 rows of my cpp file by this:
@QPoint pos = m_imageLabel->mapFromParent(event->pos());
double x = pos.x();
double y = pos.y();@And it's worked, thx Gerolf.
-
wrote on 28 May 2011, 11:43 last edited by
Same trouble after some modificatin. When zoomOut and then make a click. Coordinates moved up left from real position, and after zoomOut its moved down right. Changed code looks like this:
*.h
@#ifndef IMAGEWIDGET_H
#define IMAGEWIDGET_H#include <QWidget>
#include <QScrollBar>
#include <QScrollArea>
#include <QLabel>
#include <QMessageBox>
#include <QVBoxLayout>
#include <QMouseEvent>
#include <QColor>
#include <QGraphicsItem>enum curAction {ePixel, eErase, eNoact};
class ImageWidget : public QWidget
{
Q_OBJECTQLabel *m_imageLabel;
QScrollArea *m_scrollArea;
double m_scaleFactor;
QImage m_image;
bool m_pixelatorFlag;
int m_difference;
QColor m_currentColor;
curAction m_action;public:
ImageWidget(QWidget * parent, const QString & filename);
void zoomIn();
void zoomOut();
void normalSize();
void fitToWindow(bool fitToWindow);
void setCurrentAction(curAction action);private:
void scaleImage(double factor);
void adjustScrollBar(QScrollBar *scrollBar, double factor);
void proccessImage(QColor color, bool inverse);
void eraseImage(const QPointF & startPoint,const QPointF & endPoint);
void revertChanges();protected:
void mousePressEvent(QMouseEvent * event);
void keyPressEvent (QKeyEvent * event);public slots:
void onChangeDifference(int difference);signals:
void colorSelected(const QString & color, int x, int y);};
#endif//IMAGEWIDGET_H
@ -
wrote on 28 May 2011, 11:43 last edited by
*.cpp
@#include "ImageWidget.h"//-----------------------------------------------------------------------------
ImageWidget::ImageWidget( QWidget * parent, const QString & filename ) : QWidget(parent)
{
m_imageLabel = new QLabel();
m_imageLabel->setBackgroundRole(QPalette::Base);
m_imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
m_imageLabel->setScaledContents(true);m_scrollArea = new QScrollArea(this);
m_scrollArea->setBackgroundRole(QPalette::Dark);
m_scrollArea->setWidget(m_imageLabel);QVBoxLayout * layout = new QVBoxLayout();
layout->addWidget(m_scrollArea);
setLayout(layout);setWindowTitle(filename);
resize(500, 400);// open file
m_image = QImage(filename);
if (m_image.isNull()) {
QMessageBox::information(this, tr("Warning"),
tr("Cannot load %1.").arg(filename));
return;
}m_imageLabel->setPixmap(QPixmap::fromImage(m_image));
m_scaleFactor = 1.0;
normalSize();m_pixelatorFlag = false;
//connect(parent->ui.actionPixelator, SIGNAL(triggered()), this, SLOT(pixelatorOn()));
m_difference = 20;
m_currentColor = Qt::black;
}
//-----------------------------------------------------------------------------
void ImageWidget::zoomIn()
{scaleImage(1.25);
}
//-----------------------------------------------------------------------------
void ImageWidget::zoomOut()
{
scaleImage(0.8);
}
//-----------------------------------------------------------------------------
void ImageWidget::normalSize()
{
m_imageLabel->adjustSize();
m_scaleFactor = 1.0;
}
//-----------------------------------------------------------------------------
void ImageWidget::fitToWindow( bool fitToWindow )
{
m_scrollArea->setWidgetResizable(fitToWindow);
if (!fitToWindow) {
normalSize();
}
}
//-----------------------------------------------------------------------------
void ImageWidget::scaleImage( double factor )
{
Q_ASSERT(m_imageLabel->pixmap());
m_scaleFactor *= factor;
m_imageLabel->resize(m_scaleFactor * m_imageLabel->pixmap()->size());adjustScrollBar(m_scrollArea->horizontalScrollBar(), factor);
adjustScrollBar(m_scrollArea->verticalScrollBar(), factor);
}
//-----------------------------------------------------------------------------
void ImageWidget::adjustScrollBar( QScrollBar *scrollBar, double factor )
{
scrollBar->setValue(int(factor * scrollBar->value()- ((factor - 1) * scrollBar->pageStep()/2)));
}
//-----------------------------------------------------------------------------
void ImageWidget::mousePressEvent( QMouseEvent * event )
{
QPointF pos = m_imageLabel->mapFromParent(event->pos());
double x = pos.x();
double y = pos.y();// Calculate scale and image sizes
double h = m_imageLabel->height();
double w = m_imageLabel->width();if(x>w || y>h)
return;if(h>size().height() || w>size().width())
{
m_scaleFactor = 1.0;
}x *= m_scaleFactor;
y *= m_scaleFactor;pos = QPointF(x,y);
QRgb pixel = m_image.pixel(x,y);
m_currentColor = QColor::fromRgb(pixel);
emit colorSelected(m_currentColor.name(),x,y);
switch (m_action)
{
case ePixel:
proccessImage(m_currentColor,false);
break;
case eErase:
eraseImage(pos, QPointF(pos.x()+50,pos.y()+50));
break;
case eNoact:
break;
}
}
//-----------------------------------------------------------------------------
void ImageWidget::keyPressEvent( QKeyEvent * event )
{
switch(event->key())
{
case Qt::Key_Z:
{
if(event->modifiers() == Qt::ControlModifier)
revertChanges();
}
break;
default:
QWidget::keyPressEvent(event);
}
}
//-----------------------------------------------------------------------------
void ImageWidget::proccessImage(QColor color, bool inverse)
{
// Search algorithmQImage image = m_image;
for(int y = 0; y < image.height(); y++)
{
for(int x = 0; x < image.width(); x++)
{
QRgb currentPixel = image.pixel(x,y);if( qAbs(qRed(currentPixel) - color.red()) > m_difference &&
qAbs(qGreen(currentPixel) - color.green()) > m_difference &&
qAbs(qBlue(currentPixel) - color.blue()) > m_difference)
{
if(!inverse)
image.setPixel(x,y,qRgb(255,255,255));
}
else
{
if(inverse)
image.setPixel(x,y,qRgb(255,255,255));
}
}
}
m_imageLabel->setPixmap(QPixmap::fromImage(image));// QMessageBox::information(this, tr("Done"),
// tr("Processing image done.n"
// "The document has been modified."),
// QMessageBox::Ok);
}
//-----------------------------------------------------------------------------
void ImageWidget::eraseImage( const QPointF & startPoint,const QPointF & endPoint )
{
QImage image = m_image;for(int y = 0; y < image.height(); y++)
for(int x = 0; x < image.width(); x++)
if(y > startPoint.y() && y < endPoint.y())
if(x > startPoint.x() && x<endPoint.x())
image.setPixel(x,y,qRgb(255,255,255));m_imageLabel->setPixmap(QPixmap::fromImage(image));
m_image = image;
}
//-----------------------------------------------------------------------------
void ImageWidget::revertChanges()
{
QImage image = m_imageLabel->pixmap()->toImage();m_imageLabel->setPixmap(QPixmap::fromImage(m_image));
m_image = image;
}
//-----------------------------------------------------------------------------
void ImageWidget::onChangeDifference(int difference)
{
m_difference = difference;
//proccessImage(m_currentColor,false);
}
//-----------------------------------------------------------------------------
void ImageWidget::setCurrentAction( curAction action )
{
m_action = action;
}
//-----------------------------------------------------------------------------
@ - ((factor - 1) * scrollBar->pageStep()/2)));
-
wrote on 5 Jun 2011, 16:23 last edited by
I done this:
make m_scalefactor double;
When zoom in 0,8;
when zoom out 1,25;if(h>size().height() || w>size().width())
{
m_scaleFactor = 1.0;
}But I still have wrong coords in mouse press event x and y if I already make zomming, without zumming it's work correct. Please check somebody my code and make some corrections or recommendations.
-
wrote on 18 Oct 2011, 16:37 last edited by
Hello, i'am Novice in Qt program. I'am interested for you program (extention of imageViewer).
Can you post it if you have the solution. Thank you. -
wrote on 20 Apr 2012, 05:53 last edited by
I post header and source file of my Image widget class before. So you can see it, mahdhaoui. You just need to make an empty qt solution and use my class :)