Eros
Estoy usando Python 2.5. Y usando las clases estándar de Python, quiero determinar el tamaño de imagen de un archivo.
He oído PIL (Biblioteca de imágenes de Python), pero requiere instalación para funcionar.
¿Cómo podría obtener el tamaño de una imagen sin usar ninguna biblioteca externa, solo usando los propios módulos de Python 2.5?
Tenga en cuenta que quiero admitir formatos de imagen comunes, particularmente JPG y PNG.
Fred el fantástico
Aquí hay una secuencia de comandos de Python 3 que devuelve una tupla que contiene la altura y el ancho de una imagen para .png, .gif y .jpeg sin usar ninguna biblioteca externa (es decir, a lo que hace referencia Kurt McKee). Debería ser relativamente fácil transferirlo a Python 2.
import struct
import imghdr
def get_image_size(fname):
'''Determine the image type of fhandle and return its size.
from draco'''
with open(fname, 'rb') as fhandle:
head = fhandle.read(24)
if len(head) != 24:
return
if imghdr.what(fname) == 'png':
check = struct.unpack('>i', head[4:8])[0]
if check != 0x0d0a1a0a:
return
width, height = struct.unpack('>ii', head[16:24])
elif imghdr.what(fname) == 'gif':
width, height = struct.unpack('<HH', head[6:10])
elif imghdr.what(fname) == 'jpeg':
try:
fhandle.seek(0) # Read 0xff next
size = 2
ftype = 0
while not 0xc0 <= ftype <= 0xcf:
fhandle.seek(size, 1)
byte = fhandle.read(1)
while ord(byte) == 0xff:
byte = fhandle.read(1)
ftype = ord(byte)
size = struct.unpack('>H', fhandle.read(2))[0] - 2
# We are at a SOFn block
fhandle.seek(1, 1) # Skip `precision' byte.
height, width = struct.unpack('>HH', fhandle.read(4))
except Exception: #IGNORE:W0703
return
else:
return
return width, height
-
Su código funcionó mayormente así en 2.7.3. Tuve que reescribirlo porque ya tenía un archivo como objeto.
– xZise
12 de febrero de 2014 a las 22:12
-
-
Y con este.que debería devolver (640,480), pero obtengo (1281, 1).
– Enfermedad
6 de diciembre de 2015 a las 15:44
-
Probé solo la parte PNG de esto, pero al menos funciona bien.
– tembloroso
20/04/2016 a las 21:34
-
la imagen proporcionada por @Malandy es una línea de base DCT JEPG imagen, no una imagen compatible con ICC/IPTC/JFIF.
– Mitoxis
10 de mayo de 2018 a las 7:11
tjb
La respuesta de Kurt necesitaba ser ligeramente modificada para que funcionara para mí.
Primero, en ubuntu: sudo apt-get install python-imaging
Entonces:
from PIL import Image
im = Image.open(filepath)
im.size # (width,height) tuple
Verificar el manual para más información.
-
No responde a la pregunta: “¿(sin usar una biblioteca externa)?” se especifica en el título, y la pregunta luego se aclara con “He escuchado PIL (Biblioteca de imágenes de Python), pero requiere instalar la biblioteca”.
– Luna
16/07/2014 a las 22:00
-
@RossAllan: Claro, pero esta pregunta es la número 1 en Google para variantes de
Python Image dimensions
así que +1 de mí para una respuesta que no necesita reinventar la rueda 🙂– Clemente
1 de marzo de 2016 a las 7:20
bautista
Esta es una forma de obtener las dimensiones de un archivo PNG sin necesidad de un módulo de terceros. De Python: verifique un archivo PNG y obtenga las dimensiones de la imagen:
import struct
def get_image_info(data):
if is_png(data):
w, h = struct.unpack('>LL', data[16:24])
width = int(w)
height = int(h)
else:
raise Exception('not a png image')
return width, height
def is_png(data):
return (data[:8] == '\211PNG\r\n\032\n'and (data[12:16] == 'IHDR'))
if __name__ == '__main__':
with open('foo.png', 'rb') as f:
data = f.read()
print is_png(data)
print get_image_info(data)
Cuando ejecutes esto, te devolverá:
True
(x, y)
Y otro ejemplo que también incluye el manejo de archivos JPEG:
http://markasread.net/post/17551554979/get-image-size-info-using-pure-python-code
-
¿No es un poco ineficiente leer los datos completos de la imagen si todo lo que necesita son los datos del encabezado?
– Adam Parkin
25 de mayo de 2015 a las 2:46
-
Para evitar eso, uno puede refactorizar
get_image_info()
para tomar el nombre del archivo como un parámetro (en lugar de los datos binarios), y luego simplemente hacer unf.read(25)
para leer la información del encabezado solamente.– Adam Parkin
25 de mayo de 2015 a las 3:23
-
El último enlace está roto: “¡Vaya! Esa página no se puede encontrar”.
-Peter Mortensen
hace 2 días
Kurt Mckee
Si bien es posible llamar open(filename, 'rb')
y verifique las dimensiones de los encabezados de imágenes binarias, ¡parece mucho más útil instalar PIL y dedicar su tiempo a escribir un software nuevo y excelente! Obtiene una mayor compatibilidad con el formato de archivo y la confiabilidad que proviene del uso generalizado. De la documentación PILparece que el código que necesitarías para completar tu tarea sería:
from PIL import Image
im = Image.open('filename.png')
print 'width: %d - height: %d' % im.size # returns (width, height) tuple
En cuanto a escribir código usted mismo, no conozco un módulo en la biblioteca estándar de Python que haga lo que usted quiere. Tendrás que open()
la imagen en modo binario y comience a decodificarla usted mismo. Puede leer sobre los formatos en:
Dagh Bunnstad
Acerca de Fred el fantásticorespuesta de:
No todos los marcadores JPEG entre C0
–CF
son SOF
marcadores; Excluí DHT (C4
), DNL (C8
) y CAD (CC
). Tenga en cuenta que no he investigado si es posible analizar cualquier marco que no sea C0
y C2
de esta forma. Sin embargo, los otros parecen ser bastante raros (personalmente no he encontrado ninguno más que C0
y C2
).
De cualquier manera, esto resuelve el problema mencionado en los comentarios de Malandy con Bangles.jpg
(DHT analizado erróneamente como SOF).
El otro problema mencionado con 1431588037-WgsI3vK.jpg
Es debido a imghdr
solo pudiendo detectar los encabezados APP0 (EXIF) y APP1 (JFIF).
Esto se puede solucionar agregando una prueba más laxa a imghdr (por ejemplo, simplemente FFD8
o tal vez FFD8FF
?) o algo mucho más complejo (posiblemente incluso la validación de datos). Con un enfoque más complejo, solo encontré problemas con: APP14 (FFEE
) (Adobe); siendo el primer marcador DQT (FFDB
); y APP2 y problemas con ICC_PROFILE incrustados.
Código revisado a continuación, también modificó la llamada a imghdr.what()
levemente:
import struct
import imghdr
def test_jpeg(h, f):
# SOI APP2 + ICC_PROFILE
if h[0:4] == '\xff\xd8\xff\xe2' and h[6:17] == b'ICC_PROFILE':
print "A"
return 'jpeg'
# SOI APP14 + Adobe
if h[0:4] == '\xff\xd8\xff\xee' and h[6:11] == b'Adobe':
return 'jpeg'
# SOI DQT
if h[0:4] == '\xff\xd8\xff\xdb':
return 'jpeg'
imghdr.tests.append(test_jpeg)
def get_image_size(fname):
'''Determine the image type of fhandle and return its size.
from draco'''
with open(fname, 'rb') as fhandle:
head = fhandle.read(24)
if len(head) != 24:
return
what = imghdr.what(None, head)
if what == 'png':
check = struct.unpack('>i', head[4:8])[0]
if check != 0x0d0a1a0a:
return
width, height = struct.unpack('>ii', head[16:24])
elif what == 'gif':
width, height = struct.unpack('<HH', head[6:10])
elif what == 'jpeg':
try:
fhandle.seek(0) # Read 0xff next
size = 2
ftype = 0
while not 0xc0 <= ftype <= 0xcf or ftype in (0xc4, 0xc8, 0xcc):
fhandle.seek(size, 1)
byte = fhandle.read(1)
while ord(byte) == 0xff:
byte = fhandle.read(1)
ftype = ord(byte)
size = struct.unpack('>H', fhandle.read(2))[0] - 2
# We are at a SOFn block
fhandle.seek(1, 1) # Skip `precision' byte.
height, width = struct.unpack('>HH', fhandle.read(4))
except Exception: #IGNORE:W0703
return
else:
return
return width, height
Nota: Creé una respuesta completa en lugar de un comentario, ya que todavía no tengo permiso para hacerlo.
jensph
Si tienes imagenmagia instalado, entonces puede usar ‘identificar‘. Por ejemplo, puedes llamarlo así:
path = "//folder/image.jpg"
dim = subprocess.Popen(["identify","-format","\"%w,%h\"",path], stdout=subprocess.PIPE).communicate()[0]
(width, height) = [ int(x) for x in re.sub('[\t\r\n"]', '', dim).split(',') ]
Pedro Mortensen
Encontré una buena solución en otra publicación de Stack Overflow (usando solo bibliotecas estándar + también tratando con JPEG): respuesta de JohnTESlade
Y otra solución (la forma rápida) para aquellos que pueden permitirse ejecutar el ‘archivo‘ dentro del intérprete de Python, ejecute:
import os
info = os.popen("file foo.jpg").read()
print info
Producción:
foo.jpg: JPEG image data...density 28x28, segment length 16, baseline, precision 8, 352x198, frames 3
Todo lo que tiene que hacer ahora es formatear la salida para capturar las dimensiones. 352×198 en mi caso.
alguna sugerencia de que formato de la imagen que desea saber el tamaño de?
– Larry Lustig
7 de noviembre de 2011 a las 4:13
formatos de imagen comunes (PNG y JPG)
– eros
7 de noviembre de 2011 a las 4:25
Vea mi respuesta en otra pregunta si no le importa usar bibliotecas externas (pero de uso común)
– Martín Tomas
7 de marzo de 2017 a las 8:52