Захотелось продолжить серию постов о всяких интересных автореферентных штуковинах и решил я написать о жанре Zoomquilt. Сделал поиск, увидел, что один пост на Хабре уже есть. Подумал, подумал и решил, что пост я всё равно напишу, но он будет технический, о технологии создания Zoomquilt.
Для начала собственно о жанре. Тут проще показать чем рассказывать.
zoomquilt2.madmindworx.com/zoomquilt2.swf
www.deviantart.com/art/kopfsalat-digital-edition-30069104
Приближаемся к картинке и вместо того, чтобы в какой-то момент увидеть пиксели величиной с кулак, видим следующую картинку, повторяем процедуру многократно (на самом деле, выглядит это как один вполне себе плавный процесс и если художники хорошо поработали, то «стыков» мы вообще не увидим) и в итоге приходим к первоначальной картинке. В общем мультиквайны, только для художников.
А как такая штука делается? Конечно можно нарисовать это всё покадрово, более того, некоторые талантливые аниматоры вполне бы с этим справились. Но практически во всех существующих произведениях этого жанра указано, что это плоды коллективного творчества. Обычно есть коллектив художников, координатор проекта и программист, который собственно собирает это всё вместе и пишет интерфейс.
Дальше о технологии создания. Под катом много картинок.
Стал я искать информацию по технологии создания и мне повезло. Наткнулся на исходные изображения из которых состоял самый первый Zoomquilt. Вот одно из них:
Каждый «исходник» представляет собой изображение 1024*768 в середине которого находится чёрный прямоугольник размером 512*384.
Для начала разберёмся со сборкой zoomquilt из этих «исходников». Превратим картинки в полноценные кадры будущей анимации.
Понятно, что чёрный прямоугольник в центре изображения должен быть заменен следующим в списке изображением (для последнего изображения следующим является первое), уменьшенным до соответствующих размеров, причём перед тем, как заменять, нужно со следующим изображением проделать ту же процедуру и т.д. Пахнет это всё бесконечной рекурсией без условия останова, но к счастью, изображения дискретны и нарисовать что-либо размером меньше пикселя невозможно. Чёрный прямоугольник в центре картины будет уменьшаться, пока совсем не исчезнет и в этот момент замены можно прекратить.
Из полученных кадров конечно можно собрать анимацию
Но она будет прерывистой, т.к. в ней участвуют только ключевые кадры
Для каждого ключевого кадра можно создать при помощи приближения несколько промежуточных.
Окончательный вариант получился слишком тяжёлым для того, чтобы вставить его в статью, впрочем он мало отличается от оригинального ролика.
Это всё замечательно, собирать из готового мы уже умеем, но «исходники» кто-то должен нарисовать, причём так, чтобы все переходы были настолько плавными, чтобы не было понятно, где заканчивается одна картинка и начинается другая.
А происходит всё, насколько я понимаю, так:
Сначала координатор проекта даёт одному или нескольким художникам следующее изображение:
Художники должны заполнить всю зелёную зону и не должны трогать чёрную (точнее трогать они её могут, но всё, что они там нарисуют не будет учитываться при сборке). Затем, когда художники закончат работу, каждую из картин можно передать двум художникам. Один получает картину в таком виде:
Другой, в таком:
Обратите внимание, что размеры зелёных прямоугольников одинаковые на обеих картинах, ведь именно содержимое этого самого прямоугольника художник сдаёт координатору (ну или скорее координатор вырезает нужную часть из присланой картины).
Когда наберётся достаточное количество картин (минимум — 2, максимум не ограничен), координатор выдаст нескольким (вероятно самым сильным в проекте) художникам (их число равно числу художников, получивших в начале работы пустые картины) картины типа этой:
На этом круг замыкается, уроборос тихо переваривает хвост, а мы восторженно смотрим на очередное произведение.
Вот код, который я написал для этой статьи, писалось всё минут сорок на коленке, так что если кто-нибудь напишет по-человечески, с удовольствием и благодарностью вставлю сюда.
import PIL
from PIL import Image
from images2gif import writeGif
X,Y = 1024,768
IMAGES_NUM = 46
def render_images(raw_images):
cur_index=0
count = 0
while True:
count+=1
if count == 100: break
prev_index = cur_index - 1
if prev_index == -1: prev_index = len(raw_images)-1
cur_image = raw_images[cur_index]
prev_image = raw_images[prev_index]
prev_image.paste(cur_image.resize((X/2,Y/2)),(X/4,Y/4))
cur_index = prev_index
def before_image(im):
im1=Image.new("RGB",(X,Y),(0,255,0))
im1.paste(im.resize((X/2,Y/2)),(X/4,Y/4))
return im1
def after_image(im):
im1 = im.copy()
im1=im1.resize((X*2,Y*2))
im1.paste(new_image(),(X/2,Y/2))
return im1
def between_image(im1,im2):
im = im1.copy()
im=im.resize((X*2,Y*2))
im.paste(before_image(im2),(X/2,Y/2))
return im
def new_image():
im1=Image.new("RGB",(X,Y),(0,255,0))
im1.paste(Image.new("RGB",(X/2,Y/2),(0,0,0)),(X/4,Y/4))
return im1
def between_frames(key_frame, number_of_frames):
step_x = X/4/number_of_frames
step_y = Y/4/number_of_frames
l=[]
for i in xrange(1,number_of_frames+1):
x=step_x*i
y=step_y*i
l.append(key_frame.crop((x,y,x+(X-2*x),y+(Y-2*y))).resize((X,Y)))
return l
def crop_image(im):
im1=im.copy()
x,y=im.size
black=Image.new("RGB",(X/2,Y/2),(0,0,0)),(X/4,Y/4)
if x==X:
im1.paste(black)
elif x==X*2:
im1=im1.crop((X/2,Y/2,X/2+X,Y/2+Y))
im1.paste(black)
return im1
Здесь есть все необходимые функции для создания своего Zoomquilt. Если что-то непонятно, спрашивайте.
Если есть желающие художники, пишите в личку, могу побыть координатором, сделаем хамбразумквилт :).
Если кто-нибудь знает ещё произведения в этом жанре, присылайте ссылки.
Спасибо за внимание.
Автор: gromozeka1980