Seite 1 von 2
[gelöst] QPixmap in SQLite & imageformats/qjpeg Probleme
Verfasst: 3. Januar 2008 02:12
von René
Hallo,
wie kann man ein QPixmap am besten in einer SQLite Datenbank speichern und wieder laden? Meine bisherigen Versuche scheiterten kläglich.
Zum besseren Verständnis des Quelltextes:
'image' ist ein QPixmap-Objekt
'record' ist ein QSqlRecord-Objekt, welches in die Datenbank geschrieben wird
Die Spalte mit Namen "image" in der Datenbank ist als Typ 'blob' definiert.
Mit allen anderen Spalten, die Text oder Zahlen speichern, funktioniert alles bestens.
Code: Alles auswählen
Speichern:
//QPixmap in QByteArray umwandeln
QByteArray pixmapBytes;
QBuffer pixmapBuffer(&pixmapBytes);
pixmapBuffer.open(QIODevice::WriteOnly);
image.save(&pixmapBuffer);
//QByteArray in Datenbank schreiben
record.setValue("image", pixmapBytes.data());
Laden:
//QByteArray auslesen
const QByteArray pixmapBytes = QByteArray((char *)(record.value("image").data()));
//QPixmap konstruieren
image.loadFromData(pixmapBytes);
Vielen Dank für Eure Hilfe im voraus!
Verfasst: 3. Januar 2008 09:18
von patrik08
Versuche mal mit toBase64..
ich speichere zip so ab in mysql und kann auch sehen ob irgend eine limit ist... unter 2.4 MB geht alles prima....
Code: Alles auswählen
//////Speichern:
QByteArray pixmapBytes;
QBuffer pixmapBuffer(&pixmapBytes);
pixmapBuffer.open(QIODevice::WriteOnly);
image.save(&pixmapBuffer);
const QString blobimage = pixmapBytes.toBase64()+"|end_stream|";
/* ab in die db */
///////// Lesen
QString inside;
QByteArray xcode;
QPixmap pics;
/* sql abfrage ....*/
while (query.next()) {
inside = query.value(0).toString();
}
if (!inside.contains("|end_stream|")) {
/* error mysql limit */
return;
}
QStringList dat = inside.split("|");
if (dat.size() > 0) {
/* ok complete ... */
xcode.append(dat.at(0));
pics.loadFromData(QByteArray::fromBase64(xcode));
}
Verfasst: 3. Januar 2008 12:33
von René
Vielen Dank patrik08,
ich hatte zuerst auch damit keinen Erfolg.
inside.contains("|end_stream|") lieferte zwar
true zurück, aber
pics.loadFromData(QByteArray::fromBase64(xcode)) leider nur
false
Ich habe mir daraufhin den String näher angeschaut und musste entsetzt fesstellen, dass er außer
"|end_stream|" nichts weiter enthielt, also keine Daten meines ursprünglichen Bildes.
Daraufhin habe ich mir das Speichern nochmal angeschaut. Dort konnte ich dann fesstellen, dass
pixmapBuffer.open(QIODevice::WriteOnly) zwar
true, aber
image.save(&pixmapBuffer) leider immer
false ergab. D.h., ich hatte die ganze Zeit über nie ein Bild in meiner Datenbank.
Also habe ich mir nochmal die Dokumentation zu QPixmap::save angesehen:
Code: Alles auswählen
bool QPixmap::save ( const QString & fileName, const char * format = 0, int quality = -1 ) const
bool QPixmap::save ( QIODevice * device, const char * format = 0, int quality = -1 ) const
In beiden Varianten muss man das Format also nicht zwingend angeben. Verwendet man nun die erste Variante ohne Angabe des Formats, dann nimmt er als default-Format die Dateiendung des fileName. Verwendet man jedoch die zweite Variante ohne Angabe des Formats, dann weiß ich nicht, was er macht, offensichtlich liefert save aber
false zurück. Erst wenn ich ihm doch zwingend das Format vorgebe mit beispielsweise
image.save(&pixmapBuffer, "PNG") funktioniert es. Dann kann ich auch das Bild wieder korrekt aus der Datenbank auslesen nach deiner Methode, patrik08.
Es muss also jedes Bild, ob .jpg, .bmp oder .png erst in ein definiertes Format konvertiert werden, damit man es in den Buffer schreiben kann.
Verfasst: 7. Januar 2008 20:54
von René
Hallo,
ich habe den Status [gelöst] wieder zurück genommen, da es doch Probleme gibt. Leider funktioniert der Lösungvorschlag von patrik08 nur auf dem Rechner, auf dem ich das Projekt entwickle.

ch nutze Visual C++ 2008 Express Edition mit Qt 4.3.3 unter WindowsXP 32bit). Wenn ich versuche, die resultierende .exe Datei meines Projekts mit allen nötigen dll's auf einem beliebigen anderen WinXP Rechner zu starten, dann funktioniert eigentlich alles an meinem Programm, nur eben die Bilder werden nicht angezeigt.
Das Auslesen aus der Datenbank scheitert aus irgendwelchen Gründen.
image.loadFromData(...) liefert false, ein anschließendes image.isNull() entsprechend true.
Wie gesagt, auf dem Rechner, auf dem ich mit Visual C++ das Projekt entwickle, funktioniert es bestens. Hat da jemand eine Idee?
Verfasst: 7. Januar 2008 21:12
von Christian81
Forum Suche !
Imageformat-Plugins, ausserdem Qt Doku
http://doc.trolltech.com/4.3/plugins-howto.html
Verfasst: 7. Januar 2008 23:07
von René
Ok, erstmal danke für den Hinweis, Christian81.
Ich habe diverse Threads gelesen, auch die, in denen du dich beschwerst, dass die Leute nicht lesen würden ...
Also ich habe die Anleitungen bei Trolltech gelesen. Trotzdem funktioniert es nicht.
Ich habe Qt 4.3.3 mit debug und release, nicht static gebaut. Ich habe eine qjpeg4.dll und eine qjpegd4.dll im Verzeichnis plugins/imageformats im Qt-Installationsverzeichnis.
Für mein Projekt habe ich in meine .pro Datei QTPLUGIN += jpeg eingetragen. Mein Visual C++ Projekt enthält unter den Projekteigenschaften unter Linker->Input->Additional Dependencies unter anderem den Eintrag
C:\Programme\Qt\4.3.3\plugins\imageformats\qjpeg4.lib
für Release bzw.
C:\Programme\Qt\4.3.3\plugins\imageformats\qjpegd4.lib
für Debug.
Das Projekt kompiliert einwandfrei durch. Auf einem anderen Rechner werden die Bilder aber dennoch nicht angezeigt. Im selben Verzeichnis, aus dem ich die exe starte, habe ich ein Unterverzeichnis "imageformats" angelegt und die qjpeg4.dll hineinkopiert

ch teste auf dem anderen Rechner nur die Release-Version meines Projekts, daher habe ich nicht die qjpegd4.dll kopiert).
Was nun?
Ich hab nach etwas Suchen hier im Forum noch folgendes in meine main-Funktion geschrieben:
1. Versuch: Den Applikationspfad zu den LibraryPaths hinzufügen:
app.addLibraryPath(app.applicationDirPath());
Das hat nichts gebracht. Bilder werden immer noch nicht dargestellt.
2. Versuch: Den Applikationspfad ausschließlich zulassen:
QStringList paths;
paths.append(app.applicationDirPath());
app.setLibraryPaths(paths);
Auch das hat nichts gebracht. Bilder werden immer noch nicht dargestellt.
Jetzt weiß ich nicht mehr weiter und jetzt hilft mir auch die Doku nicht mehr weiter oder habe ich etwas übersehen?
Verfasst: 8. Januar 2008 07:07
von Christian81
QTPLUGIN nützt Dir nichts wenn man nicht statisch kompiliert.
Und auch der Rest wird irgendwie immer durcheinander gehauen. Image-Plugins gehören nach imageformats/ - so wie es in der Doku steht.
Wenn das nicht funktioniert gibt es ein paar Möglichkeiten.
1. Plugin und Qt-Dlls (diese müssen im gleichen Verzeichnis wie die exe liegen) passen nicht zueinander weil entweder die Version nicht passt oder das eine im Release- und das andere im Debug-Modus gebaut wurden.
2. Wenn man CMake benutzte ging es bis vor kurzem auch noch nicht korrekt
3. Einige Plugins brauchen noch externe Libs - wenn die nicht da sind können die Plugins nicht geladen werden -> Dependecy Walker benutzen
Ausserdem kann man in der Registry unter HKCU\Software\Trolltech\OrganizationDefaults schauen ob das Plugin überhaupt erkannt wurde und ob es aktiviert wurde (je nachdem wo es dort zu finden ist). Was dort noch sehr hilfreich ist sind die Buildkeys bei nichtladbaren Plugins - z.B.:
Code: Alles auswählen
qt3supportwidgets.dll REG_MULTI_SZ 40300 0 Windows msvc2005 release
qt3supportwidgetsd.dll REG_MULTI_SZ 40300 0 Windows msvc2005 debug
Alles andere mit irgendwelchen Application-Pfaden und sonstige Versuche sind sinnlos.
Verfasst: 8. Januar 2008 13:57
von René
Hallo Christian81,
Das QTPLUGIN += qjpeg in meiner .pro-Datei überflüssig ist, dachte ich mir schon, da ich nicht statisch kompiliere.
Wenn ich die Doku richtig verstanden habe, dann reicht es für mich völlig aus, im Verzeichnis, in dem die exe liegt, ein Verzeichnis namens imageformats anzulegen und dort die qjpeg4.dll hinzukopieren (Alles CaseSensitive).
Leider sehe ich dennoch keine JPEG Bilder in meinem Programm.
Du gibst 3 Möglichkeiten an, warum es dennoch nicht funktionieren könnte:
zu 2.: cmake nutze ich nicht.
zu 3.: qjepg4.dll sollte reichen, habe bereits von Leuten hier im Forum gelesen, dass es dann bereits funktionierte. Also gehe ich mal nicht davon aus, dass qjpeg4.dll weitere libs benötigt (Überprüfen kann ich es erst heute abend, wenn ich wieder zu Hause bin)
zu 1.: Hier vermute ich das Problem. Ich gehe mal davon aus, prinzipiell die richtige Version des Plugins zu nutzen, immerhin habe ich eine qjpeg4.dll und eine qjpegd4.dll, also wohl eine debug und eine release Version. Aber ich könnte mir vorstellen, dass die buildkeys nicht mit meiner exe übereinstimmen.
Ich nutze Visual C++ 2008. Um Qt damit zu kompilieren, musste ich als Platform explizit msvc2005 angeben, da msvc2008 noch nicht unterstützt wird. Siehe dazu auch meinen Post hier:
http://www.qt-forum.de/forum/viewtopic.php?t=5779
D.h. die Qt-Plugins müssten im buildKey "msvc2005" enthalten. Nach qmake -project und qmake -tp vc wird mir auch eine msvc2005 Projektdatei generiet, durch mein Visual C++ 2008 aber mein Projekt sofort in ein msvc2008 Projekt konvertiert. Ich vermute mal, dass dann meine resultierende exe "msvc2008" in den buildkeys enthalten wird.
Kann das die Ursache sein?
Das würde bedeuten, dass solange Qt nicht offiziell Visual C++ 2008 unterstützt und man die Qt-Plugins verwenden möchte (und dynamisch linken möchte) muss man Visual C++ 2005 verwenden.
Verfasst: 8. Januar 2008 14:23
von Christian81
Der Build-Key kommt vom mkspec, also alles ok. Ausserdem ist es egal - solange der in QtCore und QJpeg gleich sind.
Lieferst Du auch die QtCore/QtGui/... mit aus - die sind auch nötig!
Verfasst: 8. Januar 2008 16:29
von René
Hmm, jetzt bin ich etwas verwirrt.
Ich konnte gerade mein Programm auf einem weiteren WinXP-Rechner testen, da funktioniert es auf Anhieb.
Jetzt habe ich nochmal überlegt, was mit dem anderen Nicht-Entwicklungsrechner, auf dem es nicht funktioniert, nicht stimmen könnte. Da ist mir eingefallen, dass ich da mal vor ca. einem halben Jahr Qt 4.3.0 kompiliert hatte. Ich habe aber inzwischen aus meinen Umgebungsvariablen QTDIR wieder herausgenommen, und auch aus meiner PATH Variable %QTDIR%\bin entfernt. Kann es trotzdem damit zusammenhängen? Du hast geschrieben, dass es auch entsprechende Registry Einträge gibt. Zu welchem Zeitpunkt werden die eigentlich generiert? Es gibt ja keinen klassischen Installer für Qt, der auch die Registry Einträge vornimmt. Und wenn das die Ursache sein kann, wie werde ich die wieder los? Manuell entfernen, oder gibts da auch ein Tool oder ein Kommando für?
Gruß
René
Verfasst: 8. Januar 2008 16:47
von Christian81
Die Registry-Einträge werden erzeugt sobald die Plugins geladen werden (oder sie modifiziert werden) - also on demand.
Wenn Du noch eine alte Qt-Installation drauf hast, hast Du ggf. noch alte QtCore/QtGui/... libs in Windows/System32 ?
Verfasst: 8. Januar 2008 21:05
von René
Ich habe die Registry-Einträge alle manuell gelöscht.
In Windows/System32 habe ich keine QtCore/QtGui/... libs und hatte auch nie welche.
Dennoch klappt die Anzeige der Bilder auf diesem einen Rechner nicht. Nachdem ich mein Programm gestartet habe und mich davon überzeugen konnte, dass es nicht klappt, habe ich mir nochmal die Registry angesehen. Du hast ja geschrieben, dass die Einträge on demand beim erstmaligen Zugriff auf das Plugin generiert werden.
Ich wollte mal sehen, ob er überhaupt auf das Plugin zugreift. Tatsächlich hat er das Plugin auch im imageformats Verzeichnis gefunden, denn in der Registry taucht nach meiner Löschaktion die qjpeg4.dll wieder auf, allerdings mit dem Wert:
0 1 unkown 2007-12-14T21:02:56
So, und um nun die Verwirrung komplett zu machen. Ich habe mein Programm mit allen dll's und imageformats/qjpeg4.dll auf einem USB-Stick. Auf dem weiteren Rechner, den ich im letzten Post erwähnt habe, auf dem es nun funktioniert, habe ich auch den USB-Stick, also dieselben Dateien verwendet.
Es gibt eigentlich nur eine Erklärung. Auf dem Rechner 1, auf dem es nicht klappt und unkown im RegKey steht, ist kein Visual C++ 2008 installiert. Auf dem Rechner 2, auf dem es dann doch klappt, ist Visual C++ 2008 installiert (aber kein Qt). Leider kann ich jetzt wieder nicht nachsehen, was in dem RegKey auf Rechner 2 steht, denn Rechner 2 ist der auf der Arbeit, und im Moment bin ich zu Hause.
Es sieht also so aus:
Entwicklungs-PC: Qt 4.3.3 und Visual C++ 2008 installiert. qjpeg Plugin funktioniert
PC 2: kein Qt und aber Visual C++ 2008 installiert, qjpeg Plugin funktioniert
PC 1: kein Qt und kein Visual C++ 2008 vorhanden, qjpeg Plugin funktioniert nicht mehr
alles mit derselben Version vom USB-Stick getestet, kompiliert mit Qt4.3.3 unter Visual C++ 2008
Verfasst: 8. Januar 2008 21:10
von Christian81
Dann ist es ein manifest-Problem -> vcredist_x86.exe für msvc2008. Obs das allerdings schon gibt, weiss ich nicht.
Verfasst: 8. Januar 2008 21:38
von René
Ok, dann habe ich aber noch folgende Frage:
Habe ich mit Visual C++ 2005 wirklich weniger Probleme?
Ich habe das jetzt so vertanden, dass ohne die Installation von wenigstens vcredist_x86 auf dem Zielrechner die Qt Plugins nicht vernünftig laufen, Bei mir fehlt jetzt nun offensichtlich die Verison für 2008. Was ist, wenn ich Visual C++ 2005 verwendet hätte, dann würde eben diese fehlen.
Ok, für 2005 gibt es zwar die vcredist, aber eigentlich fand ich es immer recht angenehm, nicht mal die Installation dieser voraussetzen zu müssen, indem ich zu den Qt-dll's auch gleich noch die C-Runtime und C++-Runtime msvcr80.dll und msvcp80.dll und die Manifest Datei Microsoft.VC80.CRT.manifest aus dem Visual C++ 2005 Installations-Verzeichnis
C:\Programme\Microsoft Visual Studio 8.0\VC\redist\x86\Microsoft.VC80.CRT\
beigelegt habe. Genauso habe ich es auch jetzt aktuell mit den VC90 Versionen von Visual C++ 2008 gemacht. Aber für die Qt-Plugins reicht das offenbar nicht. Hier muss also zwingend wenigstens die Installation des vcredist Pakets vorausgesetzt werden. Egal ob nun für Visual C++ 2005 oder 2008.
Ist das korrekt?
Das finde ich schade, das ist echt ein Grund, sich doch den Einsatz von PNG statt JPG zu überlegen. Damit wäre ich auf kein Qt Plugin angewiesen, und mein Programm würde damit definitiv überall laufen mit dem, was ich mitliefere.
Verfasst: 8. Januar 2008 22:07
von Christian81
Dann muss sie auch beim Plugin beigelegt werden. Der Hack mit dem Manifest kopieren ist ... naja hack eben.