ユーニックス総合研究所

  • home
  • archives
  • python-pillow-image-frombytes

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で、このmodeRGBだったりすると、生成される画像がおかしくなります。

size(第2引数)

sizeは生成する画像のサイズです。(width, height)のフォーマットのタプルで渡します。

data(第3引数)

datamodeに指定されたモードのバイト列です。

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引数として適当なものを答えよ

  1. 'L'
  2. 'RGB'
  3. 'bytes'

Q2: Image.frombytes()の返り値として適当なものを答えよ

  1. bytes
  2. Image
  3. list

Q3: Image.frombytes()の第3引数として適当なものを答えよ

  1. Image
  2. bytes
  3. dict

正解はこちら↓

Q1: 1, 2
Q2: 2
Q3: 2