Seite 1 von 1
image file is truncated ?
Verfasst: Montag 4. September 2006, 10:00
von gorba
Hallo
Ich möchte an tkinter einen string übergeben, der mir dann das bild darstellt:
Code: Alles auswählen
def update_label(self, buffer):
im = Image.open( str.StringIO(buffer) )
im.thumbnail((280, 300), Image.ANTIALIAS)
self.photo = ImageTk.PhotoImage(im)
self.label.config(image = self.photo)
Diese funktion gibt mir folgenden Fehler aus:
Code: Alles auswählen
File "P:\Projekte\Eyetec_gp\Python\PythonSchnittstelle\picSplit.py", line 188, in updateGuiImage
GUI.update_label(self.receivedDataString)
File "betterGUI.py", line 172, in update_label
self.photo = ImageTk.PhotoImage(im)
File "C:\Python24\Lib\site-packages\PIL\ImageTk.py", line 116, in __init__
self.paste(image)
File "C:\Python24\Lib\site-packages\PIL\ImageTk.py", line 166, in paste
im.load()
File "C:\Python24\Lib\site-packages\PIL\ImageFile.py", line 192, in load
raise IOError("image file is truncated (%d bytes not processed)" % len(b))
IOError: image file is truncated (6 bytes not processed)
Wenn ich den string aber auf meine HD schreibe (als jpg) und ihn dann mit einem bildbearbeitungsprogramm anzeige, funktioniert das ganze...
Wie kann das sein?
Verfasst: Montag 4. September 2006, 22:20
von Michael Schneider
Hi Gorba,
was soll das hier bewirken?
im = Image.open( str.StringIO(buffer) )
Was ist str? StringIO simuliert doch schon einen Dateihandler, den Du nur an Image.open übergeben brauchst:
Code: Alles auswählen
from Tkinter import *
from StringIO import StringIO
import Image
from ImageTk import PhotoImage
def lade_bilddaten(sBild):
fileBild = open(sBild, "rb")
sData = fileBild.read()
fileBild.close()
return sData
tk = Tk()
SIO = StringIO(lade_bilddaten("test.jpg")) ## erstelle StringIO Instanz
im = Image.open(SIO) ## lade aus StringIO Instanz als Dateirepraesentation
## entspricht: im = Image.open("test.jpg")
ph = PhotoImage(im)
Label(tk, image = ph).grid()
tk.mainloop()
Grüße,
Michael
Verfasst: Dienstag 5. September 2006, 09:41
von gorba
=) Das Problem hatt sich von selber gelöst. Ich vermute ich hatte im header des jpg files noch unnötige Daten. Auf jeden Fall tritt das Problem nicht mehr auf, obwohl ich nicht sagen kann wieso... =S
Verfasst: Dienstag 5. September 2006, 19:42
von Leonidas
Davon ist abzuraten, da es die eingebaute Funktion str() überdeckt. Und str() ist ja öfter mal notwendig.
Verfasst: Mittwoch 6. September 2006, 09:49
von gorba
danke für die info. Habs gleich geändert. War mir nicht bewusst.
Verfasst: Mittwoch 6. September 2006, 13:17
von gorba
Ich habs. Das Problem war, dass im Header des Bildes eine andere Grösse stand, als ich wirklich hatte. Somit dachte mein tkinter, das bild sei so noch nicht komplett.
Hab gleich die nächste Frage =)
Ich möchte, wenn ich einen Teil des Bildes empfangen habe, den gleich darstellen. Ich nehme also meine Bilddaten, fülle den rest mit 0 auf (damit tkinter mit der grösse zufrieden ist) und zeige dann das ganze an:
Code: Alles auswählen
class MyClass(Frame):
sImage = "" ## Pfad des aktuell geladenen Bildes
photo = None ## aktuell geladenes Bild (Raster)
def __init__(self, parent, master=None):
Frame.__init__(self, master)
self.grid()
self.create_gui()
def create_gui(self):
Button(root,text="Quit",command=self.quit).grid()
Button(root,text="Bild",command=self.send_em).grid()
self.label = Label(root, image=self.photo)
self.label.grid()
def update_label(self, buffer):
im = Image.open( strIO.StringIO(buffer) ) # im = Image.open('test123.jpg')
im.thumbnail((380, 400), Image.ANTIALIAS)
self.photo = ImageTk.PhotoImage(im)
self.label.config(image = self.photo)
def send_em(self):
#~ plc.plc_remote_write_uart_no_ack(MASTER,10,11,data=[], repetitions = 0,debug = 0)
#~ RecvData()
f = open('hw0.bmp','rb')
self.fd = f.read()
f.close()
size = len(self.fd)
x = 1000
datSize = x
padSize = size - x
new = ''
new += self.fd[0:x]
new += '0' * padSize
self.update_label(new)
print '------------------------------------------'
time.sleep(0.5)
x = 2000
datSize = x
padSize = size - x
new = ''
new += self.fd[0:x]
new += '0' * padSize
print '------------------------------------------'
self.update_label(new)
root=Tk()
root.title("Viewer")
my_class = MyClass(root)
GUIFD = my_class
root.mainloop()
Komisch finde ich nun, dass tkinter den ersten aufruf von self.update_label(new) "ignoriert". Dass heisst, er zeigt mir erst das Bild beim letzten self.update_label(new) an. Egal wiviele zwischenschritte ich habe.
Gibt es sowas wie ein refresh() für tkinter? Oder kann mir jemand sagen, wiso sich tkinter so verhält?
Bin für jeden input dankbar.
greez
Verfasst: Mittwoch 6. September 2006, 14:27
von HWK
Die Darstellung beginnt erst nach Aufruf von mainloop(). Du mußt die Ausgabe also nach mainloop() z.B. in einem eigenen Thread, der ein Event an Tkinter sendet, aktualisieren oder vielleicht einfacher über einen Tkinter-Timer (after()), der in MyClass.__init__() gestartet wird.
MfG
HWK
Verfasst: Donnerstag 7. September 2006, 20:25
von Michael Schneider
Hi Gorba,
ich lasse mich gern verbessern, aber ich denke nicht dass das (in jedem Fall) so funktioniert. Denn es gibt verschiedene Arten der JPEG-Komprimierung, einige bauen das Bild z.B. in mehreren Verfeinerungsstufen auf. Ich weiß nicht was passiert, wenn plötzlich Daten von Blöcken fehlen. Zumindest wird das Bild mit Deinem Verfahren ziemlich sicher zur Unkenntlichkeit verunstaltet.
Sorry,
Michael
Verfasst: Freitag 8. September 2006, 11:56
von gorba
genau das habe ich auch festgestellt. bei bmp funktionier es (logischerweise) bei jpg schaut die ganze sache wesentlich komplizierter aus. Hab noch keinen weg gefunden, das Bild wider sauber darzustellen, nachdem irgendwo (header ausgeschlossen) bytes fehlen..
edit: das iterative anzeigen funktioniert so (mit auffüllen der leeren bytes). allerdings funktioniert sowas in der art nur bei bmp:
Code: Alles auswählen
lastImage = self.ImageNr
image = header[0]
lastBlock = self.CurrentBlockNo
nextBlock = header[1]
expectedBlock = lastBlock + 1
if(lastBlock == 255): # dirty fixing..
expectedBlock = 1
if(lastImage == image):
if(nextBlock == expectedBlock): # everything is great! The best case ever..
result = wordList
self.appendBlock(result)
elif(nextBlock == expectedBlock+1): # one block is lost in space. Not so good..
print 'One Block is lost in space. Padding with raw data'
size = len(wordList)
print 'Lenght of wordList = %d' % size
rawData = [0]
rawData = size * rawData
print 'Lenght of white RAW data = %d' % len(rawData)
i = 0
for words in wordList:
rawData.append(wordList[i])
i += 1
print 'Lengh of both: %d' % len(rawData)
result = rawData
self.appendBlock(result)
Dies ist nur ein teilausschnitt einer Funktion. Allerdings, wenn der Fall:
elif(nextBlock == expectedBlock+1):
eintritt, klappt das mit dem padding '0' nicht bez. es funkttioniert, allerdings ist das Bild verschoben und die Fraben stimmen nicht mehr.