omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    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

    Pythonista
    2
    7
    576
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • PeterDaGrape
      PeterDaGrape last edited by

      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!!!

      cvp 1 Reply Last reply Reply Quote 0
      • cvp
        cvp @PeterDaGrape last edited by cvp

        @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')	
        
        PeterDaGrape 1 Reply Last reply Reply Quote 1
        • PeterDaGrape
          PeterDaGrape last edited by

          @cvp

          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!!!

          1 Reply Last reply Reply Quote 0
          • PeterDaGrape
            PeterDaGrape @cvp last edited by

            @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?

            cvp 2 Replies Last reply Reply Quote 0
            • cvp
              cvp @PeterDaGrape last edited by

              @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')	
              
              1 Reply Last reply Reply Quote 0
              • cvp
                cvp @PeterDaGrape last edited by

                @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)
                
                1 Reply Last reply Reply Quote 0
                • PeterDaGrape
                  PeterDaGrape last edited by

                  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!!

                  1 Reply Last reply Reply Quote 0
                  • First post
                    Last post
                  Powered by NodeBB Forums | Contributors