PDA

View Full Version : loading huge pixmaps in slideshow eats up memory despite deleting



thinkabit
15th April 2011, 21:30
hi, i'm pretty new to qt, so please be kind to my mistakes ;-)

my goal is to have a slideshow with crossfading and zoom options. (it's stereoscopic, 3D, so there are two images next to each other)
that means, there are 4 images involved at the same time at the max.
i load the images in their original size to be able to zoom in really far. the images have a resolution of approx. 3600 x 2700px (i.e. about 16mb uncompressed).

i'm displaying the images as QPixmaps inside a qGraphicsScene inside a qGraphicsView to provide the zooming feature (two, to be exact).
now each time an image loads (which is done inside threads to ensure smooth zooming an fading) memory jumps up in the taskmanager, but doesn't go down again, looks like a stair, the application slows down, ...

i'm adding each newly loaded image with addPixmap to the QGraphicsScene, and it always says it just holds two objects. i'm deleteing the QPixmap before loading a new one, i'm deleting the threads before starting new ones to load the next images, nothing seems to help.

the version i had before where i used a QPainter, setOpacity and drawPixmap to display the resized and fading images worked, but it was too slow for 25 fps @ 2 x 1980 x1200, so i came up with the new solution.

anybody any clues?

thank you in advance,

oliver

squidge
15th April 2011, 21:40
Can't really say much without seeing your code, but why delete everything for every picture? Why not use one of each object and just manipulate to suit? Eg. use one thread and send it a signal when you want to load another image, use one (or maybe 2, max) QPixmap, etc.

SixDegrees
15th April 2011, 22:01
On Linux, I'd recommend running the program through valgrind to determine whether there's really a memory leak or not.

It may be that there isn't. Some unices, for instance, will keep allocating memory under conditions like this until the per-process limit is reached, and only then will they release some. They make no attempt to reuse freed blocks. Not sure what Windows does, but it's probably something similar.

DanH
16th April 2011, 01:36
Use QImageReader (http://doc.qt.nokia.com/4.7/qimagereader.html).

thinkabit
16th April 2011, 10:19
i've tried to break down the problem to the following lines, memory consumption still continuously rises, although QGraphicsScene just holds one item at a time ...

widget.cpp

#include "widget.h"

Widget::Widget(QWidget *parent)
: QWidget(parent)
{
fn[0]="DSCF0330_l.jpg";
fn[1]="DSCF0331_l.jpg";
fn[2]="DSCF0332_l.jpg";
fn[3]="DSCF0333_l.jpg";
fn[4]="DSCF0334_l.jpg";
fn[5]="DSCF0335_l.jpg";
fn[6]="DSCF0336_l.jpg";
fn[7]="DSCF0337_l.jpg";
fn[8]="DSCF0338_l.jpg";
fn[9]="DSCF0339_l.jpg";
fn[10]="DSCF0340_l.jpg";
fn[11]="DSCF0341_l.jpg";

grview = new QGraphicsView();
scene = new QGraphicsScene();
scene->setSceneRect(0, 0, 800, 600);
grview->setScene(scene);
grview->setViewport(this);
grview->show();

pmi=scene->addPixmap(QPixmap(fn[imgCtr++]));

timer0 = new QTimer(this);
connect(timer0, SIGNAL(timeout()), this, SLOT(next()));
timer0->start(7000);

imgCtr=0;
}

Widget::~Widget()
{

}

void Widget::next()
{
scene->removeItem(pmi);
pmi=scene->addPixmap(QPixmap(fn[imgCtr++]));
qDebug() << scene->items();
}

widget.h:

#ifndef WIDGET_H
#define WIDGET_H

#include <QtGui>

class Widget : public QWidget
{
Q_OBJECT

public:
Widget(QWidget *parent = 0);
~Widget();


private:
int imgCtr;
const char* fn[20];
QTimer *timer0;

QGraphicsView *grview;
QGraphicsScene *scene;
QGraphicsPixmapItem *pmi;

private slots:
void next();

};

#endif // WIDGET_H


so the problem seems to be QGraphicsScene. Is there a cache somewhere (except QPixchache, which is limited to 10240kb, and i've also tried emtying that without success)

if anybody has another solution for very fast (! >=25fps) dynamically zooming into and crossfading big images, you're most welcome ;-)

thank you,

oliver

ps.: thanks for the hints so far:
- i'm still searching for an equivalent to valgrind, that gives reasonable info, dr. memory didn't help much (to me).
- qimagereader? what did you think of there? only loading a part of an image? but it's about dynamically zooming, so i can't (re)load the images 25 times/second ...

Added after 11 minutes:

ok, just found the solution myself:

after

scene->removeItem(pmi);

there has to be a

delete pmi;

that does the trick! now memory just rises once for the first image and stays pretty much the same thereafter.
(so no need for all the other deletes i've tried ... just tried the wrong ones obviously)

there are still more problems with this application, but i think i'd better open new threads for those, as they are not directly connected to the problem described here.

thank you,

oliver