Похоже, что это должно быть реализовано во всем, что имеет дело со спрайтами, но здесь мы реализуем наш собственный спрайт-сплиттер.
Первое, что нам нужно здесь, это извлечь отдельные объекты. В этой ситуации вопрос только в том, является ли пиксель фоновым или нет. Если мы предположим, что исходная точка является фоновым пикселем, то мы закончили:
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
, созданное выше, и откроете его, вот что вы увидите на нем (я добавил прямоугольник внутри вашего пустого окна):
Следующее, что нам нужно сделать с изображением выше, это заполнить его отверстия, если мы хотим соединить спрайты, которые находятся внутри других (например, добавленный прямоугольник, см. рисунок выше). Это еще одно простое правило: если точка не может быть достигнута из точки [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) именно так, как вы указали в вопросе.
person
mmgp
schedule
21.01.2013