Выбрать главу

def paste(top,right,front,free,output="result.png"):

   im = pim.open(top)

   w,h= im.size

   edge=4

   edgecolor=(0.0,0.0,0.0)

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

   comp = pim.new(im.mode,(w*2+3*edge,h*2+3*edge),

                  edgecolor)

Мы уже открыли верхнее изображение, так что всё, что мы должны сделать - вставить его в верхнем левом квадранте нашего комбинированного изображения, сдвинув его как в горизонтальном, так и в вертикальном направлениях на ширину границы:

   comp.paste(im,(edge,edge))

Вставка трёх остальных изображений следует за той же схемой: открыть изображение и вставить его в правильной позиции. Наконец, комбинированное изображение сохраняется (выделено). Тип сохраняемого файла определяется его расширением (например, png), но его можно было бы переопределить, передав аргумент формата методу save(). Заметьте, что не было никакой причины определять формат для входных файлов, так как тип изображения функция open() определяет по их содержанию.

   im = pim.open(right)

   comp.paste(im,(w+2*edge,edge))

   im = pim.open(front)

   comp.paste(im,(edge,h+2*edge))

   im = pim.open(free)

   comp.paste(im,(w+2*edge,h+2*edge))

   comp.save(output)

Наша следующая функция рендерит вид из конкретной камеры и сохраняет результат в файл. Камера для рендера передаётся как имя Объекта Блендера (то есть, это не имя основного объекта Camera). Первая строка извлекает объект Camera и текущую сцену и делает камеру текущей в сцене - той которая будет рендерить (выделено ниже). Функция setCurrentCamera() принимает Объект Блендера, а не объект Камеры, и именно по этой причине мы передаём имя объекта.

def render(camera):

   cam = Object.Get(camera)

   scn = Scene.GetCurrent()

   scn.setCurrentCamera(cam)

   context = scn.getRenderingContext()

Так как нам может понадобиться использовать эту функцию в фоновом процессе, мы используем метод renderAnim() контекста рендера, а не метод render(). Дело в том, что метод render() не может быть использован в фоновом процессе. Следовательно, мы устанавливаем в значение текущего кадра как начальный, так и конечный кадры, чтобы гарантировать, что функция renderAnim() отрендерит единственный кадр. Мы также устанавливаем displayMode на 0, чтобы предотвратить появление дополнительного окна рендера (выделено в следующем куске кода):

   frame = context.currentFrame()

   context.endFrame(frame)

   context.startFrame(frame)

   context.displayMode=0

   context.renderAnim()

Метод renderAnim() рендерит кадры в файлы, так что наша следующая задача в том, чтобы извлечь имя файла того кадра, который мы только что визуализировали. Точный формат имени файла может задаваться пользователем в окне Пользовательских настроек, но явный вызов функции getFrameFilename() даёт нам уверенность, что мы получим правильное имя:

   filename= context.getFrameFilename()

Так как номер кадра будет одинаковым для вида каждой камеры, что мы рендерим, мы должны переименовать этот файл, в противном случае он будет переписан. Следовательно, мы создаём новое подходящее имя, состоящее из пути к кадру, который мы только что рендерили, и имени камеры. Мы используем переносимые функции обработки пути из питонового модуля os.path, так, чтобы всё работало одинаково хорошо как под Windows, так и под Linux, например.

Так как наш скрипт, возможно, уже использовался, мы пытаемся удалять любой существующий файл с тем же именем, поскольку переименование файла на существующее имя потерпит неудачу под Windows. Конечно, файла пока могло и не быть  -  в этой ситуации нас защищает блок try. Наконец, наша функция возвращает имя вновь созданного файла:

   camera = os.path.join(os.path.dirname(filename),camera)

   try:

      os.remove(camera)

   except:

      pass

   os.rename(filename,camera)

   return camera

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