Obtén el tamaño de la imagen sin descargarla en Python

¿Cómo puedo obtener las dimensiones de la imagen sin descargarla realmente? ¿Es incluso posible? Tengo una lista de urls de imágenes y quiero asignarle ancho y tamaño.

Sé que hay una forma de hacerlo localmente ( ¿Cómo verificar las dimensiones de todas las imágenes en un directorio usando python? ), Pero no quiero descargar todas las imágenes.

Editar:

Siguiente ed. Sugerencias, edité el código. Se me ocurrió este código . No estoy seguro de que el tiempo descargue el archivo completo o solo una parte (como quería).

Esto se basa en la respuesta de ed mezclada con otras cosas que encontré en la web. Me encontré con el mismo problema que los grotos con .read (24). Descargue getimageinfo.py desde aquí y descargue ReSeekFile.py desde aquí .

import urllib2 imgdata = urllib2.urlopen(href) image_type,width,height = getimageinfo.getImageInfo(imgdata) 

Modificar getimageinfo como tal …

 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 

Encontré la solución en este sitio para funcionar bien:

 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)) 

Si está dispuesto a descargar los primeros 24 bytes de cada archivo, entonces esta función (mencionada en la respuesta de johnteslade a la pregunta que menciona) resolverá las dimensiones.

Es probablemente la descarga mínima necesaria para hacer el trabajo que deseas.

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

Editar (1):

En el caso de archivos jpeg parece necesitar más bytes. Puede editar la función para que, en lugar de leer un StringIO.StringIO (datos), lea el identificador del archivo desde urlopen. Luego leerá exactamente la cantidad de imagen que necesite para averiguar el ancho y la altura.

Dado que getimageinfo.py mencionado anteriormente no funciona en Python3. Se usa almohada en lugar de ella.

La almohada se puede encontrar en pypi , o se puede instalar utilizando la pip install pillow pip: pip install pillow .


 desde io import BytesIO
 desde PIL importar imagen
 solicitudes de importación
 hrefs = ['http://sofes.miximages.com/image/15008518202_b016d7d289_m.jpg','http://sofes.miximages.com/image/15008465772_383e697089_m.jpg','https://farm4.staticflickr.com/ 3902 / 14985871946_86abb8c56f_m.jpg ']
 RANGO = 5000
 para href en hrefs:
     req = requests.get (href, headers = {'User-Agent': 'Mozilla5.0 (araña de Google)', 'Range': 'bytes = 0 - {}'. format (RANGE)})
     im = Image.open (BytesIO (req.content))

     imprimir (im.size)

Me gusta esta solución que encontré, que descarga fragmentos de la imagen hasta que PIL la reconoce como un archivo de imagen y luego detiene la descarga. Esto asegura que se descargue suficiente encabezado de imagen para leer las dimensiones, pero no más. (Encontré esto aquí y aquí ; lo he adaptado para 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 

No es posible hacerlo directamente, pero hay una solución para eso. Si los archivos están presentes en el servidor, implemente el punto final de la API que toma el nombre de la imagen como un argumento y devuelve el tamaño.

Pero si los archivos están en un servidor diferente, no tienes más remedio que descargar los archivos.

Desafortunadamente no puedo comentar, así que esto es como una respuesta:

Utilice una consulta de obtención con el encabezado

 "Range": "bytes=0-30" 

Y luego simplemente use

http://code.google.com/p/bfg-pages/source/browse/trunk/pages/getimageinfo.py

Si usas “peticiones” de python, es simplemente

 r = requests.get(image_url, headers={ "Range": "bytes=0-30" }) image_info = get_image_info(r.content) 

Esto corrige la respuesta de ed. Y no tiene otras dependencias (como ReSeekFile.py).

Mi arreglo “getimageInfo.py”, funciona con Python 3.4+, pruébalo, ¡simplemente genial!

 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"= 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://sofes.miximages.com/image/15008518202_b016d7d289_m.jpg','http://sofes.miximages.com/image/15008465772_383e697089_m.jpg','http://sofes.miximages.com/image/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://sofes.miximages.com/image/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())) 

Código fuente: http://code.google.com/p/bfg-pages/source/browse/trunk/pages/getimageinfo.py