PDA

Visualizza la versione completa : [Qt-C++] Consiglio su struttura funzione


fermat
24-09-2015, 10:32
ciao!
avrei bisogno di un consiglio su come strutturare meglio alcune parti di un programmino che sto facendo.
ho questa funzione (statica per ora):


void ImageResize::resize(QString inputImage, QString dir, int width, int height)
{
QFileInfo f(inputImage);
QPixmap pixmap(inputImage);
QPixmap newPixmap;
if (width == 0)
{
newPixmap = pixmap.scaledToHeight(height, Qt::SmoothTransformation);
}
else if (height == 0)
{
newPixmap = pixmap.scaledToWidth(width, Qt::SmoothTransformation);
}
else
{
newPixmap = pixmap.scaled(width, height, Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
QFile file(dir + f.fileName());
file.open(QIODevice::WriteOnly);
newPixmap.save(&file, 0, 100);
file.close();
}

quello che non mi piace molto è quell'if.
e il motivo è che questa funzione la lancio per ogni voce di una lista, in questo modo:


WorkerThread::WorkerThread(QVector<QString> list, int width, int height, QString startDir, QObject *parent, bool b) :
QThread(parent), stop(b)
{
this->list = list;
this->width = width;
this->height = height;
this->startDir = startDir;
}

void WorkerThread::run()
{
for (int i = 0; i < list.count(); i++)
{
QMutex mutex;
// PREVIENE CHE ALTRI THREAD IMPOSTINO LO STOP
mutex.lock();
if(this->stop) break;
mutex.unlock();
// EMETTE IL SEGNALE PER IMPOSTARE IL TESTO SULLA GUI
ImageResize::resize(list.value(i), startDir + QDir::separator(), width, height);
emit valueChanged(list.value(i));
this->msleep(500);
}
emit finished();
}

pensavo di:
-spezzare la funzione resize in tre funzioni distinte
-eseguire il controllo su width e height (che passo al costruttore di WorkerThread) prima del ciclo for.

probabilmente è una cosa stupida, ma non riesco a trovare un modo per impostare la funzione da richiamare prima del for.

non so se sono stato chiaro.....

Shores
24-09-2015, 12:41
Non vedo assolutamente la ragione di spezzarla in tre: non otterresti nessun reale vantaggio, anzi produrresti l'hoverhead di una ulteriore chiamata di funzione quando lo usi, facendo fare fatica inutile al processore...

fermat
24-09-2015, 12:49
Non vedo assolutamente la ragione di spezzarla in tre: non otterresti nessun reale vantaggio, anzi produrresti l'hoverhead di una ulteriore chiamata di funzione quando lo usi, facendo fare fatica inutile al processore...

credo di non aver capito.
se io levo quell'if, quindi una istruzione in più per ogni valore nella lista, e metto funzioni che non vengono chiamate, è peggio?
mi consigli di mantenere quella if?
anche perchè una volta avviato il processo, richiamo sempre le stesse impostazioni per ogni valore della lista.
non è che cambia da record a record.
quindi fare una if per ogni valore quando in realtà lo potrei fare solo una volta!
intendevo questo.

MItaly
24-09-2015, 14:45
Rispetto al costo di caricare/ridimensionare/salvare un'immagine sono tutte distinzioni completamente irrilevanti. Volendo puoi metterti da parte l'operazione da fare in una std::function, ma di nuovo, non c'è nessun guadagno a farlo.

Piuttosto, c'è un errore grosso sia dal punto di vista della correttezza che da quello delle prestazioni: stai usando una QPixmap. Questo è male perché:
- le QPixmap possono essere usate solo dal thread della GUI, mentre tu le stai usando da un worker thread;
- le QPixmap sono bitmap ottimizzate per il disegno rapido su schermo, non per la manipolazione; in pratica, possono essere implementate come un wrapper attorno alle bitmap della libreria grafica sottostante (su X11 fino a Qt4 erano dei reference a bitmap X11; sotto Qt5, il backend Direct2D le usa come puntatori a texture tenute in memoria video) in modo che siano velocissime da disegnare a schermo, ma accedere ai loro pixel può essere più complicato.

Per questi motivi, in generale per effettuare manipolazioni di immagini usa le QImage, non le QPixmap.

fermat
24-09-2015, 16:12
ciao MItaly!


Rispetto al costo di caricare/ridimensionare/salvare un'immagine sono tutte distinzioni completamente irrilevanti. Volendo puoi metterti da parte l'operazione da fare in una std::function, ma di nuovo, non c'è nessun guadagno a farlo.

Piuttosto, c'è un errore grosso sia dal punto di vista della correttezza che da quello delle prestazioni: stai usando una QPixmap. Questo è male perché:
- le QPixmap possono essere usate solo dal thread della GUI, mentre tu le stai usando da un worker thread;
- le QPixmap sono bitmap ottimizzate per il disegno rapido su schermo, non per la manipolazione; in pratica, possono essere implementate come un wrapper attorno alle bitmap della libreria grafica sottostante (su X11 fino a Qt4 erano dei reference a bitmap X11; sotto Qt5, il backend Direct2D le usa come puntatori a texture tenute in memoria video) in modo che siano velocissime da disegnare a schermo, ma accedere ai loro pixel può essere più complicato.

Per questi motivi, in generale per effettuare manipolazioni di immagini usa le QImage, non le QPixmap.

quindi, in sostanza, secondo te devo solo modificare QPixamp con QImage?


void ImageResize::resize(QString inputImage, QString dir, int width, int height)
{
QFileInfo f(inputImage);
QImage pixmap(inputImage);
QImage newPixmap;
if (width == 0)
{
newPixmap = pixmap.scaledToHeight(height, Qt::SmoothTransformation);
}
else if (height == 0)
{
newPixmap = pixmap.scaledToWidth(width, Qt::SmoothTransformation);
}
else
{
newPixmap = pixmap.scaled(width, height, Qt::KeepAspectRatio, Qt::SmoothTransformation);
}
QFile file(dir + f.fileName());
file.open(QIODevice::WriteOnly);
newPixmap.save(&file, 0, 100);
file.close();
}

Loading