BLOB String aus SQLite DB wieder als Image anzeigen

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
bigbonzo
User
Beiträge: 21
Registriert: Samstag 30. November 2019, 10:23

Hallo, ich habe in eine SQLite Datenbank erfolgreich binary in ein BLOB Attribut ein Thumbnail-Picture abgelegt. In einem DB Browser kann ich das Bild auch sehen. Jetzt möchte ich das Bild gerne in meiner App wieder anzeigen, bekomme aber immer Fehlermeldungen. Was ist zu tun, nachdem ich den "BLOB-String" wieder aus der Datenbank gelesen habe? Wie wird aus dem String wieder ein Image, das ich mit einem TKinter Label anzeigen kann ? Ich finde nicht den richtigen Weg/Befehl.
Danke.
Benutzeravatar
__blackjack__
User
Beiträge: 13919
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@bigbonzo: Was versuchst Du denn und was für Fehlermeldungen bekommst Du?
“Java is a DSL to transform big Xml documents into long exception stack traces.”
— Scott Bellware
bigbonzo
User
Beiträge: 21
Registriert: Samstag 30. November 2019, 10:23

Was versuche ich => Wie beschrieben, ein Bild, welches in einer SQLite Datenbank liegt (und dort auch als Binary sichtbar ist) wieder aus der Datenbank herauslesen, was auch zum Ergebnis einen sichtbaren String hat, der aber leider nicht als Image taugt. Muss ich den String jetzt mit einem "stringTObinary" Befehl wieder kodieren ?
Fehlermeldungen => Die Fehlermeldungen zeugen von meinen Irrwegen, daher wären die hier nicht hilfreich.
Also die schlichte Frage, wie kriege ich einen String, der ursprünglich mal als binary Image in der DB abgelegt war (BLOB), wieder angezeigt ??
Muss ich, um die Bildinformationen wieder als Image nutzen zu können noch konvertieren ?
Benutzeravatar
__blackjack__
User
Beiträge: 13919
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@bigbonzo: Du bekommst da bei einem Blob keine Zeichenkette sondern ein `bytes`-Objekt. Sind ja Binärdaten und keine Zeichenkette. Kann es sein dass die Frage überhaupt nichts mit der Datenbank zu tun hat sonder eigentlich eine GUI-Frage ist und Du das `data`-Argument von `tkinter.PhotoImage` suchst? Und eventuell noch das `format`-Argument.
“Java is a DSL to transform big Xml documents into long exception stack traces.”
— Scott Bellware
bigbonzo
User
Beiträge: 21
Registriert: Samstag 30. November 2019, 10:23

Ja, mit der Datenbank an sich hat das nichts zu tun, ich krieg die Daten ja wieder raus, ... aber dann.
Aus dem tkinterbook:
image = Image.open("lenna.jpg")
photo = ImageTk.PhotoImage(image)
Nur ich habe kein Bild, sondern einen String, wie kann ich daraus ein Image machen ??
Danke.
Benutzeravatar
__blackjack__
User
Beiträge: 13919
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@bigbonzo: Okay, jetzt ist also auch noch `PIL.Image` im Spiel. Du suchst also `io.BytesIO` um aus den Bytes (das ist keine Zeichenkette!) ein Dateiobjekt zu machen das Du `Image.open()` übergeben kannst.
“Java is a DSL to transform big Xml documents into long exception stack traces.”
— Scott Bellware
bigbonzo
User
Beiträge: 21
Registriert: Samstag 30. November 2019, 10:23

ok, danke blackjack. Habe mal gesucht. mit deinem Hinweis finde ich:
In-memory binary streams are also available as BytesIO objects:
f = io.BytesIO(b"some initial binary data: \x00\x01")
nur, wie wende ich das an? Die Parameter sind nicht beschrieben, das 'b' brauche ich glaube ich, aber was ist mit den \x ?
Wie muss ich den Programmcode anpassen ? hiermit bekomme ich einen Fehler "AttributeError: 'Image' object has no attribute 'open'"
data = selection[12] ## string aus der Datenbank
f = io.BytesIO(b'data')
photo=image.open(f)
bigbonzo
User
Beiträge: 21
Registriert: Samstag 30. November 2019, 10:23

Ergänzung, wenn ich mir den Wert in der Datenbank ansehen, dann beginnt der mit "b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\...."
Also ist da das 'b' schon drin !?!
Sirius3
User
Beiträge: 18216
Registriert: Sonntag 21. Oktober 2012, 17:20

Das b'xy' ist die Repräsentation eins byte-Strings. Du hast aber den byte-String schon in Weinberg Variable stehen. Und Varianten nutzt man bei BytesIO genauso wie überall sonst auch.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wenn das b’...’ “schon drin” ist, dann sind die Daten in der Datenbank kaputt. Wie sind die dadrin gelandet?
Benutzeravatar
__blackjack__
User
Beiträge: 13919
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Ich vermute mal damit ist gemeint dass das b'…' angezeigt wird wenn man das Objekt per `print()` ausgibt. In einem vorherigen Beitrag steht ja das die Bilder korrekt in einem DB-Browser angezeigt werden.
“Java is a DSL to transform big Xml documents into long exception stack traces.”
— Scott Bellware
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ahhhh. Ok.
bigbonzo
User
Beiträge: 21
Registriert: Samstag 30. November 2019, 10:23

... genau blackjack.
Was muss ich denn jetzt tun ?
data = selection[12] ## string aus der Datenbank
f = io.BytesIO(b'data')
photo=image.open(f)
Sirius3
User
Beiträge: 18216
Registriert: Sonntag 21. Oktober 2012, 17:20

data ist eine Variable mit Bytes als Wert. b'data' ist ein literaler Bytesstring. Erstes macht in deinem Fall mehr Sinn.
Benutzeravatar
__blackjack__
User
Beiträge: 13919
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@bigbonzo: ``selection[12]`` riecht komisch. Das heisst ja das Du da ein Ergebnis mit mindestens 13 Werten pro Datensatz bekommst. Verwendest Du die auch tatsächlich *alle*? Und sind die auch alle nach dem SELECT aufgelistet oder steht da ein "*"? Das sollte da nicht stehen, sondern explizit die Spaltennamen deren Werte man auch haben möchte. Damit wird das Programm verständlicher und robuster gegen Änderungen des Datenbankschemas.
“Java is a DSL to transform big Xml documents into long exception stack traces.”
— Scott Bellware
bigbonzo
User
Beiträge: 21
Registriert: Samstag 30. November 2019, 10:23

@Sirius; mit b'data' kommt die Fehlermeldung "AttributeError: 'Image' object has no attribute 'open'" , mit 'data' kommt die Fehlermeldung "TypeError: a bytes-like object is required, not 'str'"
Wie muss der Programmcode lauten, um mit dem Datenbankwert ein Image in der GUI anzuzeigen ?
data = selection[12] ## string aus der Datenbank
f = io.BytesIO(b'data')
photo=image.open(f)

Gibt es da eine Lösung zu ?
Danke.
bigbonzo
User
Beiträge: 21
Registriert: Samstag 30. November 2019, 10:23

@blackjack; der Hinweis ist richtig, hier aber leider nicht zielführend.
Ich habe seit 25 Jahren mit relationalen Datenbanken und -modellierungen zu tun und kann bestätigen, dass eine Änderung des Datenmodells und Datenbankschemas u.U. viel Aufwand bedeutet. In diesem Fall geht es aber nur um eine einzige Tabelle mit 14 Attributen ;-) und ein klein wenig Funktionalität drum herum. Mein Problem ist, dass ich Python Laie bin und nur für mich ein kleines Progrämmchen schreiben möchte.
Ich weiß, dass ich da bestimmt einiges durcheinander werfe und falsch ansetze, aber ich glaube, dass ihr Fachleute, die paar Zeilen Code, die zum Ergebnis führen, parat habt.
Wie muss der Code aussehen, um mit den Informationen in der Variable data ein Tkinter Image in der GUI anzuzeigen?
Danke.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du sollst

data

benutzen. OHNE ANFÜHRUNGSZEICHEN!

Wenn du so ein doller SQL Experte bist, dann sollte dir doch der Unterschied zwischen einem Namen einer Spalte und einem String-Literal in Anführungszeichen bekannt sein. Wieso denkst du das wäre in Python anders?
Benutzeravatar
__blackjack__
User
Beiträge: 13919
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@bigbonzo: Du machst hier den Fehler das Du folgendes hast:

Code: Alles auswählen

name = "Peter"
print("name")
Und Dich fragst warum da nicht Peter ausgegeben wird. Namen/Variablen und literale Werte und den Unterschied dazwischen zu verstehen ist eigentlich recht grundlegend. Und in SQL ist das doch genau so, das hier wird ja auch nicht den Wert der Spalte Nachname liefern sondern den Wert 'Nachname':

Code: Alles auswählen

SELECT 'Nachname' FROM personen WHERE id=1;
“Java is a DSL to transform big Xml documents into long exception stack traces.”
— Scott Bellware
bigbonzo
User
Beiträge: 21
Registriert: Samstag 30. November 2019, 10:23

@deets, will mich hier nicht als SQL Experte darstellen, bin ich nicht, suche nur eine Antwort für den Programmcode.
Natürlich hatte ich das auch ohne Anführungszeichen ausprobiert, dann kommt folgende Fehlermeldung "TypeError: a bytes-like object is required, not 'str'"
Antworten