Получите размер изображения, не загрузив его в Python
Как я могу получить размеры изображения, не загружая его? Это вообще возможно? У меня есть список URL изображений, и я хочу назначить ему ширину и размер.
Я знаю, что есть способ сделать это локально (Как проверить размеры всех изображений в каталоге, используя python?), Но я не хочу загружать все изображения.
Редактировать:
После ред. предложения, я редактировал код. Я придумал этот код. Не уверен, что погода загружает весь файл или только часть (как я хотел).
Ответы
Ответ 1
Это основано на ответе ed, смешанном с другими вещами, которые я нашел в Интернете. Я столкнулся с тем же вопросом, что и grotos с .read(24). Загрузите getimageinfo.py из здесь и скачайте ReSeekFile.py из здесь.
import urllib2
imgdata = urllib2.urlopen(href)
image_type,width,height = getimageinfo.getImageInfo(imgdata)
Измените getimageinfo как таковой...
import ReseekFile
def getImageInfo(datastream):
datastream = ReseekFile.ReseekFile(datastream)
data = str(datastream.read(30))
#Skipping to jpeg
# handle JPEGs
elif (size >= 2) and data.startswith('\377\330'):
content_type = 'image/jpeg'
datastream.seek(0)
datastream.read(2)
b = datastream.read(1)
try:
while (b and ord(b) != 0xDA):
while (ord(b) != 0xFF): b = datastream.read(1)
while (ord(b) == 0xFF): b = datastream.read(1)
if (ord(b) >= 0xC0 and ord(b) <= 0xC3):
datastream.read(3)
h, w = struct.unpack(">HH", datastream.read(4))
break
else:
datastream.read(int(struct.unpack(">H", datastream.read(2))[0])-2)
b = datastream.read(1)
width = int(w)
height = int(h)
except struct.error:
pass
except ValueError:
pass
Ответ 2
Я нашел решение на этом сайте, чтобы хорошо работать:
import urllib
import ImageFile
def getsizes(uri):
# get file size *and* image size (None if not known)
file = urllib.urlopen(uri)
size = file.headers.get("content-length")
if size: size = int(size)
p = ImageFile.Parser()
while 1:
data = file.read(1024)
if not data:
break
p.feed(data)
if p.image:
return size, p.image.size
break
file.close()
return size, None
print getsizes("http://www.pythonware.com/images/small-yoyo.gif")
# (10965, (179, 188))
Ответ 3
Если вы хотите загрузить первые 24 байта каждого файла, то эта функция (упомянутая в ответе johnteslade на вопрос, который вы упомянули) будет определять размеры.
Это, вероятно, наименьшая загрузка, необходимая для работы, которую вы хотите.
import urllib2
start = urllib2.urlopen(image_url).read(24)
Изменить (1):
В случае файлов JPEG это, кажется, нужно больше байтов. Вы можете отредактировать функцию так, чтобы вместо чтения StringIO.StringIO (данные) она вместо этого считывала дескриптор файла из urlopen. Тогда он будет читать ровно столько изображения, сколько ему нужно, чтобы узнать ширину и высоту.
Ответ 4
Это всего лишь Python 3+ адаптация более раннего ответа здесь.
import urllib
from PIL import ImageFile
def getsizes(uri):
# get file size *and* image size (None if not known)
file = urllib.request.urlopen(uri)
size = file.headers.get("content-length")
if size:
size = int(size)
p = ImageFile.Parser()
while True:
data = file.read(1024)
if not data:
break
p.feed(data)
if p.image:
return size, p.image.size
break
file.close()
return(size, None)
Ответ 5
Так как getimageinfo.py, упомянутый выше, не работает в Python3. Вместо него используется подушка.
Подушка может быть найдена в pypi или установлена с помощью pip: pip install pillow
.
from io import BytesIO
from PIL import Image
import requests
hrefs = ['https://farm4.staticflickr.com/3894/15008518202_b016d7d289_m.jpg','https://farm4.staticflickr.com/3920/15008465772_383e697089_m.jpg','https://farm4.staticflickr.com/3902/14985871946_86abb8c56f_m.jpg']
RANGE = 5000
for href in hrefs:
req = requests.get(href,headers={'User-Agent':'Mozilla5.0(Google spider)','Range':'bytes=0-{}'.format(RANGE)})
im = Image.open(BytesIO(req.content))
print(im.size)
Ответ 6
Невозможно сделать это напрямую, но для этого есть обходной путь. Если файлы присутствуют на сервере, затем реализуйте конечную точку API, которая принимает имя изображения в качестве аргумента и возвращает размер.
Но если файлы находятся на другом сервере, у вас нет другого пути, кроме как загрузить файлы.
Ответ 7
К сожалению, я не могу комментировать, так что это как ответ:
Используйте запрос get с заголовком
"Range": "bytes=0-30"
А затем просто используйте
http://code.google.com/p/bfg-pages/source/browse/trunk/pages/getimageinfo.py
Если вы используете python-запросы, просто
r = requests.get(image_url, headers={
"Range": "bytes=0-30"
})
image_info = get_image_info(r.content)
Это исправление ed. отвечать и не имеет каких-либо других зависимостей (например, ReSeekFile.py).
Ответ 8
У меня исправлено "getimageInfo.py", работайте с Python 3.4+, попробуйте, просто отлично!
import io
import struct
import urllib.request as urllib2
def getImageInfo(data):
data = data
size = len(data)
#print(size)
height = -1
width = -1
content_type = ''
# handle GIFs
if (size >= 10) and data[:6] in (b'GIF87a', b'GIF89a'):
# Check to see if content_type is correct
content_type = 'image/gif'
w, h = struct.unpack(b"<HH", data[6:10])
width = int(w)
height = int(h)
# See PNG 2. Edition spec (http://www.w3.org/TR/PNG/)
# Bytes 0-7 are below, 4-byte chunk length, then 'IHDR'
# and finally the 4-byte width, height
elif ((size >= 24) and data.startswith(b'\211PNG\r\n\032\n')
and (data[12:16] == b'IHDR')):
content_type = 'image/png'
w, h = struct.unpack(b">LL", data[16:24])
width = int(w)
height = int(h)
# Maybe this is for an older PNG version.
elif (size >= 16) and data.startswith(b'\211PNG\r\n\032\n'):
# Check to see if we have the right content type
content_type = 'image/png'
w, h = struct.unpack(b">LL", data[8:16])
width = int(w)
height = int(h)
# handle JPEGs
elif (size >= 2) and data.startswith(b'\377\330'):
content_type = 'image/jpeg'
jpeg = io.BytesIO(data)
jpeg.read(2)
b = jpeg.read(1)
try:
while (b and ord(b) != 0xDA):
while (ord(b) != 0xFF): b = jpeg.read(1)
while (ord(b) == 0xFF): b = jpeg.read(1)
if (ord(b) >= 0xC0 and ord(b) <= 0xC3):
jpeg.read(3)
h, w = struct.unpack(b">HH", jpeg.read(4))
break
else:
jpeg.read(int(struct.unpack(b">H", jpeg.read(2))[0])-2)
b = jpeg.read(1)
width = int(w)
height = int(h)
except struct.error:
pass
except ValueError:
pass
return content_type, width, height
#from PIL import Image
#import requests
#hrefs = ['http://farm4.staticflickr.com/3894/15008518202_b016d7d289_m.jpg','https://farm4.staticflickr.com/3920/15008465772_383e697089_m.jpg','https://farm4.staticflickr.com/3902/14985871946_86abb8c56f_m.jpg']
#RANGE = 5000
#for href in hrefs:
#req = requests.get(href,headers={'User-Agent':'Mozilla5.0(Google spider)','Range':'bytes=0-{}'.format(RANGE)})
#im = getImageInfo(req.content)
#print(im)
req = urllib2.Request("http://vn-sharing.net/forum/images/smilies/onion/ngai.gif", headers={"Range": "5000"})
r = urllib2.urlopen(req)
#f = open("D:\\Pictures\\1.jpg", "rb")
print(getImageInfo(r.read()))
# Output: >> ('image/gif', 50, 50)
#print(getImageInfo(f.read()))
Исходный код: http://code.google.com/p/bfg-pages/source/browse/trunk/pages/getimageinfo.py