Python 2.5を使用しています。そして、Pythonの標準クラスを使用して、ファイルの画像サイズを決定したいと思います。
PIL(Python Image Library)を聞いたことがありますが、動作させるにはインストールが必要です。
Python 2.5独自のモジュールを使用して、外部ライブラリを使用せずに画像のサイズを取得するにはどうすればよいですか?
注一般的な画像形式、特にJPGとPNGをサポートしたい。
外部ライブラリを使用せずに.png、.gif、および.jpegの画像の高さと幅を含むTupleを返すpython 3スクリプトです(つまり、Kurt McKeeが上記で参照したもの)。 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
Kurtsの答えは、私のために機能するように少し修正する必要がありました。
まず、ubuntuで:Sudo apt-get install python-imaging
次に:
from PIL import Image
im=Image.open(filepath)
im.size # (width,height) Tuple
詳しくは handbook をご覧ください。
open(filename, 'rb')
を呼び出して、ディメンションのバイナリイメージヘッダーを確認することは可能ですが、PILをインストールして、すばらしい新しいソフトウェアを作成するのに時間を費やす方がはるかに便利です。幅広いファイル形式のサポートと、広範な使用による信頼性が得られます。 PILドキュメントから の場合、タスクを完了するために必要なコードは次のようになります。
from PIL import Image
im = Image.open('filename.png')
print 'width: %d - height: %d' % im.size # returns (width, height) Tuple
自分でコードを書くことに関しては、あなたが望むことをするPython標準ライブラリのモジュールを知りません。バイナリモードで画像をopen()
し、自分でデコードを開始する必要があります。形式については、次のサイトで読むことができます。
サードパーティのモジュールを必要とせずに、PNGファイルのサイズを取得する方法を次に示します。から 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 __== '__main__':
with open('foo.png', 'rb') as f:
data = f.read()
print is_png(data)
print get_image_info(data)
これを実行すると、以下が返されます。
True
(x, y)
また、JPEGの処理を含む別の例: http://markasread.net/post/17551554979/get-image-size-info-using-pure-python-code
C0
-CF
間のすべてのJPEGマーカーがSOF
マーカーではありません。 DHT(C4
)、DNL(C8
)、DAC(CC
)を除外しました。この方法でC0
およびC2
以外のフレームを解析することさえ可能かどうかは検討していないことに注意してください。ただし、他のものはかなりまれであるようです(私は個人的にC0
とC2
以外に遭遇していません)。
いずれにしても、これはコメントで言及された問題をMalandyでBangles.jpg
(DHTが誤ってSOFとして解析された)で解決します。
1431588037-WgsI3vK.jpg
で言及されている他の問題は、imghdr
がAPP0(EXIF)およびAPP1(JFIF)ヘッダーのみを検出できるためです。
これはimghdrにもっと緩いテスト(たとえば、単にFFD8
または多分FFD8FF
?)を追加するか、もっと複雑なもの(おそらくデータ検証さえ)を追加することで修正できます。より複雑なアプローチでは、次の問題のみが見つかりました:APP14(FFEE
)(Adobe);最初のマーカーはDQT(FFDB
)です;およびAPP2および ICC_PROFILEが埋め込まれている場合の問題 。
以下のコードを修正し、imghdr.what()
への呼び出しも少し変更しました:
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
注:まだ許可されていないため、コメントではなく完全な回答を作成しました。
ImageMagick がインストールされている場合は、「 identify 」を使用できます。たとえば、次のように呼び出すことができます。
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(',') ]
このコードは2つのことを実現します。
画像寸法を取得する
実際のEOFを見つける jpgファイルの
グーグルのときは、後者のほうに興味がありました。タスクは、データストリームからjpgファイルを切り出すことでした。 Pythonの「イメージ」を使用してjpgファイルのEOFを取得する方法を見つけられなかったので、これを作成しました。
このサンプルの興味深いこと/ changes/notes:
通常のPythonファイルクラスをuInt16メソッドで拡張し、ソースコードを読みやすく保守しやすくします。 struct.unpack()をいじってみると、コードがすぐに見苦しくなります
「関心のない」領域/チャンクの読み取りをシークに置き換えました
寸法を取得したい場合は、次の行を削除できます。
hasChunk = ord(byte) not in range( 0xD0, 0xDA) + [0x00]
->画像データチャンクを読み取ってコメントするときにのみ重要になるため
#break
ディメンションが見つかったらすぐに読み上げを停止します。 ...しかし、smile私が言っていること-あなたはコーダーです;)
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()
別のStackoverflow投稿でNiceソリューションを見つけました(標準ライブラリのみを使用し、jpgも処理します): JohnTESlade answer
そして、Pythonで「file」コマンドを実行する余裕がある人のための別の解決策(簡単な方法):
import os
info = os.popen("file foo.jpg").read()
print info
出力:
foo.jpg: JPEG image data...density 28x28, segment length 16, baseline, precision 8, 352x198, frames 3
今やらなければならないのは、出力をフォーマットしてディメンションをキャプチャすることです。 352x198私の場合。
ファイルの出力に依存しますが、すべてのシステムで標準化されているかどうかはわかりません。一部のJPEGは画像サイズを報告しません
import subprocess, re
image_size = list(map(int, re.findall('(\d+)x(\d+)', subprocess.getoutput("file" + filename))[-1]))