python 將png圖片格式轉換生成gif動畫

先看知乎上面的一個鏈接    html

用Python寫過哪些【腦洞大開】的小工具?

 https://www.zhihu.com/question/33646570/answer/157806339python

這個哥們經過爬氣象網站的氣象雷達圖,生成一個gif的動態圖。很是有趣且很實用,那咱也實現下。web

 

首先先了解下什麼是幀,什麼是GIF  http://baike.baidu.com/item/GIF/217778

咱們先實現一個從GIF提取幀的代碼瀏覽器

咱們這有個gifapp

 

代碼以下:ide

from PIL import Image
import sys

def processImage(infile):
    try:
        im = Image.open(infile)
    except IOError:
        print ("Cant load", infile)
        sys.exit(1)
    i = 0
    mypalette = im.getpalette()

    try:
        while 1:
            im.putpalette(mypalette)
            new_im = Image.new("RGBA", im.size)
            new_im.paste(im)
            new_im.save('image\\a'+str(i)+'.png')

            i += 1
            im.seek(im.tell() + 1)

    except EOFError:
        pass # end of sequence

processImage('source.gif')

生成效果:工具

 

從gif提取frame是否是很簡單,只須要一個PIL庫搞定oop

但從frame生成gif就麻煩了,由於咱們使用的是py3,網上一大堆代碼用的是py2.*的 好比 PythonMagick 、 images2gif動畫

還有部分手寫gif文件頭部GIF89a,調用幀palette、NETSCAPE2.0寫入圖像等,大家都運行成功了,爲何我沒有運行成功呢?網站

唉!

python就是牛,庫如此之多,雖然本人Py通常般,但有前人爲你寫詩,您只要尾行加句號就能夠了。這裏我說的是imageio 

下載地址: https://pypi.python.org/pypi/imageio  (Version:2.2.0   by 2017-05-25)

import matplotlib.pyplot as plt
import imageio,os
images = []
filenames=sorted((fn for fn in os.listdir('.') if fn.endswith('.png')))
for filename in filenames:
    images.append(imageio.imread(filename))
imageio.mimsave('gif.gif', images,duration=1)

OK! gif生成了!

imageio查看參數: http://imageio.readthedocs.io/

imageio.help('gif')

 

其實,PIL自身也有一個save方法,裏面有一個‘save_all’ 參數,意思就是save多個,當format指定爲gif時,生成的即是gif的動畫

from PIL import Image
im=Image.open("a0.png")
images=[]
images.append(Image.open('a1.png'))
images.append(Image.open('a2.png'))
im.save('gif.gif', save_all=True, append_images=images,loop=1,duration=1,comment=b"aaabb")

讀取第一幀,將第一個幀的像素設置爲gif像素

 

python將png圖片格式轉換生成gif動畫已經能夠實現了,但咱們這裏要實現的是獲取氣象雷達圖生成GIF。

1.獲取數據

中國氣象網網站: http://products.weather.com.cn/product/radar/index/procode/JC_RADAR_AZ9210_JB      這裏是上海南匯雷達站點圖

獲取數據,咱們使用pquery

from pyquery import PyQuery as pq
d = pq('http://products.weather.com.cn/product/radar/index/procode/JC_RADAR_AZ9210_JB')
DomTree = d('#slideform #slide option')

2.下載氣象雷達png圖

想這個用Image.open 直接打開url的文件路徑就能夠

images.append(Image.open('http://pi.weather.com.cn/i/product/pic/l/sevp_aoc_rdcp_sldas_ebref_az9210_l88_pi_20170621014800000.png'))

那確定是失敗的:

Traceback (most recent call last):
  File "E:/project/test2/my.py", line 29, in <module>
    images.append(Image.open('http://pi.weather.com.cn/i/product/pic/l/sevp_aoc_rdcp_sldas_ebref_az9210_l88_pi_20170621014800000.png'))
  File "C:\Python36\lib\site-packages\PIL\Image.py", line 2410, in open
    fp = builtins.open(filename, "rb")
OSError: [Errno 22] Invalid argument: 'http://pi.weather.com.cn/i/product/pic/l/sevp_aoc_rdcp_sldas_ebref_az9210_l88_pi_20170621014800000.png'

異想天開呀!!!

imageio支持url文件路徑   參考: http://imageio.readthedocs.io/en/latest/examples.html

import imageio
import visvis as vv

im = imageio.imread('http://upload.wikimedia.org/wikipedia/commons/d/de/Wikipedia_Logo_1.0.png')
vv.imshow(im)

 

使用requests 庫保存圖片

import requests
r = requests.get('http://pi.weather.com.cn/i/product/pic/l/sevp_aoc_rdcp_sldas_ebref_az9210_l88_pi_20170621014800000.png', timeout=3)
file = open('b1.png', 'wb')
size = file.write(r.content)
file.close()

 

3.生成氣象雷達GIF圖

python 生成gif在上面咱們已經說到兩種方法,一種是imageio 另外一種是PIL自帶save_all, 這裏咱們直接寫一個類封裝方法

源碼以下:

# -*- coding: UTF8 -*-
import requests
from pyquery import PyQuery as pq
import os, sys
import imageio
from PIL import Image

'''
天氣預報.gif 生成class
'''


class weatherForecast():
    def __init__(self, weatherSite, path, endpng, savemodel):
        self.savemodel = savemodel
        if not os.path.exists(path):
            os.makedirs(path)

    def getPic(self):
        '''
        獲取資源
        '''
        print('獲取pic')
        d = pq(weatherSite)
        DomTree = d('#slideform #slide option')  # 獲取DOM節點option 標籤
        num = 100
        for bigpic in DomTree.items():
            pic = bigpic.attr('bigpic')  # 獲取bigpic 屬性指
            num += 1
            self.download(pic, 'a' + str(num) + '.png')  # 下載pic
        print('pic下載成功,共下載' + str(num - 100) + '個png')
        self.download(endpng, 'a1200.png')  # 下載end.png
        self.download(endpng, 'a1201.png')
        self.download(endpng, 'a1202.png')
        self.download(endpng, 'a1203.png')

    def download(self, url, fname):
        '''
        下載pic
        :return images size
        '''
        size = 0
        try:
            r = requests.get(url, timeout=3)
            file = open(path + fname, 'wb')
            size = file.write(r.content)
            file.close()
        except:
            pass
        return size

    def getGIF(self):
        '''
        生成gif
        '''
        images = []
        print('執行開始')
        self.getPic()  # 獲取圖片資源
        filenames = sorted(fn for fn in os.listdir(path) if fn.endswith('.png'))
        if self.savemodel == 1:  # imageio方法
            for filename in filenames:
                images.append(imageio.imread(path + filename))
            print('執行conversion操做')
            imageio.mimsave('weather.gif', images, duration=0.5, loop=1)  # duration 每幀間隔時間,loop 循環次數
            print('完成……')
        elif self.savemodel == 2:  # PIL 方法
            imN = 1
            for filename in filenames:
                if imN == 1:  # 執行一次 im的open操做,PIL在保存gif以前,必須先打開一個生成的幀,默認第一個frame的大小、調色
                    im = Image.open(path + filename)
                    imN = 2

                images.append(Image.open(path + filename))
            print('執行conversion操做')
            im.save('weather.gif', save_all=True, append_images=images, loop=1, duration=500,
                    comment=b"this is my weather.gif")
            print('完成……')


'''
注:loop循環次數在瀏覽器有效果,用看圖軟件不起做用
'''
if __name__ == "__main__":
    weatherSite = "http://products.weather.com.cn/product/radar/index/procode/JC_RADAR_AZ9210_JB"  # 上海南匯
    path = 'images/'  # png 圖片存儲位置
    endpng = 'http://images.cnblogs.com/cnblogs_com/dcb3688/982266/o_end.png'  # 因gif是循環播放,end png 區分新loop
    savemodel = 1  # 1:imageio保存圖片, 2:PIL保存圖片
    weatherForecast = weatherForecast(weatherSite, path, endpng, savemodel)
    weatherForecast.getGIF()
    sys.exit()

也能夠修改gif尺寸大小,先修改png大小

    def download(self, url, fname):
        '''
        下載pic
        :return images size
        '''
        size = 0
        try:
            r = requests.get(url, timeout=3)
            file = open(path + fname, 'wb')
            size = file.write(r.content)
            file.close()
            # 修改圖片大小,原:x=640*y=480  = 320*240
            ima = Image.open(path + fname)
            (x, y) = ima.size  # read image size
            x_s = 320
            y_s = int((y * x_s) / x)  # #calc height based on standard width
            out = ima.resize((x_s, y_s), Image.ANTIALIAS)  # resize image with high-quality
            out.save(path + fname)


        except:
            pass
        return size

 

 

images目錄

 

生成氣象雷達圖gif

 

4.外部訪問氣象雷達圖

腳步寫好了,如何讓別人也能訪問呢,直接仍到公網IP的website目錄就好了,而後寫一個crontab定時腳步,每5分鐘生成一次

*/5 * * * * python /home/wwwroot/www/web/static/weather/weather_forecast.py                  #每5分鐘執行天氣查詢腳本

在這裏,若是執行crontab定時腳步,代碼生成的gif就要指定位置,不然生成的gif會在/root 目錄裏面

imageio.mimsave('/home/wwwroot/www/web/static/weather/weather.gif', images, duration=0.5, loop=1)  # duration 每幀間隔時間,loop 循環次數

相關文章
相關標籤/搜索