« Pygame/Introduction au module Surfarray » : différence entre les versions

Contenu supprimé Contenu ajouté
NewBorn (discussion | contributions)
NewBorn (discussion | contributions)
Relecture
Ligne 1 :
{{Pygame}}
=Introduction=
Ce tutoriel a pour objectif d'introduire ensemble aux utilisateurs les modules Numeric et Surfarray de pygame. Pour les débutants, le code qui utilise surfarray peut être légèrement intimidant. Mais ici, il y a seulement quelques concepts à comprendre et vous serez opérationnel. En utilisant le module surfarray, il devient possible de réaliser des opérations au niveau du pixel en utilisant du code python pur. Les compétences requises pour faire cela en C sont d'un niveau beaucoup plus difficilement accessible.
 
Traduit de l'anglais, original par ''Pete Shinners'' :<br/>
Vous pouvez avoir envie d'aller directement voir à la section ''"Exemples"'' pour avoir une idée ce ce qu'il est possible de faire avec ce module, alors commençons par le commencement, en vous montrant le chemin.
http://www.pygame.org/docs/tut/surfarray/SurfarrayIntro.html
 
{{Remarqueampoule|1=''Note du traducteur'' :<br/>
Maintenant, je ne vais pas essayer de vous flouer en vous faisant penser que chaque chose est évidente. Pour savoir réaliser des effets puissants, il faut modifier les images au niveau des pixels, et c'est un peu compliqué. Maîtriser simplement Numeric Python (Numpy) constitue déjà un apprentissage ardu. Dans ce tutoriel, je serai rapide avec ce qui est facile et je vais utiliser beaucoup d'exemple avec pour objectif de semer les graines de la connaissance. Après avoir fini la lecture de ce tutorial, vous devriez comprendre les bases du fonctionnement de surfarray.
Le projet [http://sourceforge.net/project/showfiles.php?group_id=1369&package_id=1351 Numeric], auquel il est fait référence dans ce tutoriel, a engendré le projet [http://sourceforge.net/project/showfiles.php?group_id=1369&package_id=32367 Numarray], qui lui-même a engendré le projet [http://numpy.scipy.org/ NumPy], lequel est maintenant intégré au projet [http://www.scipy.org/ SciPy] (ouf!). D'après quelques lectures ([http://wiki.python.org/moin/NumericAndScientific 1], [http://numpy.scipy.org//#older_array 2], [http://sourceforge.net/project/showfiles.php?group_id=1369 3]), NumPy '''''devrait''''' être entièrement compatible avec les 2 projets précédents. A vérifier également la compatibilité de Pygame avec NumPy.}}
 
== Introduction ==
=Numeric Python=
Si la paquet python Numeric n'est pas installé, vous en aurez besoin maintenant. Vous pouvez télécharger le paquet depuis [http://sourceforge.net/project/showfiles.php?group_id=1369 cette adresse]. Pour être certain que Numeric fonctionne chez vous, vous devriez télécharger quelque chose essayer quelque chose depuis le prompt python en mode interactif.
>>> '''from Numeric import *''' ''#import numeric''
>>> '''a = array((1,2,3,4,5))''' ''#create an array''
>>> '''a''' ''#display the array''
array([1, 2, 3, 4, 5])
>>> '''a[2]''' ''#index into the array''
3
>>> '''a*2''' ''#new array with twiced values''
array([ 2, 4, 6, 8, 10])
Comme vous pouvez le voir, le module Numeric fournit un nouveau type de données, le ''tableau''. Cet objet contient un tableau de taille fixée, et toutes les valeurs qu'il contient sont du même type. Les tableaux peuvent aussi être multidimensionnels, et nous les utiliserons ce cette manière avec les images. Il y a quelques suppléments à en dire, mais c'est pour l'instant, c'est suffisant pour commencer.
 
Ce tutoriel a pour objectif d'introduire les utilisateurs à Numeric et au module Surfarray de Pygame. Pour les débutants, le code utilisé par Surfarray peut être légèrement intimidant. Mais ici, il y a seulement quelques concepts à comprendre et vous serez opérationnel. En utilisant le module Surfarray, il devient possible de réaliser des opérations au niveau du pixel en utilisant du code python pur. Les compétences requises pour faire cela en C sont d'un niveau beaucoup plus difficilement accessible.
Si vous observez la dernière commande ci-dessus, vous verrez que les opérations mathématiques sur les tableaux du module Numeric s'appliquent à toutes les valeurs du tableau. Ce fonctionnement est appelé "elementwise operations". Ces tableaux peuvent également utilisé la notation en ''slice'' comme les listes normales. La syntaxe du découpage en slice est la même que celle utilisée avec les objets python standards. ''(donc révisez la si besoin est)''
 
Vous pouvez avoir envie d'aller directement voir à la section [[Pygame/Introduction au module Surfarray#Exemples|Exemples]] pour vous faire une idée sur ce qu'il est possible de faire avec ce module, ensuite nous commençerons par le début pour vous montrer la manière d'y arriver.
Voici quelques exemples de ce que je réalise avec le module numpy :
 
Maintenant, je ne vais pas essayer de vous flouer en vous faisant penser que tout est simple. L'obtention d'effets puissants en modifiant les valeurs de chaque pixels est très complexe. Commencer à maîtriser Numeric constitue déjà un apprentissage ardu. Dans ce tutoriel, je serai rapide avec ce qui est facile et je vais utiliser beaucoup d'exemples avec pour objectif de semer les graines de la connaissance. Après avoir fini la lecture de ce tutoriel, vous devriez comprendre les bases du fonctionnement de Surfarray.
>>> '''len(a)''' ''#get array size''
5
>>> '''a[2:]''' ''#elements 2 and up''
array([3, 4, 5])
>>> '''a[:-2]''' ''#all except last 2''
array([1, 2, 3])
>>> '''a[2:] + a[:-2]''' ''#add first and last''
array([4, 6, 8])
>>> '''array((1,2,3)) + array((3,4))''' ''#add arrays of wrong sizes''
Traceback (innermost last):
File "&lt;interactive input&gt;", line 1, in ?
ValueError: frames are not aligned
 
== Numeric Python ==
On obtient une erreur avec la dernière commande, en essayant d'ajouter deux tableaux de tailles différentes. Pour réaliser des opérations impliquant deux tableaux (impliquant la comparaison et les assignements) les deux tableaux doivent avoir les mêmes dimensions. Il est très important de savoir que les valeurs contenues dans un tableau créé depuis une tranche possède les mêmes références que les valeurs du tableau de départ. Donc modifier une valeur dans une ''tranche'' issue d'un tableau original, modifiera la valeur correspondante du tableau original. Cette propriété des tableaux est très importante à connaître.
 
Si la paquet python Numeric n'est pas installé, il est préférable de le faire maintenant. Vous pouvez télécharger le paquet depuis [http://sourceforge.net/project/showfiles.php?group_id=1369 cette adresse]. Pour être certain que Numeric fonctionne chez vous, vous devriez obtenir quelque chose de ce genre à partir du mode interactif de Python.
>>> <b>a</b> <i>#show our starting array</i>
array([1, 2, 3, 4, 5])
>>> <b>aa = a[1:3]</b> <i>#slice middle 2 elements</i>
>>> <b>aa</b> <i>#show the slice</i>
array([2, 3])
>>> <b>aa[1] = 13</b> <i>#chance value in slice</i>
>>> <b>a</b> <i>#show change in original</i>
array([ 1, 2, 13, 4, 5])
>>> <b>aaa = array(a)</b> <i>#make copy of array</i>
>>> <b>aaa</b> <i>#show copy</i>
array([ 1, 2, 13, 4, 5])
>>> <b>aaa[1:4] = 0</b> <i>#set middle values to 0</i>
>>> <b>aaa</b> <i>#show copy</i>
array([1, 0, 0, 0, 5])
>>> <b>a</b> <i>#show original again</i>
array([ 1, 2, 13, 4, 5])
 
<source lang="python">
Maintenant, nous jetterons un coup d'œil à de petits tableau à deux dimensions. Ne soyez pas trop inquiets, c'est la même chose que d'avoir un tuple à deux dimensions ''(un tuple dans un tuple)''. Commençons avec les tableaux à deux dimensions.
>>> from Numeric import * #Importer Numeric
>>> a = array((1,2,3,4,5)) #Créer un tableau
>>> a #Afficher le tableau
array([1, 2, 3, 4, 5])
>>> a[2] #Un index dans le tableau
3
>>> a*2 #Un nouveau tableau avec des valeurs doublées
array([ 2, 4, 6, 8, 10])
</source>
 
Comme vous pouvez le voir, le module Numeric nous fournit un nouveau type de données, le ''array''. Cet objet contient un tableau de taille fixe, et toutes les valeurs qu'il contient sont du même type. Les tableaux peuvent aussi être multidimensionnels, et c'est de cette manière nous les utiliserons avec les images. Il y aurait un peu plus à dire à leur sujet, mais c'est suffisant pour commencer.
>>> <b>row1 = (1,2,3)</b> <i>#create a tuple of vals</i>
>>> <b>row2 = (3,4,5)</b> <i>#another tuple</i>
>>> <b>(row1,row2)</b> <i>#show as a 2D tuple</i>
((1, 2, 3), (3, 4, 5))
>>> <b>b = array((row1, row2))</b> <i>#create a 2D array</i>
>>> <b>b</b> <i>#show the array</i>
array([[1, 2, 3],
[3, 4, 5]])
>>> <b>array(((1,2),(3,4),(5,6)))</b> <i>#show a new 2D array</i>
array([[1, 2],
[3, 4],
[5, 6]])
 
Si vous observez la dernière commande ci-dessus, vous verrez que les opérations mathématiques sur les tableaux du module Numeric s'appliquent à toutes les valeurs du tableau. Ce fonctionnement est appelé ''elementwise operations''. Ces tableaux peuvent également être ''slicés'' (découpés) à la façon des listes normales. La syntaxe du découpage en slice est la même que celle utilisée avec les objets python standards ''(donc révisez-la si besoin)''. Voici quelques exemples de plus sur le fonctionnement des tableaux :
Maintenant, avec ce tableau à deux dimensions ''(appelé à partir de maintenant un "2D")'', nous pouvons récupérer des valeurs spécifiques par leur index et faire des tranches dans les dimensions voulues. On utilise simplement un virgule pour séparer les indices qui nous permettent de chercher/séparer dans plusieurs dimensions. Utiliser simplement "''':'''" comme un index ''(ou pour ne pas fournir tous les indices)'' renvoie toutes les valeurs contenues sur cette dimension. Un exemple ci-dessous :
>>> <b>b</b> <i>#show our array from above</i>
array([[1, 2, 3],
[3, 4, 5]])
>>> <b>b[0,1]</b> <i>#index a single value</i>
2
>>> <b>b[1,:]</b> <i>#slice second row</i>
array([3, 4, 5])
>>> <b>b[1]</b> <i>#slice second row (same as above)</i>
array([3, 4, 5])
>>> <b>b[:,2]</b> <i>#slice last column</i>
array([3, 5])
>>> <b>b[:,:2]</b> <i>#slice into a 2x2 array</i>
array([[1, 2],
[3, 4]])
 
<source lang="python">
Bon, restez avec moi, c'est à peu près aussi dur que ça. En utilisant Numeric, il est possible d'utiliser quelque chose en plus que le slicing. L'utilisation de ''slices'' permet de spécifier un ''incrément de tranche''. La syntaxe pour une tranche avec incrément est :<br/>
>>> len(a) #Obtenir la taille du tableau
'''start_index : end_index : increment'''.<br/>
5
>>> a[2:] #Les éléments [2] et supérieurs
array([3, 4, 5])
>>> a[:-2] #Tous exceptés les 2 derniers
array([1, 2, 3])
>>> a[2:] + a[:-2] #Ajout le début et la fin
array([4, 6, 8])
>>> array((1,2,3)) + array((3,4)) #Ajout de tableau de tailles différentes
Traceback (innermost last):
File "&lt;interactive input&gt;", line 1, in ?
ValueError: frames are not aligned
</source>
 
On obtient une erreur avec la dernière commande, en essayant d'ajouter deux tableaux de tailles différentes. Pour réaliser des opérations impliquant deux tableaux (incluant les comparaisons et les assignations) les deux tableaux doivent avoir les mêmes dimensions. Il est très important de savoir que les valeurs contenues dans un tableau créé depuis le slice d'un original possède les mêmes références que les valeurs du tableau de départ. Donc modifier une valeur dans un slice issue d'un tableau original, modifiera la valeur correspondante du tableau original. Cette propriété des tableaux est très importante à retenir.
>>> '''c = arange(10)''' ''#like range, but makes an array''
>>> '''c''' ''#show the array''
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> '''c[1:6:2]''' ''#slice odd values from 1 to 6''
array([1, 3, 5])
>>> '''c[4::4]''' ''#slice every 4th val starting at 4''
array([4, 8])
>>> '''c[8:1:-1]''' ''#slice 1 to 8, reversed''
array([8, 7, 6, 5, 4, 3, 2])
 
<source lang="python">
Voilà. Vous avez assez d'informations pour vous permettre de commencer à utiliser le module surfarray avec le module Numeric. Les propriétés du module Numeric sont certainement plus consistantes, mais il s'ait d'une introduction. Par ailleurs, on veut seulement faire les trucs marrants, pas vrai ?
>>> a #Afficher le tableau de départ
array([1, 2, 3, 4, 5])
>>> aa = a[1:3] #Slicer 2 éléments intermédiaires
>>> aa #Afficher le slice
array([2, 3])
>>> aa[1] = 13 #Modifier une valeur dans le slice
>>> a #Afficher le changement dans l'original
array([ 1, 2, 13, 4, 5])
>>> aaa = array(a) #Faire une copie du tableau
>>> aaa #Afficher la copie
array([ 1, 2, 13, 4, 5])
>>> aaa[1:4] = 0 #Définir à 0 des valeurs intermédiaires
>>> aaa #Afficher la copie
array([1, 0, 0, 0, 5])
>>> a #Afficher l'original
array([ 1, 2, 13, 4, 5])
</source>
 
Maintenant, nous jetterons un coup d'œil à de petits tableau à deux dimensions. Ne soyez pas trop inquiets, c'est la même chose que d'avoir un tuple à deux dimensions (un tuple dans un tuple). Commençons avec des tableaux à deux dimensions.
=Importer le module surfarray=
 
<source lang="python">
Pour utiliser le module surfarray, nous avons besoin de l'importer. Les modules surfarray et Numeric sont des composants optionnels de pygame, il faut les importer correctement pour les utiliser. Dans ces examples, j'importe le module Numeric en utilisant une variable nommée N. Vous verrez ainsi quelles fonctions du module Numeric j'utilise. ''(et c'est beaucoup plus court que de taper Numeric avant chaque fonction.)''
>>> row1 = (1,2,3) #Créer un tuple
>>> row2 = (3,4,5) #Créer un second tuple
>>> (row1,row2) #Afficher comme un tuple 2D
((1, 2, 3), (3, 4, 5))
>>> b = array((row1, row2)) #Créer un tableau 2D
>>> b #Afficher le tableau
array([[1, 2, 3],
[3, 4, 5]])
>>> array(((1,2),(3,4),(5,6))) #Afficher un nouveau tableau 2D
array([[1, 2],
[3, 4],
[5, 6]])
</source>
 
Maintenant, avec ce tableau à deux dimensions (que l'on appellera à partir de maintenant un '''2D'''), nous pouvons récupérer des valeurs spécifiques par leur index et slicer dans les deux dimensions. L'utilisation d'une virgule pour séparer les indices, nous permet de chercher/slicer dans plusieurs dimensions. L'utilisation de "''':'''" comme un index (afin de ne pas fournir tous les indices) nous renvoie toutes les valeurs contenues sur cette dimension. Voyons son fonctionnement :
try:
import Numeric as N
import pygame.surfarray as surfarray
except ImportError:
raise ImportError, "Numeric and Surfarray are required."
 
<source lang="python">
=Introduction à Surfarray=
>>> b #Afficher la tableau précédent
Il y a deux types principaux de fonctions dans surfarray. Un des jeu de fonctions crée un tableau qui est une copie des données d'une surface de pixels. Les autres fonctions créent une copie par référence d'un tableau de pixels, donc changer la matrice modifie directement la surface originale. Il y a d'autres fonctions qui vous permettent d'accéder aux valeurs du canal alpha par pixel comme des tableaux, ainsi que plusieurs autres fonctions très utiles. Nous étudierons ces fonctions plus tard.
array([[1, 2, 3],
[3, 4, 5]])
>>> b[0,1] #Indexer une valeur unique
2
>>> b[1,:] #Slicer la seconde rangée
array([3, 4, 5])
>>> b[1] #Slicer la seconde rangée (idem ci-dessus)
array([3, 4, 5])
>>> b[:,2] #Slicer la dernière colonne
array([3, 5])
>>> b[:,:2] #Slicer en un tableau 2x2
array([[1, 2],
[3, 4]])
</source>
 
Bon, restez avec moi, c'est à peu près aussi dur que ça. En utilisant Numeric, il existe une fonctionnalité supplémentaire pour effectuer des slices. Le slice de tableau nous permet de spécifier un ''incrément de slice''. La syntaxe pour un slice avec incrément est <tt>index_debut : index_fin : increment</tt>.
En utilisant ces tableaux de surface, il y a deux moyens de représenter les valeurs des pixels. La première, peut être de les représenter comme un carte de nombre entiers. Ce type de tableau est un simple tableau 2D avec un simple entier qui représente la couleur du pixel correspondant. Ce type de tableau est pratique pour déplacer des parties d'une image. L'autre type de tableaux utilise trois valeurs pour représenter chaque pixel en codage RGB. Ce type de tableau rend extrêmement simple la réalisation d'effets qui modifie la couleur de chaque pixel. Ce type de matrice est également un peu délicat à manipuler, parce qu'il s'agit en fait d'un tableau à 3 dimensions. Si vous parvenez malgré tout à comprendre le truc, ce n'est pas très différent d'utiliser un tableau 2D normal.
 
<source lang="python">
Le module Numeric utilise une machine de nombres naturels pour représenter les données numériques, donc un tableau Numeric peut être constitué d'entier de 8bits, 16bits, et 32bits. (les tableaux peuvent également utiliser d'autres types comme des flottants et des doubles, mais pour notre manipulation d'image nous n'utilisons partiquement que des entiers). Du fait de la limitation en taille de certains entiers, vous devez veiller à ce que les tableaux contenant les données des pixels soient des tableaux dont les données sont du type adéquat. Les fonctions fabriquant ces tableaux depuis des surfaces sont :
>>> c = arange(10) #Comme range(), mais pour faire un tableau
>>> c #Afficher le tableau
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> c[1:6:2] #Slicer les valuers impaires entre 1 et 6
array([1, 3, 5])
>>> c[4::4] #Slicer toutes les 4 valeurs en démarrant à l'index 4
array([4, 8])
>>> c[8:1:-1] #Slice de 1 à 8 inversé
array([8, 7, 6, 5, 4, 3, 2])
</source>
 
Voilà. Vous en savez suffisamment pour vous permettre de commencer à utiliser Numeric avec le module Surfarray. Les propriétés du module Numeric sont certainement plus consistantes, mais il ne s'agit que d'une introduction. Par ailleurs, on veut seulement faire des trucs marrants, pas vrai ?
'''surfarray.pixels2d(surface)'''
 
== Importer le module Surfarray ==
Crée un tableau 2D (valeur entière pour les pixels) qui référence les données originales de la surface. Ceci va fonctionner pour tous les formats de surface, excepté les pixels sur 24 bits.
 
Pour utiliser le module Surfarray, nous avons besoin de l'importer. Les modules Surfarray et Numeric étant des composants optionnels de Pygame, il est judicieux de s'assurer de les importer correctement avant de les utiliser. Dans ces exemples, j'importerai le module Numeric dans une variable nommée N. Vous verrez ainsi quelles fonctions utilisées provient du module Numeric (et de plus c'est légèrement plus court que de taper Numeric devant chaque fonction).
'''surfarray.array2d(surface)'''
 
<source lang="python">
Crée un tableau 2D (valeur entière des pixels) copié depuis n'importe quel type de surface.
try:
import Numeric as N
import pygame.surfarray as surfarray
except ImportError:
raise ImportError, "Numeric and Surfarray are required."
</source>
 
== Introduction à Surfarray ==
'''surfarray.pixels3d(surface)'''
 
Il y a deux principaux types de fonctions dans Surfarray. Un des jeu de fonctions concerne la création d'un tableau qui est une copie des données de pixels d'une surface. L'autre jeu de fonctions crée une copie par référence d'un tableau de pixels, donc changer le tableau modifie directement la surface originale. Il y a d'autres fonctions qui vous permettent d'accéder aux valeurs du canal alpha de chaque pixel à l'aide de tableaux et de plusieurs autres fonctions très utiles. Nous étudierons ces fonctions plus tard.
Crée un tableau 3D (valeur des pixels codé en RVB) qui contient les données originales d'une surface. Cela va fonctionner exclusivement avec des surfaces sur 24 bits ou 32 bits qui ont un formattage RGB et BGR.
 
En utilisant ces tableaux de surface, il y a deux moyens de représenter les valeurs des pixels. La première, peut être de les représenter comme un carte de nombre entiers. Ce type de tableau est un simple tableau 2D avec un unique entier qui représente la couleur du pixel correspondant. Ce type de tableau est pratique pour déplacer des parties d'une image. L'autre type de tableaux utilise trois valeurs pour représenter chaque pixel en codage RGB. Ce type de tableau rend extrêmement simple la réalisation d'effets qui modifie la couleur de chaque pixel. Ce type de matrice est également un peu délicat à manipuler, puisqu'il s'agit en fait d'un tableau à 3 dimensions. Si vous parvenez malgré tout à comprendre le truc, ce n'est pas plus difficile que d'utiliser un tableau 2D normal.
'''surfarray.array3d(surface)'''
 
Le module Numeric utilise une machine de nombres naturels pour représenter les données numériques, donc un tableau Numeric peut être constitué d'entier de 8bits, 16bits, et 32bits. (les tableaux peuvent également utiliser d'autres types comme des flottants et des doubles, mais pour notre manipulation d'image nous n'utilisons partiquement que des entiers). Du fait de la limitation en taille de certains entiers, vous devez veiller à ce que les tableaux contenant les données des pixels soient des tableaux dont les données sont du type adéquat. Les fonctions fabriquant ces tableaux à partir de surfaces sont :
Crée un tableau 3D (valeurs des pixels en RGB) qui est copié depuis n'importe quel type de surface.
 
<source lang="python">
Voici un petit résumé qui devrait mieux montrer quels types de fonction devraient être utilisés et pour quelles surfaces. Comme vous pouvez le voir, les fonctions de type arrayXD vont fonctionner avec tous les types de surface.
surfarray.pixels2d(surface)
</source>
:Crée un tableau 2D (valeur des pixels entière) qui '''référence''' les données originales de la surface. Ceci fonctionnera pour tous les formats de surface excepté celles en 24 bits.
 
<source lang="python">
surfarray.array2d(surface)
</source>
:Crée un tableau 2D (valeur des pixels entière) '''copié''' depuis n'importe quel type de surface.
 
<source lang="python">
surfarray.pixels3d(surface)
</source>
:Crée un tableau 3D (valeur des pixels codé en RGB) qui '''référence''' les données originales d'une surface. Cela va fonctionner exclusivement avec des surfaces sur 24 bits ou 32 bits qui ont un formatage RGB et BGR.
 
<source lang="python">
surfarray.array3d(surface)
</source>
:Crée un tableau 3D (valeurs des pixels codé en RGB) '''copié''' depuis n'importe quel type de surface.
 
Voici un petit résumé qui devrait mieux illustrer quels types de fonctions devraient être utilisés sur quelles surfaces. Comme vous pouvez le voir, les fonctions de type arrayXD vont fonctionner avec tous les types de surface.
 
{| class="wikitable"
Ligne 168 ⟶ 196 :
| yes
|}
=Exemples=
Avec ces informations, nous sommes parés pour commencer à essayer quelque chose avec les tableaux de surface. Les petites démonstrations suivantes qui créent un tableau numpy et l'affichent dans pygame. Ces différents tests sont issus des exemples contenus dans le fichier arraydemo.py. Il y a une simple fonction nommée surfdemo_show qui affiche un tableau à l'écran.
 
== Exemples ==
==exemple 1 : création d'une image noire==
[[Image:http://www.pygame.org/docs/tut/surfarray/allblack.jpg]]
allblack = N.zeros((128, 128))
surfdemo_show(allblack, 'allblack')
Dans notre premier exemple, nous créons un tableau tout noir de 128 lignes sur 128 colonnes. Pour créer un tableau numérique avec un taille déterminée, il est préférable d'utiliser la fonction zeros. Ici, le tableau de zéro forme une surface noire.
 
Avec ces informations, nous sommes parés pour commencer à essayer diverses choses avec les tableaux de surface. Les petites démonstrations suivantes créent un tableau Numeric et l'affichent dans pygame. Ces différents tests sont issus des exemples contenus dans le fichier <tt>arraydemo.py</tt>. Il y a une fonction simple nommée <tt>surfdemo_show()</tt> qui affiche un tableau à l'écran.
==exemple 2 : tableaux de 3 dimensions, séparation des composantes RVB==
[[Image:http://www.pygame.org/docs/tut/surfarray/striped.jpg]]
striped = N.zeros((128, 128, 3))
striped[:] = (255, 0, 0)
striped[:,::3] = (0, 255, 255)
surfdemo_show(striped, 'striped')
Ici nous manipulons un tableau à 3 dimensions. On commence par créer une image rouge. Alors on extrait un ligne sur trois et on lui donne la couleur bleu/vert. Comme vous pouvez le constater, nous pouvons traiter les tableaux à trois dimensions presque comme un tableau à deux dimensions, seulement on lui assigne des 3-uplets au lieu de valeurs uniques (scalaires).
 
==exemple= 3 : extraction des donnéesCréation d'une image depuis unnoire fichier===
 
[[Image:http://www.pygame.org/docs/tut/surfarray/imgarray.jpg]]
<source lang="python">
imgsurface = pygame.image.load('surfarray.jpg')
allblack = N.zeros((128, 128))
imgarray = surfarray.array2d(imgsurface)
surfdemo_show(imgarrayallblack, 'imgarrayallblack')
</source>
Ici nous chargeons une image avec le module image, qui la convertit en un tableau 2D d'entiers. Nous utiliserons cette image comme base dans le reste de nos exemple.
 
[http://www.pygame.org/docs/tut/surfarray/allblack.jpg Image exemple : allblack.jpg]
 
Dans notre premier exemple, nous créons un tableau entièrement noir de 128 lignes sur 128 colonnes. Pour créer un tableau numérique avec un taille déterminée, il est préférable d'utiliser la fonction <tt>N.zeros()</tt>. Ici, le tableau de zéro forme une surface noire.
<br style="clear:both;" />
 
=== Tableaux de 3 dimensions (séparation des composantes RGB) ===
 
<source lang="python">
striped = N.zeros((128, 128, 3))
striped[:] = (255, 0, 0)
striped[:,::3] = (0, 255, 255)
surfdemo_show(striped, 'striped')
</source>
 
[http://www.pygame.org/docs/tut/surfarray/striped.jpg Image exemple : striped.jpg]
 
Ici nous manipulons un tableau à 3 dimensions. On commence par créer une image rouge. Ensuite nous extrayons une ligne sur trois et nous lui donnons la couleur bleu/vert. Comme vous pouvez le constater, nous pouvons traiter les tableaux à trois dimensions presque comme un tableau à deux dimensions, seulement on lui assigne des 3-uplets au lieu de valeurs uniques (scalaires).
<br style="clear:both;" />
 
=== Extraction des données d'une image depuis un fichier ===
 
<source lang="python">
imgsurface = pygame.image.load('surfarray.jpg')
imgarray = surfarray.array2d(imgsurface)
surfdemo_show(imgarray, 'imgarray')
</source>
 
[http://www.pygame.org/docs/tut/surfarray/imgarray.jpg Image exemple : imgarray.jpg]
 
Ici nous chargeons une image avec la fonction <tt>image.load()</tt> qui la convertit en un tableau 2D d'entiers. Nous utiliserons cette image comme base dans le reste de nos exemples.
<br style="clear:both;" />
 
=== Retournement ''miroir'' vertical ===
 
<source lang="python">
flipped = imgarray[:,::-1]
surfdemo_show(flipped, 'flipped')
</source>
 
[http://www.pygame.org/docs/tut/surfarray/flipped.jpg Image exemple : flipped.jpg]
 
==exemple 4 : retournement ''miroir'' vertical==
[[Image:http://www.pygame.org/docs/tut/surfarray/flipped.jpg]]
flipped = imgarray[:,::-1]
surfdemo_show(flipped, 'flipped')
Voici un retournement vertical de l'image, réalisé en utilisant la notation en ''slices'' à l'aide d'un incrément négatif pour l'indice des colonnes.
<br style="clear:both;" />
 
=== Miniaturisation d'une image ===
 
<source lang="python">
scaledown = imgarray[::2,::2]
surfdemo_show(scaledown, 'scaledown')
</source>
 
[http://www.pygame.org/docs/tut/surfarray/scaledown.jpg Image exemple : scaledown.jpg]
 
Diminuer une image repose sur le même principe que l'exemple précédent. Ici, la notation en slices est utilisée pour conserver seulement un pixel sur deux à la fois verticalement et horizontalement.
<br style="clear:both;" />
 
=== Augmentation de la taille d'une image ===
 
<source lang="python">
size = N.array(imgarray.shape)*2
scaleup = N.zeros(size)
scaleup[::2,::2] = imgarray
scaleup[1::2,::2] = imgarray
scaleup[:,1::2] = scaleup[:,::2]
surfdemo_show(scaleup, 'scaleup')
</source>
 
[http://www.pygame.org/docs/tut/surfarray/scaleup.jpg Image exemple : scaleup.jpg]
 
Augmenter la taille d'une image n'est pas aussi radicalement simple, mais s'inspire de la diminution que nous avons réalisé en utilisant les slices. D'abord, nous créons un tableau qui est de deux fois la taille de l'original. On réalise une copie du tableau original, pixel par pixel, en écrivant seulement sur les colonnes paires du tableau de destination, puis on réalise à nouveau l'opération en écrivant seulement sur les colonnes impaires du tableau de destination. A ce stade, nous avons image redimensionnée correctement, mais toutes les lignes impaires sont noires. Il nous suffit alors de recopier chaque ligne paire sur la ligne du dessous. On obtient ainsi une image dont la taille a doublé.
<br style="clear:both;" />
 
=== Filtrage de canaux ===
 
<source lang="python">
==exemple 5 : miniaturisation d'une image==
rgbarray = surfarray.array3d(imgsurface)
[[Image:http://www.pygame.org/docs/tut/surfarray/scaledown.jpg]]
redimg = N.array(rgbarray)
scaledown = imgarray[::2,::2]
redimg[:,:,1:] = 0
surfdemo_show(scaledown, 'scaledown')
surfdemo_show(redimg, 'redimg')
Diminuer une image repose sur le même principe que l'exemple précédent. Ici, la notation en ''slices'' est utilisée pour conserver seulement un pixel sur deux à la fois verticalement et horizontalement.
</source>
 
[http://www.pygame.org/docs/tut/surfarray/redimg.jpg Image exemple : redimg.jpg]
==exemple 6 : augmentation de la taille d'une image==
[[Image:http://www.pygame.org/docs/tut/surfarray/scaleup.jpg]]
size = N.array(imgarray.shape)*2
scaleup = N.zeros(size)
scaleup[::2,::2] = imgarray
scaleup[1::2,::2] = imgarray
scaleup[:,1::2] = scaleup[:,::2]
surfdemo_show(scaleup, 'scaleup')
Augmenter la taille d'une image n'est pas aussi radicalement simple, mais s'inspire de la diminution que nous avons réalisé en utilisant la notation en tranches. D'abord, nous créons un tableau qui est de deux fois la taille de l'original. On réalise une copie du tableau original, pixel par pixel, en écrivant seulement sur les colonnes et les lignes de rang pair du tableau de destination, puis on réalise à nouveau l'opération en écrivant seulement sur les colonnes et les lignes de rang impair du tableau de destination. On obtient ainsi une image dont la taille a doublé.
 
Retour vers les tableaux 3D, on utilisera le codage RGB pour modifier les couleurs. On fait un simple tableau 3D à partir de l'image originale, en utilisant la méthode <tt>surfarray.array3D()</tt>, puis toutes les valeurs pour le bleu et le vert sont mises à zéro. Il nous reste alors, uniquement le canal rouge.
==exemple 7 : création d'une image rouge==
<br style="clear:both;" />
[[Image:http://www.pygame.org/docs/tut/surfarray/redimg.jpg]]
rgbarray = surfarray.array3d(imgsurface)
redimg = N.array(rgbarray)
redimg[:,:,1:] = 0
surfdemo_show(redimg, 'redimg')
 
=== Filtrage par convolution ===
Ici, on utilise le codage RGB pour modifier les couleurs. On fait un simple tableau 3D à partir de l'image originale, en utilisant la méthode ''surfarray.array3D()'', puis toutes les valeurs pour le bleu et le vert (''Green'' et ''Blue'') sont mises à zéro. Le codage de l'information est réalisé seulement avec la composante rouge de l'image.
 
<source lang="python">
==exemple 8 : filtrage par convolution==
soften = N.array(rgbarray)
soften[1:,:] += rgbarray[:-1,:]*8
soften[:-1,:] += rgbarray[1:,:]*8
soften[:,1:] += rgbarray[:,:-1]*8
soften[:,:-1] += rgbarray[:,1:]*8
soften /= 33
surfdemo_show(soften, 'soften')
</source>
 
[[Image:http://www.pygame.org/docs/tut/surfarray/soften.jpg] Image exemple : soften.jpg]
soften = N.array(rgbarray)
soften[1:,:] += rgbarray[:-1,:]*8
soften[:-1,:] += rgbarray[1:,:]*8
soften[:,1:] += rgbarray[:,:-1]*8
soften[:,:-1] += rgbarray[:,1:]*8
soften /= 33
surfdemo_show(soften, 'soften')
 
On réalise ici une convolution à l'aide d'un filtre 3x3 qui va adoucir les reliefs de l'image. Cela paraît lourd en calculs, mais ce qui est fait est en fait de décaler l'image de 1 pixel dans toutes les directions, et de sommer toutes ces images (en multipliant par un certain coefficient de poids). Alors, on moyenne toutes les valeurs obtenues. Ce n'est pas un filtre gaussien, mais c'est rapide.
<br style="clear:both;" />
 
=== Décoloration ===
==exemple 9 : décoloration==
[[Image:http://www.pygame.org/docs/tut/surfarray/xfade.jpg]]
src = N.array(rgbarray)
dest = N.zeros(rgbarray.shape)
dest[:] = 20, 50, 100
diff = (dest - src) * 0.50
xfade = src + diff.astype(N.Int)
surfdemo_show(xfade, 'xfade')
 
<source lang="python">
Enfin, Nous réalisons une décoloration croisée entre l'image originale et une fond entièrement en bleu. Ce n'est pas très folichon, mais l'image de destination peut être n'importe quoi, et en modifiant le coefficient multiplicateur (0.50 dans l'exemple), vous pouvez choisir l'intensité de la décoloration pour votre image.
src = N.array(rgbarray)
dest = N.zeros(rgbarray.shape)
dest[:] = 20, 50, 100
diff = (dest - src) * 0.50
xfade = src + diff.astype(N.Int)
surfdemo_show(xfade, 'xfade')
</source>
 
[http://www.pygame.org/docs/tut/surfarray/xfade.jpg Image exemple : xfade.jpg]
==conclusion==
J'espère qu'à ce stade, vous avez des idées d'utilisation pour le module surfarray, dans la réalisation d'effets spéciaux et de transformations d'image, seulement réalisables au niveau du pixel. Au minimum, vous pouvez utiliser surfarray pour faire quelques opérations rapides avec'''Surface.set_at()''' et '''Surface.get_at()'''. Mais ne pensez pas que vous en avez terminé, il vous reste encore beaucoup à apprendre.
 
Enfin, Nous réalisons une décoloration croisée entre l'image originale et une fond entièrement en bleu. Ce n'est pas très folichon, mais l'image de destination peut être n'importe quoi, et en modifiant le coefficient multiplicateur (0.50 dans l'exemple), vous pouvez choisir chaque étape pour un fondu linéaire entre deux images.
=Verrouillage de surface=
<br style="clear:both;" />
 
=== Conclusion ===
Also be aware that you really don't want to be doing much (if any) direct pixel access on hardware surfaces (HWSURFACE). This is because the actual surface data lives on the graphics card, and transferring pixel changes over the PCI/AGP bus is not fast.
Comme le reste de pygame, surfarray va verrouiller tout objet de type surface lors de l'accès aux données de pixels. C'est une chose dont il faut être conscient dans tout ce que vous faisez. En créant un tableau de données de pixels, la surface originale sera verrouillée pendant le temps d'existence du tableau de donnée. Il est important de s'en rappeler? Soyez certain d'avoir ''supprimé'' le tableau de pixels ou de le laisser en dehors du champ du programme ? espace de nommage ? (c'est à dire lors des retours de fonction).to "del" the pixel array or let it go out of scope
 
J'espère qu'à partir de maintenant vous commencez à voir comment le module Surfarray peut-être utilisé pour réaliser des effets spéciaux et/ou transformations qui ne sont possibles qu'à partir d'une manipulation de pixels. Au minimum, vous pouvez utiliser Surfarray pour faire un grand nombre d'opérations très rapides de type <tt>Surface.set_at()</tt> et <tt>Surface.get_at()</tt>. Mais ne pensez pas que vous en ayez terminé avec ce module, il vous reste encore beaucoup à apprendre.
=Transparence=
 
== Verrouillage de surface ==
Le module surfarray a plusieurs méthodes pour accéder aux valeur du canal alpha d'une surface. Aucune des fonctions qui gèrent le canal alpha n'ont d'effet sur le reste des données de la surface, seulement aux valeurs des pixels pour le canal alpha. Voici la liste de ces fonctions :
 
Comme le reste de Pygame, Surfarray va verrouiller tout objet de type Surface lors de l'accès aux données de pixels. C'est une chose dont il faut être conscient dans tout ce que vous faites. En créant un tableau de données de pixels, la surface originale sera verrouillée pendant le temps d'existence du tableau de donnée. Il est important de s'en rappeler. Soyez certain d'avoir supprimé le tableau de pixels soit explicitement avec l'instruction Python : <tt>del</tt>, soit implicitement en sortant de l'espace de nom et ainsi faire intervenir le ''garbage collector'' (comme par exemple après un retour de fonction).
 
Faites attention à ne pas accéder directement à des surfaces en hardware (''HWSURFACE''). Car les données de ces surfaces résident dans la mémoire de la carte graphique, et le transfert de modifications de pixels à travers le bus PCI/AGP n'est pas des plus rapide.
 
== Transparence ==
 
Le module Surfarray possède plusieurs méthodes pour accéder aux valeurs du canal alpha/couleur clé d'une surface. Aucune des fonctions qui gèrent le canal alpha, n'a d'effet sur le reste des données de la surface, uniquement sur les valeurs du canal alpha des pixels. Voici la liste de ces fonctions :
 
;surfarray.pixels_alpha(surface)
:Crée un tableau 2D de valeurs entières qui contient'''référence''' les valeurs du canal alpha des pixels d'une surface. Ceci fonctionne uniquement avec les images codées sur 32 bits par pixel, avec un canal alpha sur huit8 bits.
 
;surfarray.array_alpha(surface)
:Crée un tableau 2D de valeurs entières qui contient'''copie''' les valeurs du canal alpha des pixels d'une surface. Ceci fonctionne avec tous les types de surface,. siSi l'image d'origine ne contient aucun canal alpha, les valeurs du tableau sont initialisées à ''255'', qui est la valeur maximale d'opacité.
 
;surfarray.array_colorkey(surface)
:Creates a 2D array (integer pixel values) that is set to transparent (0) wherever that pixel color matches the Surface colorkey. Crée un tableau 2D de valeurs entières qui met la transparence à 0 (valeur maximale de transparence) pour chaque pixel de la surface dont la couleur correspond à la couleur de la surface ? '''traduction incertaine'''clé.
 
== Autres fonctions du module Surfarray ==
 
Il existe quelques autres fonctions disponibles dans le module Surfarray. Vous pouvez en obtenir une liste exhaustive ainsi qu'une description plus complète sur la page de [http://pygame.seul.org/docs/ref/surfarray.html référence]. Notez malgré tout cette fonction très utile :
;Autres fonctions du module surfarray.
:There are only a few other functions available in surfarray. You can get a better list with more documentation on the surfarray reference page. There is one very useful function though.
Il existe quelques autres fonctions disponibles dans le module surfarray. Vous pouvez en obtenir une liste exhaustive ainsi qu'une description plus complète sur la page de référence. Notez malgré tout cette fonction très utile :
 
;surfarray.blit_array(surface, array)
:This will transfer any type of 2D or 3D surface array onto a Surface of the same dimensions. This surfarray blit will generally be faster than assigning an array to a referenced pixel array. Still, it should not be as fast as normal Surface blitting, since those are very optimized.
Ceci va transformertransférer tout type de tableau 2D ou 3D ensur une surface possédant les mêmes dimensions. CetteCe fonctionblit surfarrayde Surfarray sera généralement beaucoup plus rapide que d'assigner un tableau qui contiendrait les pixels de références. Néanmoins, ça ne devrait pas être plus rapide qu'uneun animationblit normalenormal d'imageune à l'écransurface, carpuisque ceuxcelui-ci sontest très optimisésoptimisé.
'''traduction incertaine'''
 
== Utilisation plus avancée de Numeric ==
 
Voici deux dernière choses qu'il est bon de connaître à propos des tableaux de Numeric. En manipulant des tableautableaux de très grande taille, comme par exemple des grandes surfaces de 640x480, vous devrez veiller à deuxcertaines choses en particulier. D'abord, même si les opérateurs + et * utilisés avec les tableaux sont très pratiques, ils sont également très coûteux en temps de calcul sur les grands tableaux. Ces opérateurs doivent réaliser des nouvelles copies temporaires des tableaux, qui sont alors habituellement copiées dans un autre tableau. Cela peut prendre énormément de temps. Heureusement, tous les opérateurs du module Numeric sont fournit avec des fonctions spéciales qui sont plus performantes et peuvent être utilisées en lieu et place des opérateurs. Par exemple, vous pourriez remplacer <tt>screen[:] = screen + brightmap</tt> par la fonction plus rapide <tt>add(screen, brightmap, screen)</tt>. Toutefois, lisez la documentation concernant les [http://numpy.scipy.org/numpydoc/numpy-7.html#pgfId-36126 ''Numeric Ufuncs''] pour en savoir plus à leur sujet. C'est important lors de la manipulation des tableaux.
En manipulant les tableaux avec des valeurs de pixel codés sur 16 bits, Numeric n'utilise pas des entiers non signés sur 16 bits, donc certaines de vos valeurs seront des nombres négatifs signés. Heureusement ça ne pose pas de problème.
 
Une autre chose à laquelle il faut veiller en utilisant des tableaux est le type de données manipulé. Certains tableaux (particulièrement les surfaces de pixels ''mappées'', en codage RGB) retourne des tableaux avec des valeurs sur 8 bits non signés. Ces tableaux peuvent facilement provoquer un dépassement de capacité si vous n'êtes pas très attentifs.Le module Numeric possède les mêmes contraintes que vous trouverez dans le langage C, c'est à dire qu'une opération avec un nombre en 8 bits et un nombre en 32 bits va renvoyer un nombre en 32 bits. Vous pouvez toujours convertir le type de donnée d'un tableau, mais soyez toujours certain du type que contienne les tableaux que vous manipulez. S'il arrive une situation dans laquelle un dépassement de capacité est provoqué, Numeric va lever une exception.
D'abord, si, les opérateurs + et * utilisés avec les tableaux sont très pratiques, ils sont également très coûteux en temps de calcul sur les grands tableaux. Ces opérateurs doivent réaliser des nouvelles copies temporaires des tableaux, qui sont alors copiées dans un autre tableau habituellement. Cela peut prendre énormément de temps. Heureusement, le module Numeric fournit certaines fonctions spéciales. Par exemple, vous pourrez remplacer l'opération
 
'''>>> screen[:] = screen + brightmap'''
 
par l'opérateur plus rapide add(screen, brightmap, screen). Lisez la documentation de Numeric Ufunc pour en savoir plus à ce propos. C'est important de savoir bien manipuler les tableaux.
En manipulant des tableaux avec des valeurs de pixel codés sur 16 bits, Numeric n'utilise pas des entiers non signés sur 16 bits, donc certaines de vos valeurs seront des nombres négatifs signés. Heureusement ça ne pose pas de problème.
 
Enfin, vous devez faire attention lorsque vous assignez des valeurs dans un tableau à trois dimensions, celles-ci doivent être comprises entre 0 et 255, sinon vous obtiendrez des erreurs de troncatures indéfinies.
Une autre chose à laquelle il faut veiller en utilisant des tableaux est le type de données manipulé. Quelques tableaux (particulièrement les surfaces de pixels ''mappées'', en codage RGB) utilisent des valeurs sur huit bits non signés. Un dépassement est très facilement généré si vous n'êtes pas attentifs. Numeric utilise le même fonctionnement que le langage C? c'est à dire que d'additionner, par exemple, une valeur sur huit bits et une valeur sur 32 bits va renvoyer un nombre sur 32 bits. Vous pouvez toujours convertir le type d'un tableau, mais soyez toujours certain du type que contiennent les tableaux que vous manipulez. S'il arrive une situation dans laquelle un dépassement de capcité est provoqué, Numeric va lever une exception
Enfin, vous devez faire attention à, en assignant des valeurs dans un tableau de trois dimensions, elles doivent être comprises en tre 0 et 255, où vous allez générer des erreurs de troncatures indéfinies.
 
== Remise du Diplôme ==
Enfin, soyez prudent dans vos assignations de tableaux, un dépassement peut générer une erreur de troncature indéfinie.
 
Ok, vous l'avez, ma formation rapide sur Numeric python et Surfarray. Espérons que maintenant vous voyez ce qu'il est possible de faire, et que si vous ne l'avez jamais utilisé vous-même, vous ne serez pas effrayé à la vue de ces codes. Regardez dans l'exemples <tt>vgrade.py</tt> pour plus d'actions sur les tableaux Numeric. Il existe également quelques démonstrations "enflammées" qui utilisent Surfarray pour créer un effet de liquide en temps réel.
=Remise du Diplôme=
Le mieux est toujours d'essayer des choses par vous même. Allez-y tranquillement au début, et construisez au fur et à mesure. J'ai vu des choses très intéressantes faites avec Surfarray comme des gradients radiaux et d'autres choses dans le genre. Bonne Chance.
Ok, vous l'avez. Ma formation rapide sur Numeric python et surfarray. Espérons que maintenant vous voyez ce qu'il est possible de faire, et que si l'utilisez à votre tour, vous ne serez pas effrayé pour écrire le code correspondant. Regardez dans les exemples de vgrade pour plus de tableaux numeric en action. Il existe également quelques démonstrations "enflammées" qui utilisent surfarray pour créer un effet de flammes en temps réel.
Le mieux est toujours d'essayer des choses par vous même. Allez y doucement en premier, et augmentez au fur et à mesure. J'ai vu des choses très intéressantes faites avec surfarray comme des gradients radiaux et d'autres choses dans le genre. Bonne chance.