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
|