2011-05-05 7 views
7

У меня есть pygame Surface и вы хотите инвертировать цвета. Есть ли способ быстрее & больше pythonic, чем это? Это довольно медленно.Как инвертировать цвета изображения в pygame?

Я знаю, что вычитание значения из 255 не является единственным определением «инвертированного цвета», но это то, что я хочу сейчас.

Я удивлен, что в pygame нет такого встроенного!

Благодарим за помощь!

import pygame 

def invertImg(img): 
    """Inverts the colors of a pygame Screen""" 

    img.lock() 

    for x in range(img.get_width()): 
     for y in range(img.get_height()): 
      RGBA = img.get_at((x,y)) 
      for i in range(3): 
       # Invert RGB, but not Alpha 
       RGBA[i] = 255 - RGBA[i] 
      img.set_at((x,y),RGBA) 

    img.unlock() 

ответ

6

Ответ Winston хорош, но для полноты, когда нужно манипулировать пиксельным пикселем изображения на Python, следует избегать цикла через каждый пиксель, независимо от того, какая библиотека изображений используется. Это интенсивность процессора из-за характера языка и редко может быть использована для работы в реальном времени.

К счастью, отличный NumPy библиотека может помочь выполнить несколько скалярных операций в поток байтов, зацикливание над каждым номером в машинный код, который на несколько порядков быстрее, чем делать это исключительно в Python. Для этой конкретной операции, если мы используем операцию xor с (2^32 - 1), мы можем делегировать операцию внутреннему циклу в собственном коде.

Этот пример, который можно вставить непосредственно в консоли Python, щелкнет пиксели мгновенно белый (если у вас есть NumPy установлен):

import pygame 

srf = pygame.display.set_mode((640,480)) 
pixels = pygame.surfarray.pixels2d(srf) 
pixels ^= 2 ** 32 - 1 
del pixels 

pygame.display.flip() 

без установленного NumPy, pygame.surfarray методы возвращают обычные массивы Python (из модуля массива stdlib), и вам придется найти другой способ работы с этими числами, поскольку обычный массив Python не работает со всеми элементами, когда задана строка, такая как pixels ^= 2 ** 32 - 1.

+0

numpy is awesome, я использую его практически в каждом проекте python –

+0

Отлично! Я должен научиться и использовать Numpy. –

+0

@jsbueno Мне любопытно, почему вы сделали «дель пикселей»? –

1

Один подход, который может быть более эффективным было бы использовать PIL, как описано здесь: How to invert colors of image with PIL (Python-Imaging)?

Это легко преобразовать его в родной Pygame образ в памяти, как описано здесь: http://mail.python.org/pipermail/image-sig/2005-May/003315.html

+0

Спасибо, но я стараюсь избегать дополнительных модулей и уже посвятил себя pygame. Я должен был упомянуть об этом раньше, извините! –

+3

@ В Британии, нет. Огромная сила python - это огромное количество кода, уже написанного для вас. Вам не хватает, если вы не добавляете модуль, который помогает вам поддерживать то, что вы хотите. –

+0

@Winston: Однако, поскольку ваши и мои ответы обозначают, PIL - это не лучшая вещь для этого - преобразование между данными изображения между PIL и поверхностями Pygame является болезненным само по себе. – jsbueno

6

Взято из: http://archives.seul.org/pygame/users/Sep-2008/msg00142.html

def inverted(img): 
    inv = pygame.Surface(img.get_rect().size, pygame.SRCALPHA) 
    inv.fill((255,255,255,255)) 
    inv.blit(img, (0,0), None, BLEND_RGB_SUB) 
    return inv 

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