独自の画像プラグインの作成¶
Pillow はプラグインモデルを使用しており、ライブラリ自体を変更することなく、独自のデコーダーとエンコーダーをライブラリに追加できます。このようなプラグインの通常の名前は XxxImagePlugin.py
のようになります。ここで Xxx
は一意の形式名 (通常は略語) です。
警告
Pillow >= 2.1.0 では、ImagePlugin.py
で終わる名前の Python パス内のファイルは自動的にインポートされなくなりました。画像プラグインを手動でインポートする必要があります。
Pillow はファイルを 2 つの段階でデコードします
ロードされた順序で利用可能な画像プラグインをループ処理し、ファイルの最初の 16 バイトを使用してプラグインの
_accept
関数を呼び出します。_accept
関数が true を返した場合、プラグインの_open
メソッドが呼び出されて、画像メタデータと画像タイルが設定されます。_open
メソッドは、実際の画像データをデコードするためのものではありません。画像データが要求されると、
ImageFile.load
メソッドが呼び出され、各タイルのデコーダーを設定して、データがデコーダーに供給されます。
画像プラグインには、PIL.ImageFile.ImageFile
基本クラスから派生したフォーマットハンドラーが含まれている必要があります。このクラスは、ファイルヘッダーを読み取り、少なくとも内部 _size
および _mode
属性を設定する _open
メソッドを提供して、mode
と size
が設定されるようにする必要があります。ファイルをロードできるようにするには、メソッドで tile
記述子のリストを作成する必要もあります。この記述子には、デコーダー名、タイルの範囲、およびデコーダー固有のデータが含まれます。フォーマットハンドラークラスは、Image
モジュールへの呼び出しを介して、明示的に登録する必要があります。
注
パフォーマンス上の理由から、_open
メソッドが、適切なコンテンツを持たないファイルをすばやく拒否することが重要です。
例¶
次のプラグインは、128 バイトのヘッダーを持つ単純な形式をサポートしています。ヘッダーは、単語 “SPAM” の後に、幅、高さ、およびピクセルサイズ (ビット単位) で構成されています。ヘッダーフィールドはスペースで区切られています。画像データは、ヘッダーの直後に続き、バイレベル、グレースケール、または 24 ビットのトゥルーカラーにすることができます。
SpamImagePlugin.py:
from PIL import Image, ImageFile
def _accept(prefix: bytes) -> bool:
return prefix[:4] == b"SPAM"
class SpamImageFile(ImageFile.ImageFile):
format = "SPAM"
format_description = "Spam raster image"
def _open(self) -> None:
header = self.fp.read(128).split()
# size in pixels (width, height)
self._size = int(header[1]), int(header[2])
# mode setting
bits = int(header[3])
if bits == 1:
self._mode = "1"
elif bits == 8:
self._mode = "L"
elif bits == 24:
self._mode = "RGB"
else:
msg = "unknown number of bits"
raise SyntaxError(msg)
# data descriptor
self.tile = [ImageFile._Tile("raw", (0, 0) + self.size, 128, (self.mode, 0, 1))]
Image.register_open(SpamImageFile.format, SpamImageFile, _accept)
Image.register_extensions(
SpamImageFile.format,
[
".spam",
".spa", # DOS version
],
)
フォーマットハンドラーは、size
および mode
が設定されるように、常に内部 _size
および _mode
属性を設定する必要があります。これらが設定されていない場合、ファイルを開くことはできません。プラグインを簡略化するために、呼び出しコードは、SyntaxError
、KeyError
、IndexError
、EOFError
、および struct.error
などの例外を、ファイルの識別失敗と見なします。
画像プラグインは、PIL.Image.register_open()
を使用して明示的に登録する必要があることに注意してください。必須ではありませんが、この形式で使用される拡張子を登録することも良い考えです。
プラグインがインポートされると、使用できます
from PIL import Image
import SpamImagePlugin
with Image.open("hopper.spam") as im:
pass
tile
属性¶
ファイルを識別するだけでなく、読み取ることもできるようにするには、tile
属性も設定する必要があります。この属性は、タイル記述子のリストで構成されます。各記述子では、画像内の特定の領域にデータをロードする方法を指定します。
ほとんどの場合、画像全体をカバーする単一の記述子のみが使用されます。PsdImagePlugin.PsdImageFile
は、チャネルが 1 つずつ連続して保存されているため、単一レイヤー内のチャネルを結合するために複数のタイルを使用します。
タイル記述子は、次の内容を持つ 4 タプルです
(decoder, region, offset, parameters)
フィールドは次のように使用されます
- デコーダー
使用するデコーダーを指定します。ここで使用される
raw
デコーダーは、さまざまなピクセル形式の非圧縮データをサポートします。このデコーダーの詳細については、以下の説明を参照してください。Cデコーダーのリストは、
_imaging.c
の関数配列の codecs セクションにあります。Python デコーダーは、関連するプラグイン内で登録されています。- region
画像内のデータを格納する場所を指定する4タプル。
- offset
ファイル先頭から画像データまでのバイトオフセット。
- parameters
デコーダーへのパラメーター。このフィールドの内容は、タイル記述子タプルの最初のフィールドで指定されたデコーダーによって異なります。デコーダーがパラメーターを必要としない場合は、このフィールドに
None
を使用します。
tile
属性には、単一の記述子だけでなく、タイル記述子のリストが含まれていることに注意してください。
デコーダー¶
raw デコーダー¶
raw
デコーダーは、画像ファイルから非圧縮データを読み取るために使用されます。PPM、BMP、非圧縮TIFFなど、ほとんどの非圧縮ファイル形式で使用できます。PIL.Image.frombytes()
関数で raw デコーダーを使用するには、次の構文を使用します
image = Image.frombytes(
mode, size, data, "raw",
raw_mode, stride, orientation
)
タイル記述子で使用する場合、パラメーターフィールドは次のようになります。
(raw_mode, stride, orientation)
フィールドは次のように使用されます
- raw_mode
ファイルで使用されるピクセルレイアウトであり、データを PIL の内部レイアウトに適切に変換するために使用されます。利用可能な形式の概要については、以下の表を参照してください。
- stride
画像内の連続する2行の間のバイト単位の距離。0の場合、画像はパックされている(行間にパディングがない)と見なされます。省略した場合、ストライドはデフォルトで0になります。
- orientation
画像内の最初の行が画面上の最上行(1)か、最下行(-1)か。省略した場合、向きはデフォルトで1になります。
raw モードフィールドは、PIL の内部ピクセルレイアウトに一致するようにデータをどのようにアンパックするかを決定するために使用されます。PIL は多数の raw モードをサポートしています。完全なリストについては、Unpack.c
モジュールの表を参照してください。次の表は、一般的な raw モードをいくつか説明しています。
mode |
説明 |
---|---|
|
1ビットのバイレベルで、最上位ビットに左端のピクセルが格納されます。
0は黒、1は白を意味します。
|
|
1ビットの反転バイレベルで、最上位ビットに左端のピクセルが格納されます。
0は白、1は黒を意味します。
|
|
1ビットの反転バイレベルで、最下位ビットに左端のピクセルが格納されます。
0は黒、1は白を意味します。
|
|
8ビットのグレースケール。0は黒、255は白を意味します。 |
|
8ビットの反転グレースケール。0は白、255は黒を意味します。 |
|
8ビットのパレットマップされた画像。 |
|
24ビットのトゥルーカラーで、(赤、緑、青)として格納されます。 |
|
24ビットのトゥルーカラーで、(青、緑、赤)として格納されます。 |
|
24ビットのトゥルーカラーで、(赤、緑、青、パッド)として格納されます。パッド
ピクセルは異なる場合があります。
|
|
24ビットのトゥルーカラーで、ラインインターリーブされます(最初にすべての赤ピクセル、次に
すべての緑ピクセル、最後にすべての青ピクセル)。
|
ほとんどの場合、raw モードは単純にモードと同じであることに注意してください。
Python Imaging Library は、JPEG、PNG、PackBits など、他の多くのデコーダーをサポートしています。詳細については、decode.c
ソースファイル、およびライブラリに付属の標準プラグイン実装を参照してください。
浮動小数点データのデコード¶
PIL は、さまざまな形式をモード F
(浮動小数点)イメージメモリにロードできる特別なメカニズムを提供します。
raw
デコーダーを使用して、次のいずれかの raw モードを使用して、標準のマシンデータ型でデータがパックされた画像を読み取ることができます。
mode |
説明 |
---|---|
|
32ビットのネイティブ浮動小数点。 |
|
8ビットの符号なし整数。 |
|
8ビットの符号付き整数。 |
|
16ビットのリトルエンディアン符号なし整数。 |
|
16ビットのリトルエンディアン符号付き整数。 |
|
16ビットのビッグエンディアン符号なし整数。 |
|
16ビットのビッグエンディアン符号付き整数。 |
|
16ビットのネイティブ符号なし整数。 |
|
16ビットのネイティブ符号付き整数。 |
|
32ビットのリトルエンディアン符号なし整数。 |
|
32ビットのリトルエンディアン符号付き整数。 |
|
32ビットのビッグエンディアン符号なし整数。 |
|
32ビットのビッグエンディアン符号付き整数。 |
|
32ビットのネイティブ符号なし整数。 |
|
32ビットのネイティブ符号付き整数。 |
|
32ビットのリトルエンディアン浮動小数点。 |
|
32ビットのビッグエンディアン浮動小数点。 |
|
32ビットのネイティブ浮動小数点。 |
|
64ビットのリトルエンディアン浮動小数点。 |
|
64ビットのビッグエンディアン浮動小数点。 |
|
64ビットのネイティブ浮動小数点。 |
bit デコーダー¶
raw デコーダーが形式を処理できない場合、PIL は、さまざまなパック形式を浮動小数点イメージメモリに読み込むために使用できる特別な「bit」デコーダーも提供します。
PIL.Image.frombytes()
関数で bit デコーダーを使用するには、次の構文を使用します。
image = Image.frombytes(
mode, size, data, "bit",
bits, pad, fill, sign, orientation
)
タイル記述子で使用する場合、パラメーターフィールドは次のようになります。
(bits, pad, fill, sign, orientation)
フィールドは次のように使用されます
- bits
ピクセルあたりのビット数 (2-32)。デフォルトはありません。
- pad
行間のパディング(ビット単位)。パディングがない場合は0、行がフルバイトにパディングされている場合は8です。省略した場合、pad 値はデフォルトで8になります。
- fill
デコーダービットバッファーへのデータの追加方法と保存方法を制御します。
- fill=0
デコーダーバッファーの LSB 端にバイトを追加します。MSB 端からピクセルを保存します。
- fill=1
デコーダーバッファーの MSB 端にバイトを追加します。MSB 端からピクセルを保存します。
- fill=2
デコーダーバッファーの LSB 端にバイトを追加します。LSB 端からピクセルを保存します。
- fill=3
デコーダーバッファーの MSB 端にバイトを追加します。LSB 端からピクセルを保存します。
省略した場合、fill の順序はデフォルトで 0 になります。
- sign
ゼロ以外の場合、ビットフィールドは符号拡張されます。ゼロまたは省略した場合、ビットフィールドは符号なしになります。
- orientation
画像内の最初の行が画面上の最上行(1)か、最下行(-1)か。省略した場合、向きはデフォルトで1になります。
C で独自のファイルコーデックを作成する¶
ファイルコーデックのライフサイクルには3つの段階があります。
セットアップ:Pillow は、デコーダーまたはエンコーダーレジストリで関数を探し、内部コアイメージオブジェクトで
[codecname]_decoder
または[codecname]_encoder
という名前の関数にフォールバックします。その関数は、tile
からのargs
タプルで呼び出されます。変換:コーデックの
decode
またはencode
関数は、イメージデータのチャンクで繰り返し呼び出されます。クリーンアップ:コーデックがクリーンアップ関数を登録している場合、例外が発生した場合でも、変換プロセスの最後に呼び出されます。
セットアップ¶
現在の規則では、コーデックセットアップ関数は PyImaging_[codecname]DecoderNew
または PyImaging_[codecname]EncoderNew
という名前であり、decode.c
または encode.c
で定義されています。それに対する Python バインディングは [codecname]_decoder
または [codecname]_encoder
という名前で、_imaging.c
ファイルの関数配列のコーデックセクション内から設定されます。
セットアップ関数は PyImaging_DecoderNew
または PyImaging_EncoderNew
を呼び出す必要があり、少なくとも decode
または encode
関数ポインターを設定する必要があります。このオブジェクトで関心のあるフィールドは次のとおりです。
- decode/encode
デコードまたはエンコード関数への関数ポインター。これらは、
im
、state
、および変換されるデータのバッファーにアクセスできます。- cleanup
クリーンアップ関数への関数ポインター。これらは
state
にアクセスできます。- im
ターゲットイメージ。Pillow によって設定されます。
- state
ImagingCodecStateInstance。Pillow によって設定されます。
context
メンバーは、コーデックが特定の形式の状態またはオプションを格納するために使用できる不透明な構造体です。- pulls_fd/pushes_fd
デコーダーの
pulls_fd
またはエンコーダーのpushes_fd
が1に設定されている場合、state->fd
はPythonのファイルライクオブジェクトへのポインターになります。コーデックは、バッファを介してデータをプッシュするのではなく、codec_fd.c
の関数を使用して、ファイルライクオブジェクトと直接読み書きできます。バージョン 3.3.0 で追加。
変換¶
デコードまたはエンコード関数は、ターゲット(コア)イメージ、コーデック状態構造体、および変換されるデータのバッファとともに呼び出されます。
バッファからできるだけ多くのデータを取り出し、消費したバイト数を返すのはコーデックの責任です。コーデックへの次の呼び出しには、以前の未消費の末尾が含まれます。コーデック関数は、処理されたデータとして複数回呼び出されます。
あるいは、pulls_fd
またはpushes_fd
が設定されている場合、デコードまたはエンコード関数は空のバッファとともに一度だけ呼び出されます。その1回の呼び出しでタイル全体を変換するのは、コーデックの責任です。これを使用すると、コーデックに自由度が増しますが、コーデックによってタイル全体が一度にメモリに保持される場合、その自由度がメモリ使用量の増加につながる可能性があります。
エラーが発生した場合は、state->errcode
を設定し、-1を返します。
エラーコードを設定せずに、成功した場合は-1を返します。
クリーンアップ¶
クリーンアップ関数は、コーデックが負の値を返すか、エラーが発生した場合に呼び出されます。この関数は、割り当てられたメモリを解放し、外部ライブラリからのリソースを解放する必要があります。
Pythonで独自のファイルコーデックを作成する¶
Pythonファイルデコーダーとエンコーダーは、それぞれPIL.ImageFile.PyDecoder
とPIL.ImageFile.PyEncoder
から派生する必要があり、少なくともデコードまたはエンコードメソッドをオーバーライドする必要があります。PIL.Image.register_decoder()
とPIL.Image.register_encoder()
を使用して登録する必要があります。ファイルコーデックのC実装と同様に、Pythonベースのファイルコーデックのライフサイクルには3つの段階があります。
セットアップ:Pillowは、デコーダーまたはエンコーダーレジストリでコーデックを検索し、クラスをインスタンス化します。
変換:インスタンスの
decode
メソッドは、解釈されるデータのバッファとともに繰り返し呼び出されるか、encode
メソッドは、出力されるデータのサイズとともに繰り返し呼び出されます。あるいは、デコーダーの
_pulls_fd
プロパティ(またはエンコーダーの_pushes_fd
プロパティ)がTrue
に設定されている場合、decode
およびencode
は一度だけ呼び出されます。デコーダーでは、self.fd
を使用して、ファイルライクオブジェクトにアクセスできます。これを使用すると、コーデックの自由度が増しますが、コーデックによってファイル全体が一度にメモリに保持される場合、その自由度がメモリ使用量の増加につながる可能性があります。decode
で、データが解釈されると、set_as_raw
を使用してイメージを埋めることができます。クリーンアップ:変換が完了すると、インスタンスの
cleanup
メソッドが呼び出されます。これは、コーデックで使用されるリソースをクリーンアップするために使用できます。_pulls_fd
または_pushes_fd
をTrue
に設定した場合、decode
またはencode
の最後にクリーンアップタスクを実行することを選択した可能性があります。
PIL.ImageFile.PyDecoder
の例については、DdsImagePluginを参照してください。PIL.ImageFile.PyDecoder
とPIL.ImageFile.PyEncoder
の両方を使用するプラグインについては、BlpImagePluginを参照してください。