[TUTO] Mélanger 2 images suivant un masque en noir et blanc
Publié : sam. 05/juin/2010 13:30
L'idée est la suivante :

On part avec trois images de base , de la terre , de l'herbe , et un masque en noir est blanc.
Le calcul du mélange est très simple :
- Dans un premier , nous devons charger nos images grâce aux commandes fournies de PureBasic
en admettant que la taille de l'image A n'est pas la même que l'image B , nous allons tout mettre à l'échelle du masque , comme ça pas de problème
de taille.
Pour nous faciliter les calculs , nous allons mettre dans des tableaux à deux dimensions la couleur des images.
De cette manière , on pourra faire nos calculs tranquillement avec les tableaux , et non directement les images.
on doit maintenant remplir nos tableaux avec les couleurs respectives de chaques images.
notez le -1 aux lignes : "For y = 0 To Reference_SizeY - 1" , si vous ne le faites pas , y a des chances pour que votre programme plante à cause d'un dépassement de mémoire , n'oubliez pas que 0 compte pour 1 !
faites de même pour l'image B
pour le masque , c'est un peut différent , on se fiche de connaitre la couleur RGB , ce qui nous intéresse c'est la valeur du niveau de gris , de 0 ( noir ) à 255 ( blanc )
aucune fonctions ne renvois cela , mais une petite opération de base nous permet de connaitre cette valeur :
Image_C_Color() contient donc une valeur entre 0 et 255.
ps : si vous vous amusez à créer une image à partir de ce tableau , votre image sera un dégradé de noir vers le rouge.
Nous avons tout ce qui faut pour mélanger nos couleurs , nous devons créer une image vide qui nous servira de "sortie" :
ensuite nous allons parcourir nos tableaux et extraire les composantes des couleurs pour nos opérations :
pour simplifié nos calculs , nous allons convertir la valeur du masque qui va de 0 à 255 à une valeur qui va de 0 à 1.
en admettant que Red_A = 255 et que value = 0.5 ( la moitié de 1 ) :
resultat sera égal à 127.5 , la moitié aussi de 255 , simple calcul , non ?
reprenons notre formule vue toute en haut du topic :
et pour finir un petit :
Voilà , vous savez mélanger 2 images à partir d'un masque ! 
Code complet (sans médias):

On part avec trois images de base , de la terre , de l'herbe , et un masque en noir est blanc.
Le calcul du mélange est très simple :
nous allons voir comment mettre en place facilement cette "formule".couleur = (couleur_a * masque) + (couleur_b * (1-masque))
- Dans un premier , nous devons charger nos images grâce aux commandes fournies de PureBasic
Code : Tout sélectionner
Image_A = LoadImage(#PB_Any,"Dirt.jpg") ; La terre
Image_B = LoadImage(#PB_Any,"Grass.jpg") ; L'herbe
Mask = LoadImage(#PB_Any,"masque.png") ; le masque
de taille.
Code : Tout sélectionner
Reference_SizeX = ImageWidth(Mask)
Reference_SizeY = ImageHeight(Mask)
ResizeImage(Image_A,Reference_SizeX,Reference_SizeY)
ResizeImage(Image_B,Reference_SizeX,Reference_SizeY)
Code : Tout sélectionner
Dim Image_A_Color(Reference_SizeX,Reference_SizeY)
Dim Image_B_Color(Reference_SizeX,Reference_SizeY)
Dim Image_C_Color(Reference_SizeX,Reference_SizeY)
on doit maintenant remplir nos tableaux avec les couleurs respectives de chaques images.
Code : Tout sélectionner
StartDrawing(ImageOutput(Image_A))
For y = 0 To Reference_SizeY - 1
For x = 0 To Reference_SizeX - 1
Image_A_Color(x,y) = Point(x,y)
Next
Next
StopDrawing()
faites de même pour l'image B
pour le masque , c'est un peut différent , on se fiche de connaitre la couleur RGB , ce qui nous intéresse c'est la valeur du niveau de gris , de 0 ( noir ) à 255 ( blanc )
aucune fonctions ne renvois cela , mais une petite opération de base nous permet de connaitre cette valeur :
avec ce petit calcul , vous pouvez rendre n'importe quelle image en niveau de gris.niveau de gris = ( Composante rouge + Composante verte + composante bleue ) / 3
Code : Tout sélectionner
StartDrawing(ImageOutput(Mask))
For y = 0 To Reference_SizeY - 1
For x = 0 To Reference_SizeX - 1
Color = Point(x,y)
Image_C_Color(x,y) = (Red(Color) + Green(Color) + Blue(Color) ) / 3
Next
Next
StopDrawing()
ps : si vous vous amusez à créer une image à partir de ce tableau , votre image sera un dégradé de noir vers le rouge.
Nous avons tout ce qui faut pour mélanger nos couleurs , nous devons créer une image vide qui nous servira de "sortie" :
Code : Tout sélectionner
Sortie = CreateImage(#PB_Any,Reference_SizeX,Reference_SizeY)
Code : Tout sélectionner
StartDrawing(ImageOutput(Sortie))
For y = 0 To Reference_SizeY - 1
For x = 0 To Reference_SizeX - 1
Red_A = Red(Image_A_Color(x,y))
Green_A = Green(Image_A_Color(x,y))
Blue_A = Blue(Image_A_Color(x,y))
Red_B = Red(Image_B_Color(x,y))
Green_B = Green(Image_B_Color(x,y))
Blue_B = Blue(Image_B_Color(x,y))
Code : Tout sélectionner
Value.f = Image_C_Color(x,y) / 255
Code : Tout sélectionner
Resultat.f = Red_A * Value
reprenons notre formule vue toute en haut du topic :
elle se traduit ainsi :couleur = (couleur_a * masque) + (couleur_b * (1-masque))
Code : Tout sélectionner
Value.f = Image_C_Color(x,y) / 255
Red = (Red_A * Value) + (Red_B * (1-Value))
Green = (Green_A * Value) + (Green_B * (1-Value))
Blue = (Blue_A * Value) + (Blue_B * (1-Value))
Plot(x,y,RGB(Red,Green,Blue))
Next
Next
StopDrawing()
Code : Tout sélectionner
SaveImage(Sortie,"Sortie.bmp")

Code complet (sans médias):
Code : Tout sélectionner
UseJPEGImageDecoder()
UseJPEGImageEncoder()
UsePNGImageDecoder()
Image_A = LoadImage(#PB_Any,"Dirt.jpg")
Image_B = LoadImage(#PB_Any,"Grass.jpg")
Mask = LoadImage(#PB_Any,"masque.png")
Reference_SizeX = ImageWidth(Mask)
Reference_SizeY = ImageHeight(Mask)
ResizeImage(Image_A,Reference_SizeX,Reference_SizeY)
ResizeImage(Image_B,Reference_SizeX,Reference_SizeY)
Dim Image_A_Color(Reference_SizeX,Reference_SizeY)
Dim Image_B_Color(Reference_SizeX,Reference_SizeY)
Dim Image_C_Color(Reference_SizeX,Reference_SizeY)
StartDrawing(ImageOutput(Image_A))
For y = 0 To Reference_SizeY - 1
For x = 0 To Reference_SizeX - 1
Image_A_Color(x,y) = Point(x,y)
Next
Next
StopDrawing()
StartDrawing(ImageOutput(Image_B))
For y = 0 To Reference_SizeY - 1
For x = 0 To Reference_SizeX - 1
Image_B_Color(x,y) = Point(x,y)
Next
Next
StopDrawing()
StartDrawing(ImageOutput(Mask))
For y = 0 To Reference_SizeY - 1
For x = 0 To Reference_SizeX - 1
Color = Point(x,y)
Image_C_Color(x,y) = (Red(Color) + Green(Color) + Blue(Color) ) / 3
Next
Next
StopDrawing()
Sortie = CreateImage(#PB_Any,Reference_SizeX,Reference_SizeY)
StartDrawing(ImageOutput(Sortie))
For y = 0 To Reference_SizeY - 1
For x = 0 To Reference_SizeX - 1
Red_A = Red(Image_A_Color(x,y))
Green_A = Green(Image_A_Color(x,y))
Blue_A = Blue(Image_A_Color(x,y))
Red_B = Red(Image_B_Color(x,y))
Green_B = Green(Image_B_Color(x,y))
Blue_B = Blue(Image_B_Color(x,y))
Value.f = Image_C_Color(x,y) / 255
Red = (Red_A * Value) + (Red_B * (1-Value))
Green = (Green_A * Value) + (Green_B * (1-Value))
Blue = (Blue_A * Value) + (Blue_B * (1-Value))
Plot(x,y,RGB(Red,Green,Blue))
Next
Next
StopDrawing()
SaveImage(Sortie,"Sortie.bmp")