PDA

View Full Version : Image display using QT



ankireddy
3rd January 2012, 09:21
Hello Exports,

I am new to QT programming. I want to develop a small image processing application using QT.

My application displayes animage on screen and need to do some modifications on image pixels. So I need to do some painting (king of masking) on the image (Selecting a region on image with mouse like lines, rectangles ect., ). For example, if I draw a rectangle on the image then I want to modifiy the pixels of the image in that rectangle.

I gone through some of the QT meterial and examples. But I am not able to find the starting point where to start. That is whether should I use GrapicsView or only with QMainWindow.

I saw an example which is using ui::View to display image. But i did not get any help in Qt meterial about Ui.

Can I use GraphicsView in my applications for drawing and to display images. Or should I use some other?

I am planning to use ImageMagick because it will support > 100 image formates.

Can you please guide me how to start Qt project which satisfies the above needs.

Thanks in Advance
Wizards.

wysota
3rd January 2012, 10:27
You can use Graphics View but you don't have to. If you are operating pixel by pixel, it is probably better not to use it. If, instead, you wanted to apply a kind of "filters" on the image (like Photoshop (or GIMP with layers) does), it is likely that using Graphics View would be a better idea to have a object-by-object semantics.

ankireddy
5th January 2012, 10:29
Hello wysota,

Thank you very much for the help.

Now I made a small example to show what I want to do. To do this I followed "Diagram Scene Example" of QGraphicsView.

I overwrite the "QGraphicsScene" class as "gView" to do my image processing related tasks and drawing related tasks. I will do all image processing tasks in this class and I will use "MainWindow" to transfer signals. (like Setting line color, text size ect in "Diagram Scene Example").

I loaded image into the graphics view in "MainWindow" constructor (scene->openSceneImage("").

After I displayed image on the screen then my work will start. I will select an area of the image with the mouse (say the face on the logo). Now I want to change the color of these selected pixels of the image and then I should display the image on the screen with the changed pixels.

In this attached example in "gView" class, in button pressed event I took the start and last points in mouse pressed and released events. Now I should draw a rectangle on the image from start point to last point (with the mouse dragging) and I should change all the pixels to green. I did this on "mouseReleaseEvent" in "gView" class and displayed the image on screen with changed (green) pixels.

(I took start and last points as static because I am unable to map co-ordinates from Scene to GrapicsView).

My application need to do lot of mouse clicks on the screen (image). Can i add image (like pix=QPixmap::fromImage(image);addPixmap( pix );) to Scene every time when I click mouse like as I did in mouse release event. If this is wrong how can I display image every time with the effected pixels.

I choose QGraphicsView because some times I need to show the drowned shapes (like lines, rectangles, circles etc.,) over the image (To show the user, the area which he selected).

I tried with "QPainter" class but it is not working everywhere except in "paintEvent" (I want to run my application in all platforms ). I think it is a bit difficult to show shapes with image on the screen for every .

(My task is like quick masking tool in Photoshop).

Can you please help me whether my approach is right or wrong for my task.

Thanks in Advance
ankireddy


code:-

MainWindow.h



#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

#include<QHBoxLayout>

#include "gscene.h"
namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();

signals:
void openImage(QString path);

private slots:
void on_actionOpen_triggered();

private:
Ui::MainWindow *ui;

gScene *scene;
QGraphicsView *view;

};

#endif // MAINWINDOW_H


MainWindow.CPP



MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);

scene = new gScene(this);
scene->setSceneRect(QRectF(0, 0, 900, 900));
QHBoxLayout *layout = new QHBoxLayout;
view = new QGraphicsView(scene);
layout->addWidget(view);

scene->setgView(view);
QWidget *widget = new QWidget;
widget->setLayout(layout);

connect(this,SIGNAL(openImage(QString)),scene,SLOT (openSceneImage(QString)));

//connect(scene, SIGNAL(itemInserted(DiagramItem*)),this, SLOT(itemInserted(DiagramItem*)));
setCentralWidget(widget);
setWindowTitle(tr("gViewTest"));
setUnifiedTitleAndToolBarOnMac(true);


scene->openSceneImage("");

}

MainWindow::~MainWindow()
{
delete ui;
}


gView.h


#ifndef GSCENE_H
#define GSCENE_H

#include <QGraphicsScene>
#include<QMessageBox>
#include<QGraphicsView>
#include<QGraphicsLineItem>
#include<QPixmap>
#include<QImage>
//#include <Magick++.h>
#include<QPointF>
#include<QGraphicsSceneMouseEvent>


//using namespace Magick;

class gScene : public QGraphicsScene
{
public:
//gScene();
gScene( QObject *parent);
void setgView(QGraphicsView *view)
{
gView=view;
}
public slots:
void openSceneImage(QString path);
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent);
// void mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent);
void mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent);

private:
QGraphicsView *gView;
QByteArray imgData;
QPixmap pixmap;
//Image magickImage;
// Blob blob;

QImage image;
QPixmap pix;
QPointF first,last;

};

#endif // GSCENE_H


gView.cpp


#include "gscene.h"


gScene::gScene( QObject *parent = 0): QGraphicsScene(parent)
{

}
void gScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
{
//first=mouseEvent->pos();

first.setX(10);
first.setY(10);

}
void gScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent)
{

last.setX(100);
last.setY(100);

int x1=first.x();
int y1=first.y();
int x2=last.x();
int y2=last.y();


QRgb color=qRgb(0,255,0);

for(int y=y1;y<=y2;y++)
{
for(int x=x1;x<=x2;x++)
{
image.setPixel(x,y,color);
}
}

pix=QPixmap::fromImage(image);
addPixmap( pix );


}
void gScene::openSceneImage(QString path)
{



image.load("logo.png");
pix=QPixmap::fromImage(image);
addPixmap( pix );

/* magickImage.read("C:\\Test\\logo.png");
//magickImage.scale(Geometry(800, 600));
magickImage.magick("RGBA");

magickImage.write(&blob);

imgData = ((char*)(blob.data()));

// STEP 3 - Display
pixmap.loadFromData(imgData,"RGBA");
addPixmap( pixmap );*/

}


main.cpp


#include <QtGui/QApplication>
#include "mainwindow.h"

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();

return a.exec();
}

wysota
5th January 2012, 11:33
After I displayed image on the screen then my work will start. I will select an area of the image with the mouse (say the face on the logo). Now I want to change the color of these selected pixels of the image and then I should display the image on the screen with the changed pixels.
I don't think that's a good candidate for using Graphics View.


In this attached example in "gView" class, in button pressed event I took the start and last points in mouse pressed and released events. Now I should draw a rectangle on the image from start point to last point (with the mouse dragging) and I should change all the pixels to green. I did this on "mouseReleaseEvent" in "gView" class and displayed the image on screen with changed (green) pixels.
Actually you are placing one image over the other. If you keep it that way, sooner or later you will run out of memory.


I choose QGraphicsView because some times I need to show the drowned shapes (like lines, rectangles, circles etc.,) over the image (To show the user, the area which he selected).
Since you are probably showing just one area at a time, using Graphics View is likely an overkill here.


I tried with "QPainter" class but it is not working everywhere except in "paintEvent" (I want to run my application in all platforms ). I think it is a bit difficult to show shapes with image on the screen for every .
No, not really. It's quite easy, actually. If you use Graphics View, that's what is happening anyway, only that you are not manually writing code that does this.


Can you please help me whether my approach is right or wrong for my task.

I would say it is "wrong-ish". It will work but you could do much better.

ankireddy
5th January 2012, 11:51
Hello wysota,

Thank you very much for the quick help.

So can I do my task just with a view or on MainWindow directly with "QPainter".

Can you please suggest me the right way for my task.

That is at least the road map.

Thanks in advance
ankireddy.n

wysota
5th January 2012, 14:59
So can I do my task just with a view or on MainWindow directly with "QPainter".
Yes. Well... you'll need some kind of widget of course besized the main window for the central widget.


Can you please suggest me the right way for my task.

The base is to render your pixmap in the paint event. If you want to draw something over it then do it after rendering the pixmap. Store everything you need for rendering in member variables of the class and use it in the paint event. So basically you do your logic in your custom methods (probably slots) and call update() to trigger a paint event that will redraw everything.

ankireddy
7th January 2012, 09:05
Hello wysota,

Thanks a lot for the help.

With your help i made an example. I am drawing image in an Widget and mainwindow for slots.

Now I have a problem.

I am painting on the image. For this I implemented "mouseMoveEvent". Here I am changing the color of the image pixel at x, y location(getting from mouseMoveEvent) and calling update().

If the image size is small say 100X100 the things are OK. If the image size is more say 1828X778 then only a few points are setting color. All pixels along the mouse move path are not getting painted.

I observed this is because of calling "paintEvent" for every pixel. And paint event has the statement ( "QPixmap::fromImage(image) and painter.drawPixmap()") to display image.

This only for the cursor of size 1 pixel width. If the cursor size say 50 (50X50 rectangle in shape ) then it may not paint all pixels

I found two solutions for this problem

1) In paintEvent instead of calling "fromImage" method, just I am painting that x,y coordinate of the device with "painter.drawPoint()" method . But in this case as the pixmap has the old data and my drawing is not appear on the screen.

The code is as follows
mouseMoveEvent(QMouseEvent *event)
{
int x=mouseEvent->x();
int y=mouseEvent->y();
end.setX(x);
end.setY(y);
QRgb color=qRgb(255,0,0);
penColor=color;
image.setPixel(x,y,color);
getting=true;
updateImage=false;
update();
}

PaintEvent

QPainter paint(this);
if(readImage) //Do only after read image
{
if(updateImage)
{
pxmap=QPixmap::fromImage(image);
paint.drawPixmap(0,0,pxmap.width(),pxmap.height(), pxmap);
}
else
{
paint.setPen(penColor);
paint.drawPoint(end.x(),end.y());
paint.drawPixmap(0,0,pxmap.width(),pxmap.height(), pxmap);
}
}

2) After loading image, I scaled it to half of the image size and displaying the image for each and every pixel. In this case also if the image is zoom-in then again i am having the same problem

Another way is
A) pxmap=QPixmap::fromImage(image);
B) painter.drawPixmap(....);
D) QPainter painter(this);
E) then for every pixel update the pixel color only on device with out doing A and B steps. That is get QPainter painter(this) and painter.setPixel(x,y,color).

But I did not found any method like QPixmap::setPixel() which will update the device in such a way.

Can you please guide me how to solve this problem?

Thanks in advance
ankireddy.n

wysota
7th January 2012, 15:22
What is the purpose of this updateImage variable?

In general it should all be more or less like this:


void X::mousePressEvent(QMouseEvent *me) {
m_pt = me->pos();
}

void X::mouseReleaseEvent(QMouseEvent *me) {
addLineToPixmap(m_pt, me->pos());
m_pt = QPoint();
}

void X::mouseMoveEvent(QMouseEvent *me) {
addLineToPixmap(m_pt, me->pos());
m_pt = me->pos();
}

void X::addLineToPixmap(QPoint from, QPoint to) {
QPainter p(&m_pixmap);
p.drawLine(from, to);
update();
}

void X::paintEvent(...) {
QPainter p(this);
p.drawPixmap(m_pixmap);
}

private:
QPoint m_pt;
QPixmap m_pixmap;

ankireddy
9th January 2012, 10:01
Hello wysota,

Thank you very much for your great help.

I did it.

Thanks
ankireddy.n

chandana
24th July 2013, 11:08
hi
i am new to Qt i want to display the uploaded image in the form2 .
i have created 2forms , where one form i have included all the fields like line edit , text edit etc and i have uploaded the image. the problem i am facing is i am unable to display the data of form 1 to form 2, and please help in displaying the image which is uploaded in form 1 to form 2.

u can find the attachements.

where regform is my main form(form1)
and message is my 2nd form(form 2)

Can you please guide me how to start Qt project which satisfies the above needs.

thanku93589359936093619362