paquetes - todas las librerias de python




¿Cómo obtener el tamaño de imagen usando la clase estándar de Python(sin usar una biblioteca externa)? (6)

Aquí hay una manera de obtener las dimensiones de un archivo png sin necesidad de un módulo de terceros. Desde http://coreygoldberg.blogspot.com/2013/01/python-verify-png-file-and-get-image.html

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 ejecutas esto, volverá:

True
(x, y)

Y otro ejemplo que incluye el manejo de archivos JPEG también: http://markasread.net/post/17551554979/get-image-size-info-using-pure-python-code

Estoy usando Python 2.5. Y usando las clases estándar de Python, quiero determinar el tamaño de la imagen de un archivo.

He escuchado PIL (Biblioteca de imágenes de Python), pero requiere que la instalación funcione.

¿Cómo puedo obtener el tamaño de una imagen sin usar ninguna biblioteca externa, solo usando los módulos de Python 2.5?

Tenga en cuenta que quiero admitir formatos de imagen comunes, particularmente JPG y PNG.


Aquí hay una secuencia de comandos de python 3 que devuelve una tupla que contiene una altura y un ancho de imagen para .png, .gif y .jpeg sin utilizar ninguna biblioteca externa (es decir, a qué se refirió Kurt McKee anteriormente). 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

Encontré una buena solución en otra publicación de (usando solo librerías estándar + que tratan con jpg también): Respuesta de JohnTESlade

Y otra solución (la forma más rápida) para aquellos que pueden permitirse ejecutar el comando ' file ' dentro de python, ejecute:

import os
info = os.popen("file foo.jpg").read()
print info

Salida :

foo.jpg: JPEG image data...density 28x28, segment length 16, baseline, precision 8, 352x198, frames 3

Todo lo que tienes que hacer ahora es formatear la salida para capturar las dimensiones. 352x198 en mi caso.


Ese código logra 2 cosas:

  • Obtener la dimensión de la imagen

  • Encuentra el EOF real de un archivo jpg

Bueno, cuando busqué en Google, estaba más interesado en el posterior. La tarea era cortar un archivo jpg de un flujo de datos. Dado que II no encontró ninguna forma de usar la imagen de Pythons para obtener el EOF de modo que jpg-File lo inventé.

Cosas / cambios / notas interesantes en esta muestra:

  • ampliando la clase de archivo Python normal con el método uInt16, haciendo que el código fuente sea más legible y mantenible. Jugar con struct.unpack () rápidamente hace que el código se vea feo

  • Se reemplazó la lectura de áreas / fragmentos insatisfactorios con búsqueda

  • En caso de que quiera obtener las dimensiones, puede eliminar la línea:

    hasChunk = ord(byte) not in range( 0xD0, 0xDA) + [0x00] 
    

    -> ya que eso solo es importante cuando se lee el fragmento de datos de la imagen y se comenta

    #break
    

    para dejar de leer tan pronto como se encuentre la dimensión. ... pero sonría lo que estoy diciendo, usted es el codificador;)

      import struct
      import io,os
    
      class myFile(file):
    
          def byte( self ):
               return file.read( self,  1);
    
          def uInt16( self ):
               tmp = file.read( self,  2)
               return struct.unpack( ">H", tmp )[0];
    
      jpeg = myFile('grafx_ui.s00_\\08521678_Unknown.jpg', 'rb')
    
      try:
          height = -1
          width  = -1
          EOI    = -1
    
          type_check = jpeg.read(2)
          if type_check != b'\xff\xd8':
            print("Not a JPG")
    
          else:
    
            byte = jpeg.byte()
    
            while byte != b"":
    
              while byte != b'\xff': byte = jpeg.byte()
              while byte == b'\xff': byte = jpeg.byte()
    
    
              # FF D8       SOI Start of Image
              # FF D0..7  RST DRI Define Restart Interval inside CompressedData
              # FF 00           Masked FF inside CompressedData
              # FF D9       EOI End of Image
              # http://en.wikipedia.org/wiki/JPEG#Syntax_and_structure
              hasChunk = ord(byte) not in range( 0xD0, 0xDA) + [0x00]
              if hasChunk:
                   ChunkSize   =  jpeg.uInt16()  - 2
                   ChunkOffset =  jpeg.tell()
                   Next_ChunkOffset = ChunkOffset + ChunkSize
    
    
              # Find bytes \xFF \xC0..C3 That marks the Start of Frame
              if (byte >= b'\xC0' and byte <= b'\xC3'):
    
                # Found  SOF1..3 data chunk - Read it and quit
                jpeg.seek(1, os.SEEK_CUR)
                h = jpeg.uInt16()
                w = jpeg.uInt16()
    
    
                #break
    
    
              elif (byte == b'\xD9'):
                   # Found End of Image
                   EOI = jpeg.tell()
                   break
              else:
                  # Seek to next data chunk
                 print "Pos: %.4x %x" % (jpeg.tell(), ChunkSize)
    
              if hasChunk:       
                 jpeg.seek(Next_ChunkOffset)
    
              byte = jpeg.byte()
    
            width  = int(w)
            height = int(h)
    
            print("Width: %s, Height: %s  JpgFileDataSize: %x" % (width, height, EOI))
      finally:
          jpeg.close()
    

Si bien es posible llamar a open(filename, 'rb') y verificar a través de los encabezados de las imágenes binarias las dimensiones, ¡parece mucho más útil instalar PIL y dedicar mucho tiempo a la creación de un excelente software nuevo! Obtiene mayor soporte de formato de archivo y la confiabilidad que proviene del uso generalizado. De la documentación de PIL , parece que el código que necesitaría para completar su 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 quiera. Deberá open() la imagen en modo binario y comenzar a decodificarla usted mismo. Puede leer sobre los formatos en:


Si tiene instalado ImageMagick , puede usar ' identify '. Por ejemplo, puede 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(',') ]




python-2.5