在 Python 中获取 GIF 图片的第一帧?
Getting the first frame of GIF image in Python?
Getting the first frame of a GIF image without downloading all the other frames
↑ 这个帖子和我想知道的问题差不多。
但就我而言,我使用的是 Python 3.6 和 urllib。
import urllib
import requests
img_file = urllib.request.urlopen(img_url, timeout=10)
f = open('/img/' + img_name, 'wb')
f.write(img_file.read())
f.close()
我正在使用此代码获取图像文件。但是对于GIF或者移动的jpg(GIF后缀为jpg)文件来说,下载时间太长了。
有没有办法只下载动画的第一帧?
我不会为你写完整的东西,这将涉及解析 GIF 文件的二进制内容,但这里有一个使用流行的第三方增量下载文件的示例 requests module (using information in this section其文档)。希望这会给你一个好的起点。
import requests
img_url = 'https://upload.wikimedia.org/wikipedia/commons/d/d3/Newtons_cradle_animation_book_2.gif'
#img_filename = 'test.gif'
response = requests.get(img_url, stream=True)
if response.status_code != 200:
print('Error:', response.status_code)
else:
header = response.raw.read(6)
print(header) # b'GIF89a'
# # Download whole file in chunks and save locally.
# with open(img_filename, 'wb') as f:
# for chunk in response.iter_content(chunk_size=128):
# f.write(chunk)
print('done')
按照@martineau 的建议发布我的答案。
- 如图所示构建 GIF 库 here
- 执行下面的代码,等待
result.png
写入磁盘:
from PIL import Image
from platform import system
from ctypes import string_at, Structure, c_long as cl, c_ubyte, \
py_object, pointer, POINTER as PT, CFUNCTYPE, CDLL
import requests
class GIF_WHDR(Structure): _fields_ = \
[("xdim", cl), ("ydim", cl), ("clrs", cl), ("bkgd", cl),
("tran", cl), ("intr", cl), ("mode", cl), ("frxd", cl), ("fryd", cl),
("frxo", cl), ("fryo", cl), ("time", cl), ("ifrm", cl), ("nfrm", cl),
("bptr", PT(c_ubyte)), ("cpal", PT(c_ubyte))]
def GIF_Load(lgif, file, size):
def WriteFunc(d, w):
list = d.contents.value
if (len(list) == 0):
list.append(Image.frombytes("L", (w[0].frxd, w[0].fryd),
string_at(w[0].bptr, w[0].frxd * w[0].fryd)))
list[0].putpalette(string_at(w[0].cpal, w[0].clrs * 3))
list = []
lgif.GIF_Load(file, size,
CFUNCTYPE(None, PT(py_object), PT(GIF_WHDR))(WriteFunc),
None, pointer(py_object(list)), 0)
return list
chunk = 32768
img = "wikipedia/commons/d/d3/Newtons_cradle_animation_book_2.gif"
lgif = CDLL(("%s.so", "%s.dll")[system() == "Windows"] % "./gif_load")
size = -1
file = b""
response = requests.get("https://upload.wikimedia.org/" + img, stream = True)
if response.status_code != 200:
print('Error:', response.status_code)
else:
while size < len(file):
size = len(file)
file += response.raw.read(chunk)
list = GIF_Load(lgif, file, len(file))
if (len(list) == 1):
list[0].save("result.png")
break
print("Read %d bytes\n" % len(file))
请记住,这只是一个示例;它不支持现代 GIF 中存在的许多东西,例如隔行扫描和透明度。对于完全兼容的版本,请参考 [1] 中的示例。
Getting the first frame of a GIF image without downloading all the other frames
↑ 这个帖子和我想知道的问题差不多。 但就我而言,我使用的是 Python 3.6 和 urllib。
import urllib
import requests
img_file = urllib.request.urlopen(img_url, timeout=10)
f = open('/img/' + img_name, 'wb')
f.write(img_file.read())
f.close()
我正在使用此代码获取图像文件。但是对于GIF或者移动的jpg(GIF后缀为jpg)文件来说,下载时间太长了。
有没有办法只下载动画的第一帧?
我不会为你写完整的东西,这将涉及解析 GIF 文件的二进制内容,但这里有一个使用流行的第三方增量下载文件的示例 requests module (using information in this section其文档)。希望这会给你一个好的起点。
import requests
img_url = 'https://upload.wikimedia.org/wikipedia/commons/d/d3/Newtons_cradle_animation_book_2.gif'
#img_filename = 'test.gif'
response = requests.get(img_url, stream=True)
if response.status_code != 200:
print('Error:', response.status_code)
else:
header = response.raw.read(6)
print(header) # b'GIF89a'
# # Download whole file in chunks and save locally.
# with open(img_filename, 'wb') as f:
# for chunk in response.iter_content(chunk_size=128):
# f.write(chunk)
print('done')
按照@martineau 的建议发布我的答案。
- 如图所示构建 GIF 库 here
- 执行下面的代码,等待
result.png
写入磁盘:
from PIL import Image
from platform import system
from ctypes import string_at, Structure, c_long as cl, c_ubyte, \
py_object, pointer, POINTER as PT, CFUNCTYPE, CDLL
import requests
class GIF_WHDR(Structure): _fields_ = \
[("xdim", cl), ("ydim", cl), ("clrs", cl), ("bkgd", cl),
("tran", cl), ("intr", cl), ("mode", cl), ("frxd", cl), ("fryd", cl),
("frxo", cl), ("fryo", cl), ("time", cl), ("ifrm", cl), ("nfrm", cl),
("bptr", PT(c_ubyte)), ("cpal", PT(c_ubyte))]
def GIF_Load(lgif, file, size):
def WriteFunc(d, w):
list = d.contents.value
if (len(list) == 0):
list.append(Image.frombytes("L", (w[0].frxd, w[0].fryd),
string_at(w[0].bptr, w[0].frxd * w[0].fryd)))
list[0].putpalette(string_at(w[0].cpal, w[0].clrs * 3))
list = []
lgif.GIF_Load(file, size,
CFUNCTYPE(None, PT(py_object), PT(GIF_WHDR))(WriteFunc),
None, pointer(py_object(list)), 0)
return list
chunk = 32768
img = "wikipedia/commons/d/d3/Newtons_cradle_animation_book_2.gif"
lgif = CDLL(("%s.so", "%s.dll")[system() == "Windows"] % "./gif_load")
size = -1
file = b""
response = requests.get("https://upload.wikimedia.org/" + img, stream = True)
if response.status_code != 200:
print('Error:', response.status_code)
else:
while size < len(file):
size = len(file)
file += response.raw.read(chunk)
list = GIF_Load(lgif, file, len(file))
if (len(list) == 1):
list[0].save("result.png")
break
print("Read %d bytes\n" % len(file))
请记住,这只是一个示例;它不支持现代 GIF 中存在的许多东西,例如隔行扫描和透明度。对于完全兼容的版本,请参考 [1] 中的示例。