Seite 1 von 1
QPixmap - width / height == 0 ?
Verfasst: 15. Juli 2009 14:11
von nebler
Guten Tag,
ich programmiere mit Qt 4.2.
Ich hab eine Scene darauf sind verschiedene Pixmaps (aus performance Gründen Pixmaps und nicht direkt mit Scene Funktionen implementeiert).
Jedes Pixmap besteht aus sehr vielen Rechtecken.
Läuft meine Schleife mit folgedem Aufruf durch:
pixWidth = pixHeight = 12321. (lt Debugger)
Dann springt er in folgende If rein:
Code: Alles auswählen
if( pixmap.width() == 0 || pixmap.height() == 0 )
{
break;
}
Warum? Mach ich was falsch? Überseh ich was?
Und:
Was ist die Maximalgröße eines QPixmaps?
Gibt es eine Möglichkeit das zu vergrößern mit minimalen Aufwand?
(Hab die Zeit nicht um ein Pixmap in 4 kleinere Pixmaps aufzuteilen.)
Vielen vielen Dank.
Mit freundlichen Grüßen
Jakob
Verfasst: 15. Juli 2009 14:53
von Christian81
~576MB am Stück Speicher zu allozieren wird wohl nicht immer funktionieren würde ich sagen.
Verfasst: 15. Juli 2009 15:10
von nebler
Okay, vielen Dank.
Wie lässt sich das bei QPixmap berechnen?
Gibt es eine Möglichkeit die maximal Größe zu ermitteln?
Verfasst: 15. Juli 2009 15:48
von Christian81
Ein Pixmap ist einfach ein Bild im RGBA - Format - also 4 Bytes/Pixel.
Die maximale Größe ist abhängig von deinem Speicher und Architektur - das lässt sich nicht berechnen.
Verfasst: 15. Juli 2009 16:46
von NothingSpecial
Ermitteln ginge aber schon...
Experimentell in einer for- Schleife, die immer größere Bilder anlegt und zerstört, bis die maximale Grenze erreicht ist. Allerdings weiß man dann wahrscheinlich nie so genau, wie sich das Programm auf anderen Rechnern verhält
Grüße,
NothingSpecial
Verfasst: 15. Juli 2009 16:54
von Christian81
Man was es überhaupt nicht - woher willst Du wissen wieviel Speicher usw. der andere Rechner hat?
Verfasst: 15. Juli 2009 20:53
von nebler
Das kann man natürlich nicht wissen. Aber ich muss ja eine Empfehlung abgeben können, bzw. mit welchen Rahmenbedingungen die Software optimal läuft bzw. die Anforderungen die ich habe erfüllt.
Gäbe es eine schnellere Alternative zu
QGraphicsView <-- QGraphicsScene <- QPixmap <- QPainter ?
Irgendwo hier im Forum gelesen: this->setViewPort( new QGLWidget() ); (so ungefähr ...)
Naja das hat dazu geführt das meine Applikation total gehangen hat, als die Code Zeile dabei war.
Vielen Dank.
ps: Qt Version 4.2 - commercial
Verfasst: 15. Juli 2009 23:37
von NothingSpecial
Hi,
vielleicht liegt es nicht an der Größe, sondern an anderen Umständen, versuch es mal bitte mit einem kleineren Pixmap.
Ich habe mal nachgeschaut, was da so passiert, im QPixmap.cpp:
Code: Alles auswählen
QPixmap::QPixmap(int w, int h)
: QPaintDevice()
{
if (!qt_pixmap_thread_test())
init(0, 0,QPixmapData::PixmapType);
else
init(w, h, QPixmapData::PixmapType);
}
Code: Alles auswählen
static bool qt_pixmap_thread_test()
{
if (!qApp) {
qFatal("QPixmap: Must construct a QApplication before a QPaintDevice");
return false;
}
#ifndef Q_WS_WIN
if (qApp->thread() != QThread::currentThread()) {
qWarning("QPixmap: It is not safe to use pixmaps outside the GUI thread");
return false;
}
#endif
return true;
}
Hier ist es zwar interessant zu wissen welches BS zu verwendest, letztendlich deute ich die Fehlermeldungen/Warnungen (bekommst du welche?) so, dass dem Pixmap eine QApplication fehlt in der sie läuft. Wäre es der Speicher würde sowas kommen:
Code: Alles auswählen
QPixmap pixmap(1000000000, 100000000);
qDebug() << "pixmap height: " << pixmap.height() << " pixmap width: " << pixmap.width();
Debugger hat geschrieben:pixmap height: 100000000 pixmap width: 1000000000
X Error: BadAlloc (insufficient resources for operation) 11
Major opcode: 53 (X_CreatePixmap)
Resource id: 0x1a7
X Error: BadDrawable (invalid Pixmap or Window parameter) 9
Extension: 152 (RENDER)
Minor opcode: 4 (RenderCreatePicture)
Resource id: 0x5c00064
X Error: RenderBadPicture (invalid Picture parameter) 171
Extension: 152 (RENDER)
Minor opcode: 7 (RenderFreePicture)
Resource id: 0x5c00065
X Error: BadPixmap (invalid Pixmap parameter) 4
Major opcode: 54 (X_FreePixmap)
Resource id: 0x5c00064
Wenn man sich weiter reinließt, kommen noch andere Möglichkeiten zum Tragen, welche aber scheinbar immer eine Ausgabe produzieren. Eine weitere Möglichkeit ist es, dass das der PixelType nicht stimmt (scheinbar nur unter X11 und Mac und nicht unter Windows). In der qpixmap_x11.cpp und qpixmap_mac.cpp steht:
Code: Alles auswählen
..
bool make_null = w <= 0 || h <= 0; // create null pixmap
d = (pixelType() == BitmapType ? 1 : dd);
if (make_null || d == 0) {
w = 0;
h = 0;
hd = 0;
picture = 0;
d = 0;
if (!make_null)
qWarning("QPixmap: Invalid pixmap parameters");
return;
}
...
Hat aber auch eine Ausgabe und passiert wahrscheinlich bei dir nicht, dafür müsstest du den PixelType als int übergeben...
Was dann weiter hier passiert, weiß ich allerdings nicht:
qpixmap.cpp line 126. Vielleicht versteckt sich da auch noch ein Grund, auch wenn ich das nicht glaube. Auch weiter tiefer gibt es Stellen, wo ich einfach nicht mehr weiß, in welcher Datei die aufgerufenen Funktionen oder Klassen sind. Ich habe keine Stelle gefunden in der explizit Speicher alloziert wird.
Grüße,
NothingSpecial
Verfasst: 16. Juli 2009 08:43
von nebler
Wow, voll cool, vielen Dank für die Mühe.
Also folgende Beobachtung:
Ich stelle mit Hilfe vieler Pixmaps ein großes Bild dar.
Ich hab eine eigene Zoomfunktion, mit der ich halt die Pixmap größe bestimme sowie, wie groß die einzelnen Rechtecke darauf sein sollen.
Wird der Zoomfaktor zu groß, d.h. Pixmap größe wird zu "groß" und ich bekomm bei .width() und .height() die Ausgabe 0. Das habe ich festgestellt nachdem ich nur noch eine weiße Fläche gesehen habe. Wird der Zoomfaktor kleiner, also die berechnete Größe glaub ich unter 1200x1200 (unsicher bei dem Wert) dann bekomm ich mein Bild zu sehen. Andernfalls, ja eben nicht. Was mich halt wundert, es ist der gleiche Algorithmus, bei einem gewissen bereich meines Zoomfaktors funktioniert das wunderbar, andernfalls sieht man gar nichts. Daher fände ich es seltsam die Aussage "Er findet die QApplication nicht.". Im Output ist keine Qt Nachricht enthalten.

m Debug Mode bei MS VS 2003).
Ich verwende Windows XP.
Ist wohl etwas seltsam das ganze.
Code: Alles auswählen
QPixmap::QPixmap(int w, int h)
: QPaintDevice()
{
if (!qt_pixmap_thread_test())
init(0, 0, QPixmapData::PixmapType);
else
init(w, h, QPixmapData::PixmapType);
}
Wie kann man sicherstellen, das er immer in den "else" Zweig kommt?
Ich verwende diesen Konstruktor.
Verfasst: 16. Juli 2009 09:20
von franzf
Da du ja ein QApplication-Objekt hast und deine App ja nicht mit nem Fehler beendet, ist nur noch das hier möglich:
Code: Alles auswählen
#ifndef Q_WS_WIN
if (qApp->thread() != QThread::currentThread()) {
qWarning("QPixmap: It is not safe to use pixmaps outside the GUI thread");
return false;
}
#endif
Du verwendest ja Windows. Ich hab mir jetzt nicht die Mühe gemacht, den QPixmap-Source zu durchforsten nach weiteren Vorkommen von qt_pixmap_thread_test(). Das kannst du ja machen.
Unter der Annahme, dass diese nur beim Konstruieren (oder wahrscheinlich auch resizen) aufgerufen wird, ist doch klar, was zu tun ist. Keine QPixmap in einem anderen als dem MainThread erstellen

2 Alternativen:
1) So was in der Art zum Erstellen in einem anderen Thread als dem main-thread:
Code: Alles auswählen
moveToThread(qApp->thread());
QPixmap pix(w,h);
moveToThread(this);
2) Im main-Thread ein eigenes Objekt, welches nur die Pixmaps in eine Liste schiebt, oder sonst wie dem Thread zur Verfügung stellt. Anforderung/Mitteilung über Fertigstellung per Signal/Slot.
Gibt aber sicher auch andere Lösungsmöglichkeiten.
Verfasst: 16. Juli 2009 10:54
von NothingSpecial
Hmm vielleicht gibt Windows ja solche Meldungen nicht raus.. Meine kamen ja direkt vom X.. Da es aber mit kleineren Pixmaps geht liegt es schon am Speicher,
Der Algo (benutzt der scale()??) funktioniert dann so lange, bis er kein neues Pixmap mehr erstellen kann. Ich nehme an, dass es sich bei den 1200x1200 aus dem vorherigem Post um ein 12 000x 12 000px handelt und dass du nicht für einen so großen Monitor entwickelst. Wäre das der Fall musst du eben dafür sorgen, dass der interessante Ausschnitt in ein neues kleineres Pixmap copiert wird. Interessant wird es dann, wenn du wieder rauszoomen willst.
Grüße,
NothingsSpecial