PythonのPillowのImage.frombytesの使い方: バイト列データを画像に変換する
- 作成日: 2020-09-29
- 更新日: 2024-02-17
- カテゴリ: Python
PillowのImage.frombytesの使い方
Pythonの画像処理ライブラリであるPillowは画像を処理するImage
モジュールを持っています。
Image
モジュールは低レイヤ―なバイト列(bytes
)から画像を生成できるfrombytes()
関数を持っています。
この関数を使うとバイト列で画像データを編集し、結果を画像に変換することが可能になります。
プログラミング的な画像の編集は、一般的にはnumpy
を使ったほうが効率がいいのでよければ↓の記事も参照してみてください。
Image.frombytesの構造
Image.frombytes()
は↓のような構造を持っています。
PIL.Image.frombytes(mode, size, data, decoder_name='raw', *args)
引数と返り値の解説は↓の通りです。
mode(第1引数)
mode
は生成する画像のモードです。L
(8ビット)やRGB
等を指定できます。
バイト列(data
)のモードとこのmode
は一致させる必要があります。
たとえばバイト列のモードがRGBA
で、このmode
がRGB
だったりすると、生成される画像がおかしくなります。
size(第2引数)
size
は生成する画像のサイズです。(width, height)
のフォーマットのタプルで渡します。
data(第3引数)
data
はmode
に指定されたモードのバイト列です。
decoder_name(第4引数)
decoder_name
はデコーダーの名前です。デフォルトはraw
です。
args(第5引数)
args
はデコーダーの引数です。
返り値
返り値はImage
オブジェクトです。
今回使用する画像
今回使用する画像はこちらです。
この画像はRGBA
画像です。
画像をバイト列にする
Image
オブジェクトをバイト列にするにはImage.tobytes
関数を使います。
from PIL import Image
im = Image.open('img/a.png') # RGBAの画像ファイルを開く
bs = im.tobytes() # 画像をバイト列に変換する
print(type(bs)) # タイプ
print(bs[:4]) # バイト列(先頭4バイトのみ)
<class 'bytes'>
b'\x95\x8e\x8e\xff'
バイト列を画像にする
bytes
を画像にするにはImage.frombytes()
を使います。
from PIL import Image
im = Image.open('img/a.png') # 画像を開く
bs = im.tobytes() # 画像をバイト列に変換する
dst_im = Image.frombytes('RGBA', im.size, bs) # バイト列から画像を生成
dst_im.save('dst/out0.png') # 画像を保存
出力結果。
バイト列を編集する
RGBA
の画像をバイト列で編集します。
RGBA
の場合、RGBA
自体の長さは4
つです。例えば画像のサイズが横幅(10px)、高さ(10px)だった場合、そのデータの長さは以下の式で求められます。
data_len = 4 (RGBA) * 10 (横幅) * 10 (高さ)
↓のコードでは、横幅x高さの長さだけfor
文を回し、そのインデックスを基準にしたRGBA
のデータにアクセスしています。
data[4 * i + 0]
というのがR
へのアクセスで、data[4 * i + 1]
がG
へのアクセスです。
from PIL import Image
im = Image.open('img/a.png') # RGBA画像を開く
data = im.tobytes() # バイト列に変換
arr = bytearray() # 編集用のバイト配列
print('data len', len(data)) # RGBAの500px(横)* 500px(高さ)の画像だから全体の長さは1000000
for i in range(im.size[0] * im.size[1]): # 横x高さだけ回す
r = data[4 * i + 0] * 3 % 255 # Rの編集
g = data[4 * i + 1] * 3 % 255 # Gの編集
b = data[4 * i + 2] * 3 % 255 # Bの編集
a = data[4 * i + 3] # Aの編集
arr += bytearray((r, g, b, a)) # 編集したRGBAをバイト配列に追加
print('arr len', len(arr))
dst_im = Image.frombytes('RGBA', im.size, bytes(arr)) # バイト列から画像を生成
dst_im.save('dst/out1.png') # 画像を保存
出力結果。
data len 1000000
arr len 1000000
関連
Image.frombytes()
と関連のある関数の記事は以下があります。
問題
Q1: Image.frombytes()
の第1引数として適当なものを答えよ
- 'L'
- 'RGB'
- 'bytes'
Q2: Image.frombytes()
の返り値として適当なものを答えよ
- bytes
- Image
- list
Q3: Image.frombytes()
の第3引数として適当なものを答えよ
- Image
- bytes
- dict
正解はこちら↓
Q1: 1, 2
Q2: 2
Q3: 2