加入收藏 | 设为首页 | 会员中心 | 我要投稿 财气旺网 - 财气网 (https://www.caiqiwang.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 编程要点 > 语言 > 正文

怎样使用Python对Gif进行压 缩

发布时间:2022-11-25 12:42:55 所属栏目:语言 来源:
导读:  背景
  前天在给微信公众号上传文章的时候,文章里面有一个图片是gif的,在上传的过程中报错了,说是图片超大了。搜索之后发现图片需要小于5m。
  
  那么问题就转化为怎么把当前的gif给缩减到5m以内本
  背景
  前天在给微信公众号上传文章的时候,文章里面有一个图片是gif的,在上传的过程中报错了,说是图片超大了。搜索之后发现图片需要小于5m。
  
  那么问题就转化为怎么把当前的gif给缩减到5m以内本着有轮子用轮子,没有轮子造轮子的精神,网上搜索一番。
  
  发现一些现象
  
  1、压缩要不就是需要会员才能下载;
  
  2、要不免费的只能压缩5m以下的。
  
  考虑到能动手不花钱的本性,我觉得要自己搞一下。
  
  知识背景:
  
  众所周知,gif图就是由若干组图片组成的一种文件格式,有多张有一定差异的图片连续播放,间隔时间较小,欺骗了我们的眼睛和大脑,然后我们以为是一个完全连续的。其实就是一个类似快速翻书的操作。
  
  二、方案选型
  方案一
  
  因为gif是有多种图片做的,那我们就考虑把图片减少一些,比如说原来是100张是10m,我给缩减到10张,那体积可不就要缩小到1m左右了吗?当然,为了用户看起来不是那么卡顿,我就拍脑袋给缩减到20张吧,即只有原来的1/5。
  
  方案二
  
  如果缩减的图片太多导致gif看起来卡顿的话,我们可以考虑不缩减图片的张数,但是我们可以压缩图片。
  
  方案三
  
  最后的都是重要的,如果前面两个都无法满足的话,那就可以考虑把他们进行叠加。先减张数,再压缩拆分的图片。
  
  三、项目落实
  整体流程如下:
  
  if __name__ == "__main__":
     # 设置源gif的地址
     sourceGifPath = "/Users/user/test/f79a3e2c2e864863a6b1a66791cb0950_tplv-k3u1fbpfcp-watermark.gif"
     # 将gif拆分成多个图片,并保存在本地
     SplitGif(sourceGifPath)
     # 将指定位置的文件下的图片按照文件名索引排序,做成gif
     Combine2Gif(sourceGifPath[:-4], sourceGifPath[:-4] + "_result.gif")
     print("== finished ==")
  1、将源gif读入内存
  2、将gif拆分成png,并保存
  def SplitGif(gifPath):
     # 获取png存储的文件夹的地址
     pngDir = gifPath[:-4]
     # 要存储的文件夹下清理干净,避免影响当前操作
     rmPngDir(pngDir)
     # 创建存储的文件夹
     os.mkdir(pngDir)
     # 把指定gif拆分后存储到指定文件夹
     savePngToDir(gifPath, pngDir)
  2.1、获取要存储的地址
  
  2.2、清空并移除存储png的文件夹
  
  def rmPngDir(pngDir):
     if os.path.exists(pngDir):
         files = os.listdir(pngDir)
         # 如果不一个一个的移除文件夹下的文件的话,无法移除文件夹
         for file in files:
             file = pngDir + "/" + file
             os.remove(file)
         os.rmdir(pngDir)
  2.3、创建存储png的文件夹
  
  2.4、将gif拆分成png,并保存
  
  def savePngToDir(gifPath, pngDir):
     # 通过路径传教image对象
     image = Image.open(gifPath)
     try:
         # 循环,通过异常方案退出循环
         while True:
             # 获取当前的索引的位置
             current = image.tell()
             # 创建文件路径
             pngPath = pngDir + '/' + str(current) + '.png'
             image.save(pngPath, quality=100)
             # 索引后移,越界后异常,退出当前循环
             image.seek(current + 1)
     except EOFError as e:
         print(e)
         pass
  3、按照一定的间隔读取2中的png,并生成gif
  def Combine2Gif(folderPath, gifFilePath):
     GenerateGif(0.1, gifFilePath, getPngArray(folderPath))
  3.1、获取所有的png
  
  def getPngArray(folderPath):
     files = os.listdir(folderPath)
     pngFiles = []
     # 通过设置step,将文件的大小修改为原来的体积的1/step
     for i in range(0, len(files), 5):
         pngFiles.append(folderPath + "/" + ('%d.png' % i))
     return pngFiles
  3.2、将png合并成gif
  
  def GenerateGif(step, gifPath, filterPngs):
     images = []
     for filePath in filterPngs:
         images.append(imageio.imread(filePath))
     # 生成gif,duration 是播放两个图片之间的间隔时间
     imageio.mimsave(gifPath, images, duration=step)
  四、全部的代码
  #! /usr/local/bin/python3
  # -*- coding: utf-8 -*-
  from PIL import Image
  import os
  import imageio
  
  
  def SplitGif(gifPath):
     # 获取png存储的文件夹的地址
     pngDir = gifPath[:-4]
     # 要存储的文件夹下清理干净,避免影响当前操作
     rmPngDir(pngDir)
     # 创建存储的文件夹
     os.mkdir(pngDir)
     # 把指定gif拆分后存储到指定文件夹
     savePngToDir(gifPath, pngDir)
  
  
  def rmPngDir(pngDir):
     if os.path.exists(pngDir):
         files = os.listdir(pngDir)
         # 如果不一个一个的移除文件夹下的文件的话,无法移除文件夹
         for file in files:
             file = pngDir + "/" + file
             os.remove(file)
         os.rmdir(pngDir)
  
  
  def savePngToDir(gifPath, pngDir):
     # 通过路径传教image对象
     image = Image.open(gifPath)
     try:
         # 循环,通过异常方案退出循环
         while True:
             # 获取当前的索引的位置
             current = image.tell()
             # 创建文件路径
             pngPath = pngDir + '/' + str(current) + '.png'
             image.save(pngPath, quality=100)
             # 索引后移,越界后异常,退出当前循环
             image.seek(current + 1)
     except EOFError as e:
         print(e)
         pass
  
  
  def Combine2Gif(folderPath, gifFilePath):
     GenerateGif(0.1, gifFilePath, getPngArray(folderPath))
  
  
  # 获取文件的数组
  def getPngArray(folderPath):
     files = os.listdir(folderPath)
     pngFiles = []
     # 通过设置step,将文件的大小修改为原来的体积的1/step
     for i in range(0, len(files), 5):
         pngFiles.append(folderPath + "/" + ('%d.png' % i))
     return pngFiles
  
  
  def GenerateGif(step, gifPath, filterPngs):
     images = []
     for filePath in filterPngs:
         images.append(imageio.imread(filePath))
     # 生成gif,duration 是播放两个图片之间的间隔时间
     imageio.mimsave(gifPath, images, duration=step)
  
  
  if __name__ == "__main__":
     # 设置源gif的地址
     sourceGifPath = "/Users/user/test/f79a3e2c2e864863a6b1a66791cb0950_tplv-k3u1fbpfcp-watermark.gif"
     # 将gif拆分成多个图片,并保存在本地
     SplitGif(sourceGifPath)
     # 将指定位置的文件下的图片按照文件名索引排序,做成gif
     Combine2Gif(sourceGifPath[:-4], sourceGifPath[:-4] + "_result.gif")
     print("== finished ==")
  五、结尾
  作为一个追求高效的程序员,我就做一个能满足我需求的方案,即方案一。至于方案二和方案三,有兴趣的朋友可以举一反三。
 

(编辑:财气旺网 - 财气网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!