1. ホーム
  2. python

[解決済み] 画像をメモリに読み込まずに画像サイズを取得する

2022-05-29 09:27:05

質問

PILを使用して、以下の方法で画像サイズを取得することができると理解しています。

from PIL import Image
im = Image.open(image_filename)
width, height = im.size

しかし、画像の幅と高さを取得するために を使わずに をメモリに読み込むことなく、画像の幅と高さを取得したいのです。それは可能でしょうか?私は画像サイズの統計をとっているだけで、画像の中身は気にしていません。私はただ、私の処理をより速くしたいだけです。

どのように解決するのですか?

コメントで言及されているように、PILは .open . のドキュメントを見ると PIL 1.1.7 の docstring を見ると .open にはこうあります。

def open(fp, mode="r"):
    "Open an image file, without loading the raster data"

のように、ソースの中にいくつかのファイル操作があります。

 ...
 prefix = fp.read(16)
 ...
 fp.seek(0)
 ...

などがありますが、これらはファイル全体を読んでいるとは言い難いものです。実際 .open は単に成功時にファイルオブジェクトとファイル名を返します。さらに docs は言う。

open(file, mode="r")

与えられた画像ファイルを開き、識別します。

この関数はファイルを識別しますが、実際の画像データはデータを処理するまでファイルから読み込まれません(または、画像ファイルを開くために ロード メソッドを呼び出す) まで、実際の画像データはファイルから読み込まれません。

さらに掘り下げると、以下のようになります。 .open が呼び出す _open を呼び出します。これは、画像フォーマット固有のオーバーロードです。の各実装は _open への実装は、新しいファイルの中で見つけることができます。例えば、.jpeg ファイルは JpegImagePlugin.py . それを深く見てみましょう。

ここでは少し厄介なことが起こっているようです。この中には無限ループがあり、jpegマーカーが見つかるとそこから抜け出すようになっています。

    while True:

        s = s + self.fp.read(1)
        i = i16(s)

        if i in MARKER:
            name, description, handler = MARKER[i]
            # print hex(i), name, description
            if handler is not None:
                handler(self, i)
            if i == 0xFFDA: # start of scan
                rawmode = self.mode
                if self.mode == "CMYK":
                    rawmode = "CMYK;I" # assume adobe conventions
                self.tile = [("jpeg", (0,0) + self.size, 0, (rawmode, ""))]
                # self.__offset = self.fp.tell()
                break
            s = self.fp.read(1)
        elif i == 0 or i == 65535:
            # padded marker or junk; move on
            s = "\xff"
        else:
            raise SyntaxError("no marker found")

これは、次のように見えます。 は、もしそれが不正なものであれば、ファイル全体を読むことができます。しかし、もしそれが情報マーカを読み取るのに問題がなければ、それは早期に脱走するはずです。関数 handler は最終的に self.size を設定し、これが画像の寸法となります。