Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
Bug: scene.load_pil_image raises SystemError
-
The 3.4 version raises a SystemError when using
scene.load_pil_image .This code
import scene from PIL import Image im = Image.new('RGBA',(10,10)) ims = scene.load_pil_image(im)
results in
Traceback (most recent call last):
File "/private/var/mobile/Containers/Shared/AppGroup/11021B83-B419-4F67-A331-D54B9BAFC718/Pythonista3/Documents/misc/a1.py", line 5, in <module>
ims = scene.load_pil_image(im)
File "/var/containers/Bundle/Application/A061EDB8-1B89-41D2-B706-1F4E042DE8E4/Pythonista3.app/Frameworks/Py3Kit.framework/pylib/site-packages/pythonista/scene_drawing.py", line 32, in load_pil_image
return load_image_data(b.getvalue())
SystemError: PY_SSIZE_T_CLEAN macro must be defined for '#' formats -
@upwart Thank you, I'll look into it.
-
@upwart Workaround
import scene from PIL import Image import os im = Image.new('RGBA',(10,10)) #ims = scene.load_pil_image(im) path = 'temp.png' im.save(path, 'PNG') ims = scene.load_image_file(path) os.remove(path)
-
@cvp
Thanks for the workaround. I wonder whether that would work in my case as I have to do hundreds if not thousands of these call per second. Maybe your workaround with io.BytesIO would improve performance. -
@upwart said
. I wonder whether that would work in my case as I have to do hundreds if not thousands of these call per second.
Wow. So much? Not sure it could be possible even with load_pil_image.
And, there is no load_data!
-
@cvp
Yes, it's amazing how fast Pythonista (or the iPad) is.
Even with your workaround (thanks for that!), I can manage at least 2000 images per second.
It's all for animation with 'salabim', my discrete event simulation package (www.salabim.org).
It still crashes at some point in Pythonista 3.4, but for now I' happy. -
It crashes at some point
Please make sure that you are properly closing your
BytesIO
or you will have a memory leak and after processing many images, Pythonista will crash. The safest way is to use awith BytesIO as my_bytes:
context manager. -
@ccc In this case, he doesn't use BytesIO because scene_drawing doesn't provide a "load from bytes or data" method, only from pil (crash in V3.4) or from a file (workaround).
But I agree with your advice in case of using BytesIO -
@upwart you might consider writing directly to canvas.
See this thread about doing high performance real time audio and image display.
See the link in the first thread to Medric's implementation of an idea I had using IOSurface. You can basically get raw access to the image bytes, which you can copy from a PIL buffer without ever creating a UIImage, which has a bunch of overhead. UIImages have advantages when they will be shown more than once, but if you want to display them destroy, probably more than we need.
In particular, - when using UIImage in a loop, you have to have an auto release pool to drain every so often otherwise UIImages are never actually deleted from memory. That's a feature of IOS, not Python. For a while, Pythonista's autorelease pool context manager didn't quite work correctly, I haven't checked if latest Pythonista fixes some of the autorelease bugs of older versions. See thread below, which has an example which should fix most crashes when reading large numbers of images.
https://forum.omz-software.com/topic/6400/memory-usage-when-changing-image-in-an-ui-imageview/18
-
@JonB
Thanks for this advise.
In fact in my application, I just start every tick with an empty canvas a throw lots of PIL images in it. No copies, nothing destroyed (explicitely). So, your suggestion might work very well for me.
Thanks.