2015-11-14 4 views
0

У меня есть тысячи спрайтов характера (правда, это просто файлы PNG с прозрачностью), которые были сохранены у Майи.Нужно обрезать тысячи изображений/спрайтов при сохранении средней точки

Это анимация персонажей, при этом почти все из них составляют 12 кадров каждый. Каждая анимация отображается из каждого из 8 основных направлений.

В каждой анимации символ уже сосредоточен в кадре (это как он экспортируется с майя); однако каждое изображение имеет кучу белого/прозрачного пространства вокруг него.

Мне нужно обрезать эти спрайты горизонтально снаружи ->, чтобы сохранить среднюю точку персонажа в кадре. Причина этого в том, что если она не сохранилась, так как игра сворачивается с одной анимации на другую, персонаж будет перемещаться или прыгать. Итак, важно, чтобы персонаж находился в горизонтальном положении (, используя середину своего тела) в кадре во всех своих анимациях.

Дополнительно ... в идеале персонаж всегда находится на уровне или очень близко к нижнему краю спрайта.

Для купе de grace ... окончательное обрезанное изображение должно быть четным числом или делиться на 2, по причинам игрового движка.

Есть ли способ хотя бы частично или полностью автоматизировать это? Или есть программы, которые кто-то мог бы рекомендовать, чтобы помочь в автоматизации этого; бесплатно или оплачивается.

+0

Существует хороший шанс, что imagemagick может выполнить обработку, если заданы соответствующие командные строки с помощью языка сценариев или программы драйвера по вашему выбору. –

+0

@Chris Это была моя первая мысль, и раньше я использовал imagemagick, я просто не совсем уверен, как бы достичь желаемого результата. Я также должен быть уверен, что не переуплотняйте ни одно из изображений в последовательности. – Tusker

+0

Если это сгенерированные образы с эффектно пустым фоном, нужно легко найти символ внутри - просто сканировать нефонические пиксели. Но если персонаж должен двигаться, определение статического центра может быть не таким, как центр экстентов. –

ответ

1

Я еще не знаю, подходит ли ответ на Python, но вот что я получил, с небольшой работой, вы можете скопировать и вставить этот скрипт в свой редактор сценариев в Maya или выполнить его в вашем интерпретаторе Python.

Этот скрипт требует установки библиотеки PIL.

Чтобы установить его на Maya, вы можете перейти по этой ссылке Mistermatti's blog. Разархивируйте file и вставьте папку PIL в вашу майю, чтобы установить здесь: Maya20XX\Python\Lib\site-packages Это работает на Maya2014, не протестировано на других версиях tho.

from PIL import Image 
import time 
start_time = time.time() 

#parses the image to find the first pixel on the x axis which is not blank 
def parseXImage(pixelMap, resWidth, resHeight): 
    for x in range(0, int(resWidth/2)): 
     for y in range(0, int(resHeight/2)): 
      if (pixelMap[x,y] != (0, 0, 0, 0)) or \ 
       (pixelMap[x,resHeight-y-1] != (0, 0, 0, 0)) or \ 
       (pixelMap[resWidth-x-1,y] != (0, 0, 0, 0)) or \ 
       (pixelMap[resWidth-x-1,resHeight-y-1] != (0, 0, 0, 0)): 
       return x 
    return None 

#parses the image to find the first pixel on the y axis which is not blank 
def parseYImage(pixelMap, resWidth, resHeight): 
    topFound = False 
    bottomFound = False 
    yTop = None 
    yBottom = None 
    for y in range(0, int(resHeight/2)): 
     for x in range(0, int(resWidth/2)): 
      if not topFound: 
       if (pixelMap[x,y] != (0, 0, 0, 0)) or \ 
        (pixelMap[resWidth-x-1,y] != (0, 0, 0, 0)): 
        yTop = y 
        topFound = True 
      if not bottomFound: 
       if (pixelMap[x,resHeight-y-1] != (0, 0, 0, 0)) or \ 
        (pixelMap[resWidth-x-1,resHeight-y-1] != (0, 0, 0, 0)): 
        yBottom = y 
        bottomFound = True 
    return yTop, yBottom 

imageList = [r"Path\To\Image\Mod_Turn.001.png", 
    r"Path\To\Image\Mod_Turn.002.png", 
    r"Path\To\Image\Mod_Turn.003.png", 
    r"Path\To\Image\Mod_Turn.004.png", 
    r"Path\To\Image\Mod_Turn.005.png"] 

#get images resolution 
imagePil = Image.open(imageList[0]) 
resWidth, resHeight = imagePil.size #get the resolution of the first image in the list 
imagePil.close() 

valueWidthList = [] 
valueHeightTopList = [] 
valueHeightBottomList = [] 
for imageListIndex, imagePath in enumerate(imageList): 
    imagePil = Image.open(imagePath) 
    pixelMap = imagePil.load() 

    xValue = parseXImage(pixelMap, resWidth, resHeight) #now parse the image to find x 
    yTopValue, yBottomValue = parseYImage(pixelMap, resWidth, resHeight) #now parse the image to find y 
    valueWidthList.append(xValue) #Store it 
    valueHeightTopList.append(yTopValue) #Store it 
    valueHeightBottomList.append(yBottomValue) #Store it 
    imagePil.close() 

xValueToCrop = min(valueWidthList) #Get the minimal value of X crop among all the entries 
yTopValueToCrop = min(valueHeightTopList) #Get the minimal value of Y crop among all the entries 
yBottomValueToCrop = min(valueHeightBottomList) #Get the minimal value of Y crop among all the entries 
#This is the crop square we will use 
cropSquare = (xValueToCrop, yTopValueToCrop, resWidth-xValueToCrop, resHeight-yBottomValueToCrop ) 

for imagePath in imageList: 
    imagePil = Image.open(imagePath) 
    #Replace Turn by something in the name of your image 
    imagePil.crop(cropSquare).save(imagePath.replace("Turn", "Turn_Cropped")) #Crop dans save the image 
    imagePil.close() 

print("--- %s seconds ---" % (time.time() - start_time)) 

Вы должны изменить ImageList Dict своими путями к изображениям и "Turn", "Turn_Cropped" в самом конце сценария.

FYI, обработка 300 изображений @ 720p заняла около 250 секунд. Это можно улучшить.

+0

Спасибо, кучка @ DrHaze. Я посмотрю на это более подробно, так как это может быть жизнеспособное решение. Очень признателен! – Tusker

0

Возможно дать TexturePacker попробовать https://www.codeandweb.com/texturepacker

Я использовал его раньше, когда дело с спрайтов и найти его довольно хорошо. Я считаю, что у него также есть функциональность в командной строке, хотя я не использовал его сам. И это кросс-платформенный.

+0

Я раньше использовал TexturePacker, но я не могу понять, как просто обрезать серию спрайтов. Мы не используем (и не можем использовать) спрайты. В противном случае TexturePacker был одной из моих первых мыслей ... – Tusker

 Смежные вопросы

  • Нет связанных вопросов^_^