< [ на главную ]

PixelArray - начинаем работать с Pygame .

    1. Немного объяснений для начала:

    1.1  Цель этой статьи показать как пользоваться оператором pixelarray модуля pygame для быстрого создания различных экранных  эффектов.  Для начала я взял встроенный в  Pygame  пример ( если pygame установлен то его вместе с  другими примерами и описанием на английском языке вы найдете у себя  по адресу : /usr/share/doc/python-module-pygame-doc-1.8.1 ) и дополнил своими комментариями. Запускать примеры из этой папки под обычным пользователем у вас не получится ( не хватит прав ), но можно скопировать содержание каталога examples в ваш домашний каталог и запускать примеры уже оттуда. Для продолжения я написал небольшую демку ( вспоминая Спектрумовский Supercode ).которая немного дополняет встроенный пример.
Кроме того специально для этой статьи я сделал архив Pixelarray.tar в котором запакован этот пример с моими комментариями на русском, моя небольшая демка использующая pixelarray, а также изображения необходимые для работы этих программ.
Если эта тема вас заинтересовала, скачиваете архив, распаковываете его и запускаете программы.
    1.2  Заранее извиняюсь за возможные неточности в объяснении работы некоторых операторов этой библиотеки (я не переводил описание, а пытался понять что делает каждый оператор сравнивая листинг программы с ее работой ), а также за несколько не питоновскую терминологию, например я упорно использую понятие массива ( сказывается паскальное прошлое ), вместо списка, впрочем создатели pygame видимо придерживаются похожих взглядов (думаю, что pyxelarray можно спокойно перевести, как массив пикселов).
Кое-где вместо "элемент массива" я допускаю высказывания пиксел или точка (так короче и по смыслу понятнее ) и тому подобные вольности, будем надеяться Вы, как читатель, не ждете  сухого академического стиля от кодера-любителя.
    1.3  Теперь немного теории для лучшего понимания этих примеров:
В pygame есть понятие screen - это  окно ( виртуальное ) в котором происходит работа графических операторов.
 Команда pigame.display.flip() отображает содержание виртуального окна на дисплее.
Понятие surface - поверхность, это некоторое виртуальное окно ( в отличие от screen, который всегда один, поверхностей может быть много ), с которым можно производить различные действия, а можно и загрузить ее в screen:     screen.blit(surface,(0,0)) для последующего отображения на дисплее оператором
pigame.display.flip().
 
Последний комментарий собственно о pixelarray: он представляет собой двумерный массив (по X и Y ). где значением каждого элемента является значение цвета соответствующего ему пиксела на поверхности ( surface ). Причем, можно произвести и обратную операцию, изменить значение элементов массива, а затем уже передать все эти свойства поверхности (все это я довольно неплохо откомментировал во встроенном примере, так что там и смотрите ). Теперь предположим что pixelarray уже создан:
ar = pygame.PyxelArray (surface)
     немного про его адресацию :
ar[x,y] = (0, 0, 0) - записываем в элемент с координатами x,y значение соответствующее черному цвету.
ar[:] = ( 255, 255, 255) - записываем во все элементы массива значение соответствующее белому цвету.
ar[:] = ar [::-1,:] - отражаем картинку по X для этого всем элементам массива ( ar[:] ) присваиваем  значения элементов этого массива взятых 
   по X   от  максимального к минимальному, а по Y стандартно ( ar [ ::-1,:] )
ar[:] = ar [:,::-1] - отражаем картинку по Y , если у вас есть проблемы с пониманием подобных записей посмотрите хорошую книгу по питону
   (или   сходите по ссылке из моей статьи ) и почитайте там о  адресации в списках, кортежах , строках.
Что бы содержание массива было преобразовано в цвет точек поверхности, надо дать команду:
del ar - при этом произойдет преобразование цвета точек поверхности соответствующих элементам массива , а сам массив будет удален.  
Вот собственно и все предисловие, смотрите примеры:


   2. Пример с комментариями:
 
#!/usr/bin/env python
# _*_ coding: utf-8 _*_
# без этой строки нельзя пользоваться русским даже в коментариях
import os, pygame
#подключить модули os и pygame
pygame.init ()
#обязательно при работе pygame
screen = pygame.display.set_mode ((255, 255))
#задать размер окна x , y
surface = pygame.Surface ((255, 255))
#задать размер виртуальной поверхности x , y
pygame.display.flip ()
# показать изменение на экране, внимание без использования этого
# оператора на экране останется старая картинка



def show (image):
# процедура заливает окно ,белым цветом и в координаты 0,0 впечатывает
# картинку после чего ожидает клика мышкой в окне программы для
# выхода из процедуры
# или щелчка по кнопке закрытия,крест, на заголовке окна, для
# выхода из программы
screen.fill ((255, 255, 255))
# заливка цветом
screen.blit (image, (0, 0))
# загрузка изображения
pygame.display.flip ()
# отрисовка на всего на экране
while 1:
# бесконечный цикл
event = pygame.event.wait ()
if event.type == pygame.QUIT:
raise SystemExit
# выход из программы по нажатию Esc или попытки закрытия окна
if event.type == pygame.MOUSEBUTTONDOWN:
break
# выход из процедуры по щелчку мыши на окне программы
# Create the PixelArray.


#---------------------------------------------------------

ar = pygame.PixelArray (surface)
# Создаем 2-мерный массив ar соответствующий поверхности
r, g, b = 0, 0, 0
# Do some easy gradient effect.
# верикальный градиент,темное вверху
for y in xrange (255):
# значения цвета в каждом канале red,green,blue одновременно изменяются
# в цикле от 0 до 255 это переход от черного к белому
r, g, b = y, y, y
ar[:,y] = (r, g, b)
# нумерация строк массива тоже изменяется в цикле от 0 до 255 при этом
# во все элементы строки записывается текущее значение цвета
del ar
# необходимо сделать чтобы изменения в массиве привели к изменению
# картинки, внимание массив при этом удаляется
show (surface)

#---------------------------------------------------------

# We have made some gradient effect, now flip it.
# вертикальный градиент ,темное внизу
ar = pygame.PixelArray (surface)
# Создаем 2-мерный массив ar соответствующий поверхности
ar[:] = ar[:,::-1]
# Переворачиваем массив по Y '(каждой строчке массива начиная с первой Ymin+1 ar[:]
# присваиваем значение строчки начиная с последней Ymax-1 ar[:,::-1) '
del ar
show (surface)

#---------------------------------------------------------


# Every second column will be made blue
# вертикальные синие полосы
ar = pygame.PixelArray (surface)
# Создаем 2-мерный массив ar соответствующий поверхности
ar[::2] = (0, 0, 255)
# во все столбцы через 2 записываем синий для любого значения Y'(цвет задается
# в формате красный,зеленый,синий интенсивность от 0 до 255 )'
del ar
show (surface)

#---------------------------------------------------------

# Every second row will be made green
# Зеленые квадратики
ar = pygame.PixelArray (surface)
# Создаем 2-мерный массив ar соответствующий поверхности
ar[:,::2] = (0, 255, 0)
# Во все строки через 2 записываем зеленый для любого значения X
del ar
show (surface)

#---------------------------------------------------------

# Manipulate the image. Flip it around the y axis.
# Перевернуть изобр по Y
surface = pygame.image.load (os.path.join ('data', 'arraydemo.bmp'))
# загрузить изображение arraydemo.bmp из каталога data на поверхность
ar = pygame.PixelArray (surface)
# Создаем 2-мерный массив ar соответствующий поверхности
ar[:] = ar[:,::-1]
# Переворачиваем массив по Y '(каждой строчке массива начиная с первой Ymin+1 ar[:]
# присваиваем значение строчки начиная с последней Ymax-1 ar[:,::-1]) '
del ar
show (surface)

#---------------------------------------------------------


# Flip the image around the x axis.
# Перевернуть изображение по X
ar = pygame.PixelArray (surface)
# Создаем 2-мерный массив ar соответствующий поверхности
ar[:] = ar[::-1,:]
# Переворачиваем массив по X '(каждой столбцу массива начиная с первого Xmin+1 ar[:]
# присваиваем значение столбца начиная с последнего Xmax-1 ar[::-1,:]) '
del ar
show (surface)

#---------------------------------------------------------

# Every second column will be made white.
# Провести белые вертикальные прямые с промежутком 2 пиксела
ar = pygame.PixelArray (surface)
# Создаем 2-мерный массив ar соответствующий поверхности
ar[::2] = (255, 255, 255)
del ar
show (surface)

#----------------------------------------------------------

# Flip the image around both axes, restoring it's original layout.
# Перевернуть изображение по X и по Y - исходная картинка
ar = pygame.PixelArray (surface)
# Создаем 2-мерный массив ar соответствующий поверхности
ar[:] = ar[::-1,::-1]
del ar
show (surface)

#----------------------------------------------------------

# Scale it by throwing each second pixel away.
# Уменьшить изображение в 2 раза
surface = pygame.image.load (os.path.join ('data', 'arraydemo.bmp'))
# загружаем изображение
ar = pygame.PixelArray (surface)
# Создаем 2-мерный массив ar соответствующий поверхности
sf2 = ar[::2,::2].make_surface ()
# Создаем новую поверхность выбирая точки через одну по X и Y
del ar
show (sf2)
# Рисуем на экране новую поверхность

#-----------------------------------------------------------


# Replace anything looking like the blue color from the text.
# Заменить цвет
ar = pygame.PixelArray (surface)
# Создаем 2-мерный массив ar соответствующий поверхности
ar.replace ((60, 60, 255), (0, 255, 0), 0.06)
# Заменяем пикселы совпадающие по цвету из первых скобок на цвет из вторых
# скобок коэффициент изменяется от 0 до 1 и является порогом цвета
del ar
show (surface)

#-----------------------------------------------------------

# Extract anything which might be somewhat black.
# Заменить цвет на черный
surface = pygame.image.load (os.path.join ('data', 'arraydemo.bmp'))
# Грузим картинку
ar = pygame.PixelArray (surface)
# Создаем 2-мерный массив ar соответствующий поверхности
ar2 = ar.extract ((0, 0, 0), 0.07)
# Создаем массив ar2 из массива ar заменяя его точки на черные, коэффициент
# порога цвета 0.07

sf2 = ar2.surface
# создаем поверхность из массива
del ar, ar2
show (sf2)
# Рисуем на экране новую поверхность

#-----------------------------------------------------------

# Compare two images.
# Сравнить 2 изображения, несовпадающие элементы белым
surface = pygame.image.load (os.path.join ('data', 'alien1.gif'))
# грузим 1-ую картинку
surface2 = pygame.image.load (os.path.join ('data', 'alien2.gif'))
# грузим 2-ую картинку
ar1 = pygame.PixelArray (surface)
ar2 = pygame.PixelArray (surface2)
# создаем массивы соответствующие поверхностям
ar3 = ar1.compare (ar2, 0.07)
# создаем массив ar3 сравнивая ar1 и ar2, если элементы совпадают,с учетом
# коэффициента, ставим черный пиксел, если нет белый
sf3 = ar3.surface
# создаем новую поверхность соответствующую массиву
del ar1, ar2, ar3
show (sf3)
# Рисуем на экране новую поверхность


  3. Моя демка:
#!/usr/bin/env python
# _*_ coding: utf-8 _*_
# небольшая демка на тему pygame.PixelArray
import os, pygame
katalog = 'cosmos'
risunok = 'whirlpool.jpg'
pygame.init ()
xs=800
ys=500
screen = pygame.display.set_mode ((xs, ys))
# задаем размер окна
pygame.display.flip ()
# отрисовываем его на дисплее
def show (image):
# процедура заливает окно ,белым цветом и в координаты 0,0 впечатывает
# картинку, после чего ждет 1 секунду
screen.fill ((255, 255, 255))
# заливка цветом
screen.blit (image, (0, 0))
# загрузка изображения
pygame.display.flip ()
pygame.time.wait(1000)

#-----------------------------------------------------------------

surface = pygame.image.load (os.path.join (katalog, risunok))
# Грузим изображение на поверхность
ar = pygame.PixelArray (surface)
# Создаем 2-мерный массив ar соответствующий поверхности
ar[::16,:] = [0,255,0] # вертик зеленые полосы Y
ar[:,::16 ] = [0,255,0] # гориз зеленые полосы X
for i in range (ys):
ar[i,i] = [0,0,255] # проводим красную диагональ
del ar
show (surface)

#-----------------------------------------------------------------

# заливка синим цветом
surface = pygame.image.load (os.path.join (katalog, risunok))
# грузим рисунок на поверхность
ar = pygame.PixelArray (surface)
# Создаем 2-мерный массив ar соответствующий поверхности
ar[:,:] = [255,0,0]
# Во все точки массива записываем синий
del ar
show (surface)

#------------------------------------------------------------------

# Загрузить изображение и уменьшить его

surface = pygame.image.load (os.path.join (katalog, risunok))
# грузим рисунок на поверхность
ar = pygame.PixelArray (surface)
# Создаем 2-мерный массив ar соответствующий поверхности
del ar
show (surface)

for n in range (1,3):
# цикл n= 1, 2, 3
ar = pygame.PixelArray (surface)
# Создаем 2-мерный массив ar соответствующий поверхности
pygame.time.wait(500)
# Пауза 0,5 секунды
surface = ar[::2,::2].make_surface ()
# Создаем поверхность из каждой второй точки массива(уменьшаем в 2 раза)
del ar
screen.fill ((0, 0, 0))
# заливаем экран черным цветом
screen.blit (surface, (xs//2-xs//2//(n+1) ,ys//2-ys//2//(n+1)))
# отрисовываем поверхность на экране
pygame.display.flip ()
# отображаем экран на дисплее

#-----------------------------------------------------------------

# Расходящиеся по X шторки
surface = pygame.image.load (os.path.join (katalog, risunok))
# грузим изображение на поверхность
ar = pygame.PixelArray (surface)
# Создаем 2-мерный массив ar соответствующий поверхности

sf1 = ar[:xs//2,:].make_surface ()
# Создаем поверхность где x=0 до x=xs//2
# Левая шторка
sf2 = ar[xs//2:,:].make_surface ()
# Создаем поверхность где x=xs//2 до xs
# Правая шторка
del ar
for i in range (0,xs//2,10):

screen.fill ((0, 0, 0))
# заливка черным цветом
screen.blit (sf1, (-i, 0))
# левая шторка печатается на пиксел влево
screen.blit (sf2, ((xs//2)+i, 0))
# правая шторка печатается на пиксел вправо
pygame.display.flip ()
# отрисовка на дисплее

screen.fill ((0, 0, 0))
pygame.display.flip ()
# закрашиваем экран черным цветом

#-----------------------------------------------------------------

# Сходящиеся по X к центру шторки
surface = pygame.image.load (os.path.join (katalog, risunok))
for i in range (0,xs//2,10):
ar = pygame.PixelArray (surface)
sf1 = ar[:xs//2-i ,:].make_surface ()
# левая шторка от 0 до xs//2-i, ширина уменьшается в цикле
sf2 = ar[xs//2+i: ,:].make_surface ()
# правая шторка от xs//2+i до xs , ширина уменьшается в цикле
del ar
screen.fill ((0, 0, 0))
# заливаем черным
screen.blit (sf1, (i, 0))
# левую шторку смещаем вправо в цикле
screen.blit (sf2, (xs//2, 0))
# правую шторку печатаем посередине

pygame.display.flip ()
# отрисовка на дисплее
screen.fill ((0, 0, 0))
# заливаем черным
pygame.display.flip ()

# отрисовка на дисплее

#----------------------------------------------------------------

# скроллинг вправо,влево,вниз,вверх

# скроллинг вправо
surface = pygame.image.load (os.path.join (katalog, risunok))
# грузим картинку
for i in range (0,xs+10,10):

screen.fill ((0, 0, 0))
# заливаем экран черным

screen.blit (surface, (i, 0))
# впечатываем картинку в экран со смещением в цикле на 10 вправо
pygame.display.flip ()
# отрисовка на дисплее
#----------------------------

# скроллинг влево
surface = pygame.image.load (os.path.join (katalog, risunok))
# грузим картинку
for i in range (0,xs+10,10):

screen.fill ((0, 0, 0))
# заливаем экран черным
screen.blit (surface, (-i , 0))
# печатаем картинку со смещением влево
pygame.display.flip ()
# отрисовка на дисплее
#----------------------------

surface = pygame.image.load (os.path.join (katalog, risunok))
# грузим картинку
for i in range (0,ys+10,10):

screen.fill ((0, 0, 0))
# заливаем экран черным
screen.blit (surface, (0 , i))
# печатаем картинку со смещением вниз
pygame.display.flip ()
# отрисовка на дисплее
#----------------------------

surface = pygame.image.load (os.path.join (katalog, risunok))
# грузим картинку
for i in range (0,ys+10,10):

screen.fill ((0, 0, 0))
# заливаем экран черным
screen.blit (surface, (0 , -i))
# печатаем картинку со смещением вниз
pygame.display.flip ()
# отрисовка на дисплее
#----------------------------




kostyalamer 14.12.2009
< [ на главную ]




Hosted by uCoz