用Python实现播放gif文件

用Python实现播放gif文件

在Python中,你可以使用第三方库Pillow(PIL)来加载和展示 GIF 文件。并实现“暂停”和“继续”控制功能。

Pillow是Python社区中最受欢迎的图像处理库之一,可以轻松地完成各种图像处理任务,它易于学习和使用,并且具有良好的文档和社区支持。Pillow基于PIL库进行了更新和改进(最初是PIL的一个分支,后来发展独立,并超越了它)。

Windows系统电脑中pillow库的安装,在cmd中输入如下命令后回车即可:

pip install pillow

若你的电脑上安装了多个Python版本,你可以为特定版本的Python安装,例如我的电脑中安装了多个Python版本,要在Python 3.10版本中安装,并使用清华的镜像,cmd命令行中,输入如下命令

py -3.10 -m pip install pillow -i https://pypi.tuna.tsinghua.edu.cn/simple

需要注意的是pillow库安装成功后,导包时要用PIL来导入,而不是用pillow【这里使用 PIL 导入,但实际上使用的是 Pillow 库,这里的 PIL 可以看做是 Pillow 库的简称】。如:

import PIL

from PIL import Image

关于第三方库Pillow(PIL)的更多介绍可见https://blog.csdn.net/cnds123/article/details/126141838

先看出效果图:

【提示:实际运行画面是动态的。】

注意,某些GIF可能使用了特殊的编码或格式特性,这些特性可能不被Pillow(PIL)库完全支持。

源码如下:

from PIL import Image, ImageTk
import tkinter as tk
from tkinter import filedialog

class GIFPlayer:
    def __init__(self, master):
        self.master = master
        self.frames = []
        self.delay = []
        self.is_paused = False
        self.gif_path = None

        # 创建画布和按钮
        self.canvas = tk.Canvas(master, width=400, height=400, bg='grey')
        self.canvas.pack()

        # 创建用于显示GIF的区域
        self.gif_area = self.canvas.create_rectangle(20, 20, 380, 380, outline='black')

        self.open_button = tk.Button(master, text="Open", command=self.open_file)
        self.open_button.pack()

        self.pause_button = tk.Button(master, text="Pause/Resume", command=self.toggle_pause)
        self.pause_button.pack()

    def open_file(self):
        self.gif_path = filedialog.askopenfilename(title="Open GIF", filetypes=[("GIF Files", "*.gif")])
        if not self.gif_path:
            return

        self.gif = Image.open(self.gif_path)
        self.original_width, self.original_height = self.gif.size

        self.original_frames = []  # 新增列表以保存原始的Image帧

        # 加载GIF帧
        try:
            for i in range(self.gif.n_frames):
                self.gif.seek(i)
                frame = self.gif.copy()
                if 'gif_frame' in frame.info:
                    frame.info['gif_frame'] = i
                self.original_frames.append(frame)  # 保存原始的Image帧
                self.frames.append(ImageTk.PhotoImage(frame))
                self.delay.append(self.gif.info['duration'])
        except EOFError:
            pass

        self.frame_index = 0
        self.scale_and_animate(0)

    def scale_and_animate(self, frame_index):
        # 获取指定区域的大小
        area_width = 360   #
        area_height = 360

        # 计算缩放因子
        scale_w = area_width / self.original_width
        scale_h = area_height / self.original_height
        scale = min(scale_w, scale_h)

        # 调整图像大小
        new_width = int(self.original_width * scale)
        new_height = int(self.original_height * scale)

        # 对原始帧应用缩放
        frame = self.original_frames[frame_index].resize((new_width, new_height), Image.ANTIALIAS)
        self.photo = ImageTk.PhotoImage(frame)  # 更新图片对象
        self.canvas.delete('gif')
        self.canvas.create_image(20, 20, anchor=tk.NW, image=self.photo, tags='gif')

        if not self.is_paused:
            self.frame_index = (self.frame_index + 1) % len(self.original_frames)
            self.master.after(self.delay[frame_index], lambda: self.scale_and_animate(self.frame_index))
   

    def toggle_pause(self):
        self.is_paused = not self.is_paused
        if self.is_paused:
            self.pause_button.config(text="Resume")
        else:
            self.pause_button.config(text="Pause")
            # 恢复播放时立即调用 scale_and_animate
            self.scale_and_animate(self.frame_index)

if __name__ == '__main__':
    root = tk.Tk()
    player = GIFPlayer(root)
    root.mainloop()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/585711.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

《21天学通C++》(第十二章)运算符类型与运算符重载

1.为什么要重载运算符&#xff1f; 通过重载运算符&#xff0c;可以将复杂的操作封装成简单的运算符形式&#xff0c;简化代码&#xff0c;提高可读性下面举一个简单的例子 计算两个点的坐标之和。 1.不重载运算符 #include <iostream> using namespace std; class P…

OpenHarmony实战开发-使用SmartPerf-Host分析应用性能

简介 SmartPerf-Host是一款深入挖掘数据、细粒度展示数据的性能功耗调优工具&#xff0c;可采集CPU调度、频点、进程线程时间片、堆内存、帧率等数据&#xff0c;采集的数据通过泳道图清晰地呈现给开发者&#xff0c;同时通过GUI以可视化的方式进行分析。该工具当前为开发者提…

docker在linux上的安装与使用

我的操作系统centos7本地vm docker安装 1、卸载旧版本 如果系统中已经存在旧的Docker&#xff0c;则先卸载 yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine 2、配置一…

Android 音视频基础知识

本系列文章会介绍两个 Android NDK Demo&#xff0c;拉流端会实现一个基于 FFmpeg 的视频播放器 Demo&#xff0c;推流端会实现一个视频直播 Demo&#xff0c;当然在做 Demo 之前会介绍音视频的基础知识。以下是本系列文章的目录&#xff1a; Android 音视频基础知识 Android 音…

【langchain】快速封装替换自定义LLM(基于自定义API或本地模型)

1. 引言 你可能已经注意到&#xff0c;LLM时代下的许多项目&#xff08;特别是Github上的论文项目、工程项目&#xff09;都要求我们设置OpenAI的API Key&#xff0c;就像这样&#xff1a; os.environ["OPENAI_API_KEY"] "sk-"from langchain_openai im…

SDKMAN!

概述 官网&#xff0c;SDKMAN是一款管理多版本SDK的工具&#xff0c;可以实现在多个版本间的快速切换。 其他特性&#xff1a; 易用&#xff1a;安装SDK不再需要去Google想安装的某个软件的官网的下载页&#xff0c;或找其他下载页面&#xff0c;然后下载安装包、解压、设置…

.NET C# ORM 瀚高数据库

SqlSugar ORM SqlSugar 是一款 老牌 .NET开源ORM框架&#xff0c;由果糖大数据科技团队维护和更新 &#xff0c;开箱即用最易上手的ORM 优点 &#xff1a;【生态丰富】【高性能】【超简单】 【功能全面】 【多库兼容】【适合产品】 【SqlSugar视频教程】 支持 &#xff1a…

C语言指针和数组的一些笔试题

文章目录 前言一、一维数组二、字符数组-1三、字符数组-2总结 前言 C语言指针和数组的一些笔试题 一、一维数组 #include <stdio.h> int main() {int a[] { 1,2,3,4 };printf("%d\n", sizeof(a));printf("%d\n", sizeof(a 0));printf("%d\n…

Eclipse MAT工具分析内存溢出

1、通过dominator_tree可以查看哪些对象大 可以看到com.codex.terry.entity.User对象有57万个 2、打开thread_overview查看内存溢出的代码

TCP重传,滑动窗口,流量控制,拥塞控制

TCP重传&#xff0c;滑动窗口&#xff0c;流量控制&#xff0c;拥塞控制 TCP重传机制&#xff1a; 超时重传快速重传SACKD-SACK 通过序列号与确认应答判断是否要重传 超时重传&#xff1a; 超过指定时间没有收到确认应答报文&#xff0c;就会重发该数据 触发超时重传的情况…

(十四)Servlet教程——Servlet中HttpSession的使用

除了使用Cookie&#xff0c;Web应用程序中还经常使用Session来记录客户端状态。Session是服务器端使用的一种记录客户端状态的机制&#xff0c;相应地也增加了服务器的存储压力。 1. 什么是Session Session是另外一种记录客户端状态的机制&#xff0c;不同的是Cookie保存在客户…

2024年618哪些数码家电值得入手?热门家电好物抢先看!

618购物狂欢节即将来临&#xff0c;这是一年一度的大促销活动&#xff0c;家电和数码产品在这个时间段内通常都会有优惠和折扣。但随着产品的多样化&#xff0c;很多时候一款产品就有多款品牌&#xff0c;在这不同品牌又各自擅长不同的东西&#xff0c;看着眼花缭乱。今天我就给…

基于python+django网易新闻+评论的舆情热点分析平台

博主介绍&#xff1a; 大家好&#xff0c;本人精通Java、Python、C#、C、C编程语言&#xff0c;同时也熟练掌握微信小程序、Php和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我有丰富的成品Java、Python、C#毕设项目经验&#xff0c;能够为学生提供各类…

Java中优雅实现泛型类型的强制转换

在Java中经常遇到将对象强制转换成泛型类的情况&#xff1a; Map<String, Object> data Map.of("name", "XiaoMing","age", 17,"scores", List.of(80, 90, 70) );List<Integer> scores (List<Integer>) data.get…

Docker容器添加修改端口映射的方法与详细步骤

1、先找到要修改的容器hash值&#xff1a; 2、然后退出docker Desktop服务 &#xff08;因为在线状态配置文件修改保存不了&#xff09; 3、资源管理器中打开最新安装的Docker的配置文件的路径&#xff1a; 4、打开后修改其中的 config.v2.json 和 hostconfig.json 5、启动…

【C++】哈希表的底层逻辑

目录 一、哈希概念 1、哈希冲突 2、哈希冲突的解决 a、闭散列 &#x1f7e2;插入 &#x1f7e2;查找 &#x1f7e2;删除 &#x1f7e2;其他类型的数据 &#x1f7e2;实现 b、 开散列 &#x1f7e2;插入 &#x1f7e2;查找 &#x1f7e2;删除 &#x1f7e2;析构 &a…

《霍格沃茨之遗》找不到emp.dll如何修复?分享5种亲测有效的方法

在我们享受电脑游戏带来的乐趣时&#xff0c;偶尔会遇到一些技术上问题&#xff0c;具体来说&#xff0c;当你启动一款游戏&#xff0c;系统却弹出一个提示“由于找不到emp.dll文件&#xff0c;因此无法继续执行代码”&#xff0c;这样的情况确实让人感到扫兴。这究竟是什么原因…

.net core ef 连表查询

Information和TypeInfo连表查询 类似&#xff1a; select st.Title1,si.* from [Star_Information] si left join Star_TypeInfo st on si.typeId2st.id 先在EfCoreDbContext.cs配置 protected override void OnModelCreating(ModelBuilder builder){base.OnModelCreating(b…

Jupyter Notebook 中使用虚拟环境的Python解释器

问题&#xff1a;创建虚拟环境&#xff0c;在pycharm中配置虚拟环境的Python解释器&#xff0c;然后在pycharm中打开ipynb&#xff0c;执行发现缺少包&#xff0c;但是虚拟环境中已经安装了 解决方式&#xff1a; 配置Jupyter Notebook 使用虚拟环境的Python解释器 1&#x…

ElasticSearch总结2

一、创建索引库&#xff1a;PUT ES中通过Restful请求操作索引库、文档。请求内容用DSL语句来表示。创建索引库和mapping的DSL语法如下&#xff1a; 整个jason 里边&#xff0c;它有一个叫mapping的属性&#xff0c;代表的是映射。映射里边有properties代表就是字段。可以看到这…