タイトルにある通りのことをしたかった。
単純に はみ出し crop すると背景は黒くなるので、これを白くする。
簡単にまとめると、Image.new に paste した後 crop した。
Pillow で単純な crop をすると黒背景になる
Pillow では次のように crop できる。
PIL.Image.Image.crop - documentation
from PIL import Image
img = Image.open("lena.jpg") # 512 x 512
width = 512
height = 512
left = 256
top = 256
right = left + width
bottom = top + height
rect = (left, top, right, bottom)
img = img.crop(rect)
img.save("lena_crop.jpg")
はみ出した背景は黒で埋められる。
crop の背景を白で埋める
次のように Image.new で白背景の画像を作り paste してから crop する。
from PIL import Image
img = Image.open("lena.jpg") # 512 x 512, RGB
width = 512
height = 512
left = 256
top = 256
right = left + width
bottom = top + height
rect = (left, top, right, bottom)
img_old = img
# 背景色は白(0xFF)
bgcolor = 255
# ( 幅 , 高さ ) = ( left + width , left + width ) の大きい画像を作る
img = Image.new(img_old.mode,(left+width,left+width),(bgcolor,bgcolor,bgcolor))
# 大きい画像の 左上 (0,0) に貼り付け
img.paste(img_old,(0,0))
img = img.crop(rect)
img.save("lena_crop.jpg")
このように、はみ出した背景を白くできた。
注意点
今回使った画像は mode が "RGB" なので、
img = Image.new(img_old.mode,(left+width,top+height),bgcolor)
のように単純に int を渡すと赤 ( RGB の R ) とみなされ、背景が赤くなる。
逆に、グレースケール (modeが"L") の画像に (255,255,255) と色指定すると次のようなエラーが出る。
TypeError: color must be int or single-element tuple
途中で img_old = img_old.convert("L") のような変換をしていた場合は int を渡す。
場合分けを書く場合は、以下のページなどを見ながら書くと良いと思う。
Concepts - Pillow documentation
より良い方法が見つかれば追記する。