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.
I need help displaying a python PIL image within Pythonista UI
-
Hi there, I am completely new to Pythonista UI and all I need to do is show an image generated within PIL, I have found https://forum.omz-software.com/topic/1935/how-can-i-convert-a-pil-image-to-a-ui-image However I can only get it to work on a button, as I have no idea how to get it to work.
The reason I need it to displayed outside of a button is that I need to be able to tap anywhere on the image and get the x and y coordinates of the tap, which I don’t think you can do with the button.
Any help; would be great thanks!!! -
@PeterDaGrape try this little script (tap anywhere) and tell me if I had correctly understood your request
import ui from PIL import Image import io def pil2ui(imgIn): with io.BytesIO() as bIO: imgIn.save(bIO, 'PNG') imgOut = ui.Image.from_data(bIO.getvalue()) return imgOut class MyView(ui.View): def __init__(self, pil, *args, **kwargs): super().__init__(self, *args, **kwargs) iv = ui.ImageView() iv.touch_enabled = True iv.frame = self.frame self.add_subview(iv) iv.image = pil2ui(pil) def touch_began(self, touch): x,y = touch.location self.name = f'x={x} y={y}' pil = Image.open('test:Lenna') wi,hi = pil.size w = 400 h = w * hi/wi mv = MyView(pil,frame=(0,0,w,h)) mv.present('sheet')
-
You my friend are a genius, I had sort of figured out how to display the image within a window but only as a button, and I couldn’t find anywhere how you would just show a simple image within a window, and it works just as I needed, thanks as well for including the tap location part, that will also be extremely useful thank you!!!
-
@cvp this code is working perfectly, I have been playing around, and I can’t figure out how to refresh the image, so it will use the same image, and will refresh the view to show an updated version of the image, is this possible?
-
@PeterDaGrape It will depend how/when you want to change the image. Here a quick and dirty script to show how to change the image by tapping a button. It does not foresee the case where your images do not have the same proportion
import ui from PIL import Image import io def pil2ui(imgIn): with io.BytesIO() as bIO: imgIn.save(bIO, 'PNG') imgOut = ui.Image.from_data(bIO.getvalue()) return imgOut class MyView(ui.View): def __init__(self, *args, **kwargs): super().__init__(self, *args, **kwargs) self.images = ['test:Lenna', 'test:Mandrill', 'test:Peppers', 'test:Sailboat'] self.idx = 0 pil = Image.open(self.images[self.idx]) wi,hi = pil.size self.width = 400 self.height = self.width * hi/wi iv = ui.ImageView() iv.touch_enabled = True iv.frame = self.frame self.add_subview(iv) iv.image = pil2ui(pil) iv.name = 'iv' b = ui.ButtonItem() b.title = 'new image' b.action = self.b_action self.right_button_items = (b,) def touch_began(self, touch): x,y = touch.location self.name = f'x={x} y={y}' def b_action(self,sender): self.idx += 1 if self.idx == len(self.images): self.idx = 0 pil = Image.open(self.images[self.idx]) self['iv'].image = pil2ui(pil) mv = MyView() mv.present('sheet')
-
@PeterDaGrape another example with a gif (which contains a set of images) where the updating of images is automatically done by the standard update method of your ui.View. Try it
from PIL import Image import ui import io class Gif(ui.View): def __init__(self,gif_file,duration): self.frame = (0,0,400,400) self.duration = duration self.ImageView = ui.ImageView() self.ImageView.frame = self.frame self.add_subview(self.ImageView) self.pil = Image.open(gif_file) self.update_interval = self.duration / self.pil.n_frames self.frame_id = 0 def pil2ui(self,imgIn): with io.BytesIO() as bIO: imgIn.save(bIO, 'PNG') imgOut = ui.Image.from_data(bIO.getvalue()) del bIO return imgOut def update(self): # Display individual frames from the loaded animated GIF file self.pil.seek(self.frame_id) self.ImageView.image = self.pil2ui(self.pil) self.frame_id = self.frame_id + 1 if self.frame_id >= self.pil.n_frames: self.frame_id = 0 def touch_ended(self,touch): if self.update_interval == 0: self.update_interval = self.duration / self.pil.n_frames else: self.update_interval = 0 if __name__ == '__main__': v = Gif('../Examples/Misc/animation.gif',1) v.present('sheet')#,hide_title_bar=True)
-
Ah, thank you very much, Ill have a play around with this, currently it would be creating a new window for every image generated which isn’t ideal, ill let you know if it does as needed!!