Page 1 sur 1

[TUTO] Mélanger 2 images suivant un masque en noir et blanc

Publié : sam. 05/juin/2010 13:30
par G-Rom
L'idée est la suivante :

Image
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 :
couleur = (couleur_a * masque) + (couleur_b * (1-masque))
nous allons voir comment mettre en place facilement cette "formule".


- 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
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.

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)
Pour nous faciliter les calculs , nous allons mettre dans des tableaux à deux dimensions la couleur des images.

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)
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.

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() 
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 :
niveau de gris = ( Composante rouge + Composante verte + composante bleue ) / 3
avec ce petit calcul , vous pouvez rendre n'importe quelle image en niveau de gris.

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() 
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" :

Code : Tout sélectionner

Sortie          = CreateImage(#PB_Any,Reference_SizeX,Reference_SizeY)
ensuite nous allons parcourir nos tableaux et extraire les composantes des couleurs pour nos opérations :

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))
pour simplifié nos calculs , nous allons convertir la valeur du masque qui va de 0 à 255 à une valeur qui va de 0 à 1.

Code : Tout sélectionner

Value.f   = Image_C_Color(x,y) / 255
en admettant que Red_A = 255 et que value = 0.5 ( la moitié de 1 ) :

Code : Tout sélectionner

Resultat.f  =  Red_A * Value
resultat sera égal à 127.5 , la moitié aussi de 255 , simple calcul , non ?
reprenons notre formule vue toute en haut du topic :
couleur = (couleur_a * masque) + (couleur_b * (1-masque))
elle se traduit ainsi :

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()
et pour finir un petit :

Code : Tout sélectionner

SaveImage(Sortie,"Sortie.bmp")
Voilà , vous savez mélanger 2 images à partir d'un masque ! :wink:


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")

Re: [TUTO] Mélanger 2 images suivant un masque en noir et bl

Publié : sam. 05/juin/2010 14:11
par lepiaf31
yeah ca pourrait m'être utile prochainement, merci =)

Re: [TUTO] Mélanger 2 images suivant un masque en noir et bl

Publié : sam. 05/juin/2010 15:26
par Backup
Tuto numero 46 ;)

Re: [TUTO] Mélanger 2 images suivant un masque en noir et bl

Publié : sam. 05/juin/2010 15:45
par Ar-S
Merci G-Rom, clair et précis (et joli rendu en plus) :)

Re: [TUTO] Mélanger 2 images suivant un masque en noir et bl

Publié : sam. 05/juin/2010 17:47
par SPH
Les 4 premieres images parlent d'elles memes. Ca rend tout de suite tres bien !

Re: [TUTO] Mélanger 2 images suivant un masque en noir et bl

Publié : dim. 06/juin/2010 12:40
par venom
Un si petit code pour un beau rendu.
Merci G-Rom pour ce tuto :wink:








@++