Получите размер изображения, не загружая его в Python - PullRequest
18 голосов
/ 18 сентября 2011

Как я могу получить размеры изображения, не загружая его?Это вообще возможно?У меня есть список URL изображений, и я хочу назначить ему ширину и размер.

Я знаю, что есть способ сделать это локально ( Как проверить размеры всех изображений в каталоге, используяpython? ), но я не хочу загружать все изображения.

Редактировать:

После ред.предложения, я редактировал код.Я придумал этот код .Не уверен, что он загружает весь файл или только часть (как я хотел).

Ответы [ 8 ]

17 голосов
/ 29 января 2012

Это основано на ответе Эда, смешанном с другими вещами, которые я нашел в Интернете.Я столкнулся с той же проблемой, что и 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
15 голосов
/ 05 мая 2013

Я нашел решение на этом сайте , чтобы работать хорошо:

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))
10 голосов
/ 18 сентября 2011

Если вы хотите загрузить первые 24 байта каждого файла, то эта функция (упомянутая в ответе johnteslade на вопрос, который вы упомянули) отработает размеры.

Это, вероятно, наименьшая загрузка, необходимая для работы, которую вы хотите.

import urllib2
start = urllib2.urlopen(image_url).read(24)

Редактировать (1):

В случае файлов JPEG требуется больше байтов. Вы можете отредактировать функцию так, чтобы вместо чтения StringIO.StringIO (данные) она вместо этого считывала дескриптор файла из urlopen. Затем он будет читать ровно столько изображения, сколько ему нужно, чтобы узнать ширину и высоту.

5 голосов
/ 08 июня 2016

Это просто адаптация 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)
4 голосов
/ 11 февраля 2015

Поскольку 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)
2 голосов
/ 18 сентября 2011

Невозможно сделать это напрямую, но для этого есть обходной путь.Если файлы присутствуют на сервере, реализуйте конечную точку API, которая принимает имя изображения в качестве аргумента и возвращает размер.

Но если файлы находятся на другом сервере, у вас нет другого пути, кромескачать файлы.

1 голос
/ 06 июня 2015

Мой исправленный "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

1 голос
/ 15 января 2015

К сожалению, я не могу комментировать, так что это как ответ:

Используйте запрос 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)

Это исправляет ответ редактора и не имеет других зависимостей (например, ReSeekFile.py).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...