Ich benutze Python 2.5. Und mit den Standardklassen von Python möchte ich die Bildgröße einer Datei bestimmen.
Ich habe PIL (Python Image Library) gehört, aber es erfordert eine Installation, um zu funktionieren.
Wie kann ich die Größe eines Bildes erhalten, ohne eine externe Bibliothek zu verwenden, nur mit Python 2.5-eigenen Modulen?
Hinweis Ich möchte gängige Bildformate unterstützen, insbesondere JPG und PNG.
python
image
python-2.5
Eros
quelle
quelle
Antworten:
Hier ist ein Python 3-Skript, das ein Tupel zurückgibt, das eine Bildhöhe und -breite für .png, .gif und .jpeg enthält, ohne externe Bibliotheken zu verwenden (dh was Kurt McKee oben erwähnt hat). Sollte relativ einfach sein, es auf Python 2 zu übertragen.
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
quelle
Kurts Antwort musste leicht modifiziert werden, um für mich zu arbeiten.
Erstens auf Ubuntu:
sudo apt-get install python-imaging
Dann:
from PIL import Image im=Image.open(filepath) im.size # (width,height) tuple
Weitere Informationen finden Sie im Handbuch .
quelle
Python Image dimensions
, also +1 von mir für eine Antwort, bei der das Rad nicht neu erfunden werden muss :)Während es möglich ist,
open(filename, 'rb')
die Binärbild-Header aufzurufen und nach den Dimensionen zu durchsuchen, scheint es viel nützlicher zu sein, PIL zu installieren und Ihre Zeit damit zu verbringen, großartige neue Software zu schreiben! Sie erhalten eine bessere Unterstützung für Dateiformate und die Zuverlässigkeit, die sich aus der weit verbreiteten Verwendung ergibt. Aus der PIL-Dokumentation geht hervor , dass der Code, den Sie zur Ausführung Ihrer Aufgabe benötigen würden, folgender wäre:from PIL import Image im = Image.open('filename.png') print 'width: %d - height: %d' % im.size # returns (width, height) tuple
Was das Schreiben von Code selbst betrifft, ist mir kein Modul in der Python-Standardbibliothek bekannt, das das tut, was Sie wollen. Sie müssen
open()
das Bild im Binärmodus bearbeiten und es selbst dekodieren. Sie können über die Formate lesen unter:quelle
Image.open
nicht nurImage
per tjb antworten.Hier finden Sie eine Möglichkeit, die Abmessungen einer PNG-Datei abzurufen, ohne ein Modul eines Drittanbieters zu benötigen. Von 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)
Wenn Sie dies ausführen, wird Folgendes zurückgegeben:
True (x, y)
Ein weiteres Beispiel, das auch den Umgang mit JPEGs umfasst: http://markasread.net/post/17551554979/get-image-size-info-using-pure-python-code
quelle
get_image_info()
, kann man den Dateinamen als Parameter (und nicht als Binärdaten) umgestalten und dann einfachf.read(25)
die Header-Informationen lesen.In Bezug auf die Antwort von Fred the Fantastic :
Nicht jeder JPEG-Marker zwischen
C0
-CF
sindSOF
Marker; Ich habe DHT (C4
), DNL (C8
) und DAC (CC
) ausgeschlossen. Beachten Sie, dass ich nicht untersucht habe, ob es überhaupt möglich ist, andere Frames alsC0
undC2
auf diese Weise zu analysieren . Die anderen scheinen jedoch ziemlich selten zu sein (ich persönlich bin keinem anderen alsC0
und begegnetC2
).In jedem Fall löst dies das Problem, das in den Kommentaren von Malandy mit
Bangles.jpg
(DHT fälschlicherweise als SOF analysiert) erwähnt wurde.Das andere erwähnte Problem
1431588037-WgsI3vK.jpg
besteht darin, dassimghdr
nur die Header APP0 (EXIF) und APP1 (JFIF) erkannt werden können.Dies kann behoben werden, indem imghdr ein lockererer Test hinzugefügt wird (z. B. einfach
FFD8
oder vielleichtFFD8FF
?) Oder etwas viel komplexeres (möglicherweise sogar Datenvalidierung). Bei einem komplexeren Ansatz habe ich nur Probleme gefunden mit: APP14 (FFEE
) (Adobe); der erste Marker ist DQT (FFDB
); und APP2 und Probleme mit eingebetteten ICC_PROFILEs .Der überarbeitete Code unten hat den Aufruf ebenfalls
imghdr.what()
geringfügig geändert :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
Hinweis: Es wurde eine vollständige Antwort anstelle eines Kommentars erstellt, da dies noch nicht zulässig ist.
quelle
Wenn Sie ImageMagick installiert haben, können Sie " Identifizieren " verwenden. Zum Beispiel können Sie es so nennen:
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(',') ]
quelle
width, height = list( map( int, dim.decode('utf-8').strip('"').split(',')))
In einem anderen Stackoverflow-Beitrag eine gute Lösung gefunden (nur mit Standardbibliotheken + auch mit JPG ): JohnTESlade-Antwort
Und eine andere Lösung (der schnelle Weg) für diejenigen, die es sich leisten können , den Befehl ' file ' in Python auszuführen, führen Sie Folgendes aus:
import os info = os.popen("file foo.jpg").read() print info
Ausgabe :
foo.jpg: JPEG image data...density 28x28, segment length 16, baseline, precision 8, 352x198, frames 3
Jetzt müssen Sie nur noch die Ausgabe formatieren, um die Abmessungen zu erfassen. 352x198 in meinem Fall.
quelle
Dieser Code erfüllt zwei Dinge:
Abrufen der Bildgröße
Finden Sie den tatsächlichen EOF einer JPG-Datei
Nun, beim googeln war ich mehr an dem späteren interessiert. Die Aufgabe bestand darin, eine JPG-Datei aus einem Datenstrom auszuschneiden. Da ich keine Möglichkeit gefunden habe, Pythons 'Bild' zu verwenden, um den EOF einer solchen JPG-Datei zu erhalten, habe ich mir das ausgedacht.
Interessante Dinge / Änderungen / Notizen in diesem Beispiel:
Erweitern der normalen Python-Dateiklasse mit der Methode uInt16, um den Quellcode besser lesbar und wartbar zu machen. Wenn Sie mit struct.unpack () herumspielen, sieht der Code schnell hässlich aus
Ersetzt durch "uninteressante" Bereiche / Chunk durch Suchen
Wenn Sie nur die Abmessungen erhalten möchten, können Sie die Linie entfernen:
hasChunk = ord(byte) not in range( 0xD0, 0xDA) + [0x00]
-> da dies nur beim Lesen des Bilddatenblocks und Kommentierens wichtig wird
#break
aufhören zu lesen, sobald die Dimension gefunden wurde. ... aber lächle was ich erzähle - du bist der Kodierer;)
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()
quelle
Es hängt von der Ausgabe der Datei ab, von der ich nicht sicher bin, ob sie auf allen Systemen standardisiert ist. Einige JPEGs geben die Bildgröße nicht an
import subprocess, re image_size = list(map(int, re.findall('(\d+)x(\d+)', subprocess.getoutput("file" + filename))[-1]))
quelle
Stolperte über dieses, aber Sie können es erhalten, indem Sie das Folgende verwenden, solange Sie numpy importieren.
import numpy as np [y, x] = np.shape(img[:,:,0])
Es funktioniert, weil Sie alle bis auf eine Farbe ignorieren und das Bild dann nur noch 2D ist. Die Form gibt also an, wie hoch das Gebot ist. Python ist noch ein bisschen neu, scheint aber eine einfache Möglichkeit zu sein.
quelle