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.
Can't add image to clipboard from share sheet extension?
-
Hi --
I'm trying to use Pythonista 3.4 to push some data to the clipboard, and am running into an error. The code below reproduces the problem: if I am in an app that allows you to share an image (e.g. for a social media post or similar) and I share that image with this Pythonista code, I get the following output:
Starting test Setting clipboard image Traceback (most recent call last): File "/private/var/mobile/Library/Mobile Documents/iCloud~com~omz-software~Pythonista3/Documents//pythonista-scripts/clipboard-image-test.py", line 24, in <module> main() File "/private/var/mobile/Library/Mobile Documents/iCloud~com~omz-software~Pythonista3/Documents//pythonista-scripts/clipboard-image-test.py", line 17, in main r1 = clipboard.set_image(my_image, format="png", jpeg_quality=1.0) File "/var/containers/Bundle/Application/B859D305-94CD-48F6-8589-AE439D2CCB7E/Pythonista3.app/Frameworks/Py3Kit.framework/pylib/site-packages/pythonista/clipboard.py", line 55, in set_image image_data = rgba_image.tostring() File "/var/containers/Bundle/Application/B859D305-94CD-48F6-8589-AE439D2CCB7E/Pythonista3.app/Frameworks/Py3Kit.framework/pylib/site-packages/PIL/Image.py", line 520, in __getattr__ raise AttributeError(name) AttributeError: tostring
It looks like Pythonista's
clipboard.py
is calling argba_image.tostring()
method which no longer exists in the version ofPIL
shipping with Pythonista 3.4.Has anyone else seen this? Any suggestions to work around it?
Thanks!
Sample code is below.
import importlib import importlib.util def main(): print("Starting test") # check to see if appex library is available appex_spec = importlib.util.find_spec("appex") FOUND_APPEX_LIBRARY = appex_spec is not None if FOUND_APPEX_LIBRARY: import appex import clipboard import shortcuts if appex.is_running_extension(): my_image = appex.get_image() print("Setting clipboard image") r1 = clipboard.set_image(my_image, format="png", jpeg_quality=1.0) print("Finished setting clipboard image") else: print("This demo is for Pythonista running in an extension") if __name__ == "__main__": main()
-
try: import appex import clipboard import shortcuts except ImportError: raise Exception("This code only runs on Pythonista on iOS.")
-
@felciano try this workaround
my_image = appex.get_image(image_type='ui') print("Setting clipboard image") r1 = clipboard.set_image(my_image, format="png", jpeg_quality=1.0) print("Finished setting clipboard image")
But, you are right, with image_type = 'pil', the default, the clipboard.set_image crashes with error as you described (thus problem for @omz)
-
Thanks @cvp. That workaround addresses the immediate issue, however now it looks like the
Image
object returned bymy_image = appex.get_image(image_type="ui")
is missing methods as well (e.g.
my_image.format
fails).Submitted https://github.com/omz/Pythonista-Issues/issues/702 and https://github.com/omz/Pythonista-Issues/issues/703 for these.
-
@felciano sure that an ui.Image does not have the methods of a PIL image but the clipboard.set_image allows to save an ui.Image as a format=png
-
@cvp I need to do other things with the image besides push it to the clipboard. Is there a way to convert it from a "ui" image to a regular "pil" image once, and then use the "pil" version going forward?
-
OK I think I found a workaround. Ugly, but servicable until this gets fixed in the mainline: I retrieve the share sheet image in PIL format as desired, but then convert it to to "ui" format before pushing to the clipboard. For all other uses, I have a PIL object with all the right methods.
In case anyone else runs into this, this code shows the workaround:
import importlib import importlib.util import io import ui from PIL import Image def pil2ui(pil_img): with io.BytesIO() as buffer: pil_img.save(buffer, format='PNG') return ui.Image.from_data(buffer.getvalue()) def main(): print("Starting test") # check to see if appex library is available appex_spec = importlib.util.find_spec("appex") FOUND_APPEX_LIBRARY = appex_spec is not None if FOUND_APPEX_LIBRARY: import appex import clipboard import shortcuts if appex.is_running_extension(): my_image = appex.get_image(image_type="pil") # workaround: force to 'ui' format my_new_image = pil2ui(my_image) print("Setting clipboard image") r1 = clipboard.set_image(my_new_image, format="png", jpeg_quality=1.0) print("Finished setting clipboard image") else: print("This demo is for Pythonista running in an extension") if __name__ == "__main__": main()