PDA

View Full Version : Display continous images on the screen



tuent
22nd December 2010, 09:16
Hi, I have many images need to modify. I want to modify and display one by one (display each image after modifying it). Now I just can do this work for 1 image, how do I do it for many images? Here is the code that do the work to modify and display 1 image:


RF2Img::RF2Img()
{
imageLabel = new QLabel;
imageLabel->setBackgroundRole(QPalette::Base);
imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
imageLabel->setScaledContents(true);

createActions();
createMenus();

processRFImg("1.bmp"); // This will process 1.bmp
loadRFImg("1.bmp"); // This will display 1.bmp

setWindowTitle(tr("RF2IMG"));
resize(800, 800);
}




int main(int argc, char *argv[])
{
QApplication app(argc, argv);
RF2Img rf2img;
rf2img.show();
return app.exec();
}

So then, How do i do it for many images: 2.bmp, 3.bmp...? Thanks :)!

high_flyer
22nd December 2010, 09:21
Are you familiar with the 'for' loop concept?

tuent
22nd December 2010, 09:56
But when I try to use this code:


for(int i = 0; i < 10; i++) {
QString str;
str.append(QString("%1").arg(i+1));
str.append(".bmp");
processRFImg(str);
loadRFImg(str);
}

It just display the first imge, how do I show all the image one by one while modifying them?

Lykurg
22nd December 2010, 10:02
Have a look at http://doc.trolltech.com/qq/qq27-responsive-guis.html. That will solve your problem!

high_flyer
22nd December 2010, 10:12
It just display the last imge, how do I show all the image one by one while modifying them?
I though more along the lines of:


MyClass::processImage(const QString &strFileName)
{
imageLabel = new QLabel(this);
imageLabel->setBackgroundRole(QPalette::Base);
imageLabel->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
imageLabel->setScaledContents(true);

createActions();
createMenus();

processRFImg(strFileName); // This will process 1.bmp
loadRFImg(strFileName); // This will display 1.bmp

setWindowTitle(tr("RF2IMG"));
resize(800, 800);
}

...
//and then
QStringList slstFileNames; //needs to be filled with the file names of your images
for(int i = 0; i < slstFileNames.size(); i++) {
pMyClass->processImage(slstFileNames.at(i));
}


And note what Lykurg said as well.

NOTE:
these are suggestions, they are not fully working application.
YOU have to make this work, but that would be the general way to about it.

tuent
23rd December 2010, 03:07
Thanks for your comment lykurg and high_flyer but your article http://doc.trolltech.com/qq/qq27-responsive-guis.html is quite difficult for me. Could you show me some more detail advises for my problem.
I have a class RF2Img derived QMainWindow


class RF2Img : public QMainWindow
{
Q_OBJECT

public:
RF2Img();
public slots:
// Load RF image
void loadRFImg(QString fileName); // Attach the image to image label
void processImg(QString fileName); // Process image
private:
void createActions();

void updateActions();

QLabel *imageLabel;
};

in main.cpp I have


int main(int argc, char *argv[])
{
QApplication app(argc, argv);
RF2Img rf2img;
rf2img.show();
return app.exec();
}


The image will be displayed by imageLabel, because the processImage function is quite slow so the image must be displayed one by one, how do I use multithread or some other solutions to display the image one by one using my current function? Thanks for your advices :).

Lykurg
23rd December 2010, 06:39
Do the image scaling in a thread or even easier use QtConcurrent for that. There is also an example in the docs: QtConcurrent Image Scaling Example. Or simply call
QCoreApplication::processEvents();after setting the image to the label. But the last will still block your gui.

tuent
24th December 2010, 04:57
I solved my problems! Thanks for your help :)!

tuent
29th December 2010, 08:49
Hi all, I'm using the QtConcurrent example http://doc.trolltech.org/4.7-snapshot/qtconcurrent-imagescaling-imagescaling-cpp.html for my project. My process image algorithm will replace scale function.


#include "imagescaling.h"
#include "math.h"

#ifndef QT_NO_CONCURRENT

const int imageSize = 100;

QImage scale(const QString &imageFileName)
{
QImage image(imageFileName);
return image.scaled(QSize(imageSize, imageSize), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
}

Images::Images(QWidget *parent)
: QWidget(parent)
{
setWindowTitle(tr("Image loading and scaling example"));
resize(800, 600);

imageScaling = new QFutureWatcher<QImage>(this);
connect(imageScaling, SIGNAL(resultReadyAt(int)), SLOT(showImage(int)));
connect(imageScaling, SIGNAL(finished()), SLOT(finished()));

openButton = new QPushButton(tr("Open Images"));
connect(openButton, SIGNAL(clicked()), SLOT(open()));

cancelButton = new QPushButton(tr("Cancel"));
cancelButton->setEnabled(false);
connect(cancelButton, SIGNAL(clicked()), imageScaling, SLOT(cancel()));

pauseButton = new QPushButton(tr("Pause/Resume"));
pauseButton->setEnabled(false);
connect(pauseButton, SIGNAL(clicked()), imageScaling, SLOT(togglePaused()));

QHBoxLayout *buttonLayout = new QHBoxLayout();
buttonLayout->addWidget(openButton);
buttonLayout->addWidget(cancelButton);
buttonLayout->addWidget(pauseButton);
buttonLayout->addStretch();

imagesLayout = new QGridLayout();

mainLayout = new QVBoxLayout();
mainLayout->addLayout(buttonLayout);
mainLayout->addLayout(imagesLayout);
mainLayout->addStretch();
setLayout(mainLayout);
}

Images::~Images()
{
imageScaling->cancel();
imageScaling->waitForFinished();
}

void Images::open()
{
// Cancel and wait if we are already loading images.
if (imageScaling->isRunning()) {
imageScaling->cancel();
imageScaling->waitForFinished();
}

// Show a file open dialog at QDesktopServices::PicturesLocation.
QStringList files = QFileDialog::getOpenFileNames(this, tr("Select Images"),
QDesktopServices::storageLocation(QDesktopServices ::PicturesLocation),
"*.jpg *.png");

if (files.count() == 0)
return;

// Do a simple layout.
qDeleteAll(labels);
labels.clear();

int dim = sqrt(qreal(files.count())) + 1;
for (int i = 0; i < dim; ++i) {
for (int j = 0; j < dim; ++j) {
QLabel *imageLabel = new QLabel;
imageLabel->setFixedSize(imageSize,imageSize);
imagesLayout->addWidget(imageLabel,i,j);
labels.append(imageLabel);
}
}

// Use mapped to run the thread safe scale function on the files.
imageScaling->setFuture(QtConcurrent::mapped(files, scale));

openButton->setEnabled(false);
cancelButton->setEnabled(true);
pauseButton->setEnabled(true);
}

void Images::showImage(int num)
{
labels[num]->setPixmap(QPixmap::fromImage(imageScaling->resultAt(num)));
}

void Images::finished()
{
openButton->setEnabled(true);
cancelButton->setEnabled(false);
pauseButton->setEnabled(false);
}

#endif // QT_NO_CONCURRENT

But my images are too big (2MB/image) and when the program runs the memory loaded too much because it loads all the images to memory. How do I delete the image memory after display it.
I tried this way but it can't release the displayed image data:
I try delete the displayed image data in showImage(int):


void Images::showImage(int num)
{
labels[num-1].clear();
labels[num]->setPixmap(QPixmap::fromImage(imageScaling->resultAt(num)));
}

How do i optimize the memory in my program? Thanks for your help :)!

high_flyer
29th December 2010, 08:59
How do I delete the image memory after display it.
The question is when?
If you delete it just after diplaying it, it will just be there for a short moment and be gone.

You need to specify how your program is supposed to behave in regard to showing the images.

tuent
29th December 2010, 10:35
The question is when?
If you delete it just after diplaying it, it will just be there for a short moment and be gone.

You need to specify how your program is supposed to behave in regard to showing the images.
I want to delete the previous image when the current image is displayed. My program is just like the Qtconcurrent example. (The function Scale() take quite long time to run each image)

high_flyer
29th December 2010, 10:46
You have a problem with your design.
I don't understand why do you need concurrent execution here, if you are showing one image at a time?
That is why you have the problem - you allocate only one image per scan() but your scans run in parallel, resulting in multiple images allocated.
If for what ever reason you have to do things this way, one way would be to manage the thread pool, so that only one a certain maximum number of threads will be started, and, you might want to allocate on the heap and not on the stack, since stack size is very limited.
You will have much more freedom on the heap - but you will have to watch your limits there too, otherwise your system might suffocate, specially if its embedded.