これは、スプライトを扱うものすべてに実装する必要があるように思えますが、ここでは独自のスプライト スプリッターを実装します。
ここで最初に必要なことは、個々のオブジェクトを抽出することです。この状況では、ピクセルが背景かどうかを判断するだけです。原点の点が背景ピクセルであると仮定すると、完了です。
from PIL import Image
def sprite_mask(img, bg_point=(0, 0)):
width, height = img.size
im = img.load()
bg = im[bg_point]
mask_img = Image.new('L', img.size)
mask = mask_img.load()
for x in xrange(width):
for y in xrange(height):
if im[x, y] != bg:
mask[x, y] = 255
return mask_img, bg
上記で作成した画像を保存してmask
開くと、次のように表示されます (空のウィンドウ内に四角形を追加しました)。
上の画像で、他のスプライト内にあるスプライトを結合したい場合、次に必要なことはその穴を埋めることです (追加された長方形のように、上の図を参照)。これはもう 1 つの単純な規則です。[0, 0] の点から点に到達できない場合、それは穴であり、埋めなければなりません。あとは、各スプライトを個々の画像に分離するだけです。これは、連結成分のラベル付けによって行われます。コンポーネントごとに、ピースの寸法を定義するために軸に沿った境界ボックスを取得し、元の画像から特定のコンポーネントに属するポイントをコピーします。簡潔にするために、次のコードはscipy
これらのタスクに使用します。
import sys
import numpy
from scipy.ndimage import label, morphology
def split_sprite(img, mask, bg, join_interior=True, basename='sprite_%d.png'):
im = img.load()
m = numpy.array(mask, dtype=numpy.uint8)
if join_interior:
m = morphology.binary_fill_holes(m)
lbl, ncc = label(m, numpy.ones((3, 3)))
for i in xrange(1, ncc + 1):
px, py = numpy.nonzero(lbl == i)
xmin, xmax, ymin, ymax = px.min(), px.max(), py.min(), py.max()
sprite = Image.new(img.mode, (ymax - ymin + 1, xmax - xmin + 1), bg)
sp = sprite.load()
for x, y in zip(px, py):
x, y = int(x), int(y)
sp[y - int(ymin), x - int(xmin)] = im[y, x]
name = basename % i
sprite.save(name)
print "Wrote %s" % name
sprite = Image.open(sys.argv[1])
mask, bg = sprite_mask(sprite)
split_sprite(sprite, mask, bg)
これで、質問に含めたとおりのすべてのピース (sprite_1.png、sprite_2.png、...、sprite_8.png) が得られました。