Fonction remplissage (FillArea)

Partagez votre expérience de PureBasic avec les autres utilisateurs.
comtois
Messages : 5186
Inscription : mer. 21/janv./2004 17:48
Contact :

Fonction remplissage (FillArea)

Message par comtois »

Code : Tout sélectionner

; Comtois
; 02/07/05
 
; La fonction FillArea() est un peu limitée , elle impose de connaitre à l'avance la couleur de bord.
; Dans ce programme , la couleur du tracé est aléatoire ,donc impossible d'utiliser FillArea ,du moins pas à ma connaissance .

; La fonction Remplissage() est lente pour des grandes zones à remplir
; Pour tester faites des petites formes fermées (cercles ou autres) avec la souris en maintenant le bouton gauche de la souris
; Et utilisez le bouton droit de la souris pour remplir une zone d'une couleur aléatoire.
; [F1] pour effacer l'écran

; Delta limite la zone de remplissage à partir de la position de la souris 
; Mettre 800 pour prendre en compte la totalité de l'écran
; ou changez les paramètres de remplissage() de cette façon remplissage(MouseX(), MouseY(), 0, 0, 800, 600, Random($FFFFFF))


InitSprite()
InitKeyboard()
InitMouse()
OpenScreen(800,600,32,"Remplissage")

Enumeration
    #Fond
    #Souris
    #Temoin
EndEnumeration
   
CreateSprite(#Fond,800,600)
CreateSprite(#Souris,3,3)
StartDrawing(SpriteOutput(#Souris))
Box(0,0,3,3,RGB(255,255,255))
StopDrawing()

;Delta limite la zone de remplissage à partir de la position de la souris 
Delta = 100 

Procedure remplissage(xx, yy, MinX, MinY, MaxX, MaxY, c)
    ;Toutes les options de remplissage sont envisageables en modifiant légèrement ce code
    
    ;La version originale de ce code se trouve ici (ainsi que les explications)
    ;http://raphaello.univ-fcomte.fr/IG/Algorithme/Algorithmique.htm#remplissage
    
    ;Remarque : j'ai ajouté les paramètres Min et Max ,
    ;parce qu'une personne sur le forum anglais m'a demandé comment faire pour limiter la zone de remplissage.
    
    Psp = 1
    Dim Px(1000)
    Dim Py(1000)
    Px(0) = xx
    Py(0) = yy
    FrontColor(Red(c), Green(c), Blue(c))
    
    lim = Point(xx, yy)
    If MinX < 0 : MinX = 0 : EndIf
    If MinY < 0 : MinY = 0 : EndIf
    If MaxX > SpriteWidth(#Fond)  : MaxX = SpriteWidth(#Fond)  : EndIf
    If MaxY > SpriteHeight(#Fond) : MaxY = SpriteHeight(#Fond) : EndIf
    
    While Psp <> 0
        xi = Px(Psp - 1)
        xf = Px(Psp - 1)
        x  = Px(Psp - 1)
        y  = Py(Psp - 1)
        
        x + 1
        cp = Point(x, y)
        While cp = lim And x < MaxX
            xf = x
            x + 1
            cp = Point(x,y)
        Wend
        
        x = Px(Psp - 1) - 1
        cp = Point(x, y)
        
        While cp = lim And x > MinX
            xi = x
            x - 1
            cp = Point(x, y)
        Wend
        
        LineXY(xi, y, xf, y)
        Psp - 1
        
        ; Y + 1
        x = xf
        While x >= xi And y < MaxY
            cp = Point(x, y + 1)
            While (((cp <> lim) Or (cp = c)) And (x >= xi))
                x - 1
                cp = Point(x, y + 1)
            Wend
            If ((x >= xi) And (cp = lim) And (cp <> c))
                Px(Psp) = x
                Py(Psp) = y + 1
                Psp + 1
            EndIf
            cp = Point(x, y + 1)
            While (( cp = lim ) And ( x >= xi ))
                x - 1
                cp = Point(x,y+1)
            Wend
        Wend
        
        ; Y - 1
        x = xf
        While x >= xi And y > MinY
            cp = Point(x, y - 1)
            While (((cp <> lim) Or (cp = c)) And (x >= xi))
                x - 1
                cp = Point(x, y - 1)
            Wend
            If ((x >= xi) And (cp = lim) And (cp <> c))
                Px(Psp) = x
                Py(Psp) = y - 1
                Psp + 1
            EndIf
            cp = Point(x, y - 1)
            While (( cp = lim ) And ( x >= xi ))
                x - 1
                cp = Point(x, y - 1)
            Wend
        Wend
    Wend
EndProcedure


Repeat
    FlipBuffers()
    ExamineMouse()
    ExamineKeyboard()
    DisplaySprite(#Fond,0,0)
    DisplaySprite(#Souris, MouseX(), MouseY())
    
    ;Efface le fond
    If KeyboardPushed(#PB_Key_F1)
        StartDrawing(SpriteOutput(#Fond))
        Box(0,0,SpriteWidth(#Fond) ,SpriteHeight(#Fond) , 0)
        StopDrawing()
    EndIf    
    
    ;trace des formes 
    If MouseButton(1)
        StartDrawing(SpriteOutput(#Fond))
        Line(MouseX(),MouseY(),-MouseDeltaX(),-MouseDeltaY(), Couleur)
        StopDrawing()
    Else
        Couleur = Random($FFFFFF)
    EndIf 
    
    ;Remplissage
    If MouseButton(2)
        StartDrawing(SpriteOutput(#Fond))
        remplissage(MouseX(), MouseY(),MouseX() - Delta, MouseY() - Delta, MouseX() + Delta, MouseY() + Delta, Random($FFFFFF))
        StopDrawing()
    EndIf   
    
Until KeyboardPushed(#PB_Key_Escape) 
Avatar de l’utilisateur
Jacobus
Messages : 1559
Inscription : mar. 06/avr./2004 10:35
Contact :

Message par Jacobus »

Tout simplement excellent, mérite d'être poussé dans les fonctionnalités.
Merci pour ce bel exemple ! :D
Quand tous les glands seront tombés, les feuilles dispersées, la vigueur retombée... Dans la morne solitude, ancré au coeur de ses racines, c'est de sa force maturité qu'il renaîtra en pleine magnificence...Jacobus.
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

la meme chose !

Code : Tout sélectionner

Procedure remplis(*hdc,x,y,couleur_remplissage)
  pinceau=CreateSolidBrush_(couleur_remplissage)
  SelectObject_(*hdc,pinceau)
  ExtFloodFill_(*hdc,x,y,GetPixel_(*hdc,x,y),#FLOODFILLSURFACE)
  DeleteObject_(pinceau)
  ReleaseDC_(WindowID(),*hdc)
EndProcedure
on appel ainsi :

Code : Tout sélectionner

  *dc=StartDrawing(ScreenOutput())   
       remplis(*dc,x,y,RGB(rouge,vert,bleu) )  
  StopDrawing()


:D
Anonyme2
Messages : 3518
Inscription : jeu. 22/janv./2004 14:31
Localisation : Sourans

Message par Anonyme2 »

Dobro,

je pense que la procedure est mieux comme ceci

Code : Tout sélectionner

Procedure remplis(*hdc,x,y,couleur_remplissage)
  pinceau=CreateSolidBrush_(couleur_remplissage)
  If pinceau
     AncienneBrush = SelectObject_(*hdc,pinceau)
     If AncienneBrush
        ExtFloodFill_(*hdc,x,y,GetPixel_(*hdc,x,y),#FLOODFILLSURFACE)
        SelectObject_(*hdc,AncienneBrush)
     EndIf
     DeleteObject_(pinceau)
  EndIf
EndProcedure
si tu utilises SelectObject_, tu vas changer soit la brush, soit le pen soit la police du hdc

Dès que ton opération est terminée, il faut remettre dans le hdc l'ancien objet

Je pense que ReleaseDc est inutile les commandes Startdrawing() et StopDrawing() se charge de libérer correctement le hdc
Backup
Messages : 14526
Inscription : lun. 26/avr./2004 0:40

Message par Backup »

ok ! :D
Avatar de l’utilisateur
Thyphoon
Messages : 2706
Inscription : mer. 25/août/2004 6:31
Localisation : Eragny
Contact :

Message par Thyphoon »

Désolé de remonté ce vieux topic.

J'utilise le code de comtois (le premier) pour analyser le contenue d'une piece dans une map fait de tile. ça marche plutôt bien sauf que dans certain cas le "remplissage" passe en diagonal. Vous voyez ce que je veux dire ?
Quelqu'un sait comment je peux corriver ce petite bug ?
Répondre