Sorry about the long post in advance.
Using Python 3.7.3, I want to have base64 encoded photo and resize it without saving to file to disk and reopening the file using Image.open().
I've looked into PyPng from This answer which seems to use the base64 data directly but I can't figure out how to resize it as a PIL Image. I know how to resize it, once it's a Pillow Image, what I need to figure out is how to get from base64 directly to a Pillow Image.
# import tkinter as tk, png
# from PIL import Image, ImageTk
# ... self.PIC_LABEL is a tk.Label() object.
def ShowImage(self, PhotoData=None):
try:
tempImg = png.Reader(bytes=PhotoData)
img = Image.open(tempImg)
# ... resizing code is working ...
self.PIC_LABEL.IMG = tk.PhotoImage(img)
self.PIC_LABEL.configure(image=self.PIC_LABEL.IMG)
except Exception as e:
logger.exception(e)
The error is:
FormatError: PNG file has invalid signature.
Traceback (most recent call last):
File "C:\Program Files\Python37\lib\site-packages\PIL\Image.py", line 2774, in open
fp.seek(0)
AttributeError: 'Reader' object has no attribute 'seek'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "D:/test.py", line 911, in ShowImage
img = Image.open(tempImg)
File "C:\Program Files\Python37\lib\site-packages\PIL\Image.py", line 2776, in open
fp = io.BytesIO(fp.read())
File "C:\Program Files\Python37\lib\site-packages\png.py", line 1813, in read
self.preamble(lenient=lenient)
File "C:\Program Files\Python37\lib\site-packages\png.py", line 1609, in preamble
self.validate_signature()
File "C:\Program Files\Python37\lib\site-packages\png.py", line 1595, in validate_signature
raise FormatError("PNG file has invalid signature.")
png.FormatError: FormatError: PNG file has invalid signature.
I also tried Image.open(base64.decodebytes(PhotoByteDataDict[name]))
, but it gives a "Invalid Start Byte error".
UPDATE: I tried something else based on this answer:
rawDefect = PhotoByteData['defect']
msg = base64.b64decode(rawDefect) # base64.decodebytes(rawDefect) doesn't work either.
buf = io.BytesIO(msg)
tempImg = Image.open(buf)
size = tempImg.size
size = (size[0]*2, size[1]*2)
tempImg = tempImg.resize(size)
print(tempImg)
newImg = tk.PhotoImage(tempImg)
lbl.configure(image=newImg)
This allows me to successfully create the Pillow Image and the tk.PhotoImage but crashes when you try to display it:
Traceback (most recent call last):
File "D:/OneDrive/WorkSpace/PyCharm WorkSpace/TruePad/DEV/DevTest.py", line 2907, in <module>
<PIL.Image.Image image mode=RGBA size=480x270 at 0x26DBB5DCDD8>
lbl.configure(image=newImg)
File "C:\Program Files\Python37\lib\tkinter\__init__.py", line 1485, in configure
return self._configure('configure', cnf, kw)
File "C:\Program Files\Python37\lib\tkinter\__init__.py", line 1476, in _configure
self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
TypeError: __str__ returned non-string (type Image)
Also Tired after looking through the source code for tk.PhotoImage:
tkDefect = tk.PhotoImage(data=rawDefect)
newHeight = 480 / tkDefect.height()
newWidth = 800 / tkDefect.width()
newSize = (newWidth, newHeight)
newImg = tkDefect.zoom(int(newWidth * tkDefect.width()), int(newHeight * tkDefect.height()))
lbl.configure(image=newImg)
But again crashes when trying to display it, with a different error:
Traceback (most recent call last):
File "Test.py", line 2919, in <module>
newImg = tkDefect.zoom(int(newWidth * tkDefect.width()), int(newHeight * tkDefect.height()))
File "C:\Program Files\Python37\lib\tkinter\__init__.py", line 3568, in zoom
self.tk.call(destImage, 'copy', self.name, '-zoom',x,y)
_tkinter.TclError: not enough free memory for image buffer
Any ideas?