Forum Archive

Display an animated GIF in an ImageView

cvp

I know we can display an animated gif via a WebView
see
but I wanted to display it into an Image, thus...
try this little imperfect script
if you tap on the gif, it will stop or restart

PS sorry if already done

from PIL import Image
import ui
import io

class Gif(ui.View):
    def __init__(self,gif_file,duration):
        self.duration = duration
        self.ImageView = ui.ImageView()
        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('dog left to right.gif',1)
    v.present('sheet')#,hide_title_bar=True)

cvp

brumm
        self.width, self.height = self.pil.size
        self.ImageView.frame = self.frame
cvp

@brumm you're right but my objective was only to display the gif. In reality, I display it in an ImageView with other dimensions, scaling the gif. And I move the ImageView horizontally at each update to show a moving dog, in its superview.

cvp
        class Gif(ui.View):
            def __init__(self,gif_file,duration):
                self.ImageView = ui.ImageView()
                self.add_subview(self.ImageView)
                self.pil = Image.open(gif_file)
                self.width, self.height = self.pil.size
                self.update_interval = 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):
                if 'right to left' in gif_file:
                    self.x = self.x - 5
                    if (self.x + self.width) < 0:
                        self.x = self.superview.width
                else:
                    self.x = self.x + 5
                    if self.x > self.superview.width:
                        self.x = - self.width
                # 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

v = ui.View()
v.frame = (0,0,600,10)
gif_file = os.path.expanduser('~/Documents/MesTools/Icons 32x32 black and white/dog left to right.gif')
wb = Gif(gif_file,1)        
wb.y = v.height
h = 120
wb.width, wb.height = wb.width * h / wb.height, h
if 'right to left' in gif_file:
    wb.x = v.width
else:
    wb.x = 0
v.height = v.height + wb.height + 10
v.add_subview(wb)
v.present('sheet')
Phuket2

@cvp , another nice use of the update method. Just having it there in the API and being stable is really nice I think. Opens up many possibilities as you have shown. For me as

Phuket2

@cvp , I just wanted to say another nice use of the update method. It's fairly easy for me to read your code and understand the logic flow. If you had to use threads and use decorators etc... all of a sudden its starts to look complex to someone like me. Also it appears that even very good Python programmers are not immune to different side effects when using threads and ui interaction. The update method just seems to work!
Just saying :)

cvp

@Phuket2 I agree. In the past, I used this for the same result:

        class Gif(ui.View):
            def __init__(self,gif_file,duration):
                ...
                self.update_interval = duration / self.pil.n_frames
                ui.delay(self.xupdate,self.update_interval)

            def xupdate(self):
                ...
                ui.delay(self.xupdate,self.update_interval)