Page 1 sur 2

Selection et contour

Publié : jeu. 23/juil./2015 8:40
par blendman
salut

Toujours pour mon soft de dessin, je travaille en ce moment sur les sélections. Ensuite, je dois pouvoir copier/couper, coller , déplacer, transformer ou faire une rotation de sélection, peindre dessus, la supprimer, etc..
Bref, beaucoup de travail en perspective ^^.

Pour certaines sélections, c'est assez facile (rectangle de sélection), mais pour d'autres, je n'ai aucune idée de la marche à suivre ^^.

Voici les sélections sur lesquelles j'ai commencé à travailler :
- masque de sélection : à peu près ok
- sélectionner l'alpha d'un calque : à peu près ok (en fait, je sélectionne les pixels non transparents)
- rectangle de sélection : ok, ça c'est très facile ^^.
- baguette magique : pas ok
- lasso : pas ok

J'aimerais trouver un moyen de récupérer les pixels non transparents :
- avec un lasso : pour ça je n'ai pas trop d'idée.
- avec une baguette magique : je pensais peut-être à une technique ressemblant au fillarea()
- pouvoir ajouter ou retirer des pixels de la sélection (par exemple, en utilisant un rectangle de sélection pour ajouter ou enlever des surfaces de pixels) : avec un rectangle de sélection, c'est assez simple, je peux ajouter ou supprimer les pixels contenus dans la zone de mon rectangle de sélection.

Si vous avez des idées ou des suggestions, n'hésitez pas ;).

Re: Selection et contour

Publié : jeu. 23/juil./2015 9:11
par djes
A mon avis, il faut faire à la façon de photoshop, c'est à dire avec des couches alpha. Une sélection = une couche alpha. Le lasso, c'est un dessin à main levé dans une couche alpha, avec antialiasing (plus ou moins fort). La baguette magique (pixels contigus) c'est un algo de remplissage avec tolérance qui allume ou pas les pixels dans la couche alpha.

Re: Selection et contour

Publié : jeu. 23/juil./2015 11:20
par Ar-S
+1 Spock & Djes, à mon avis ce sont les 2 méthodes de détourages utilisées par tohop et les autres.

Re: Selection et contour

Publié : jeu. 23/juil./2015 13:05
par blendman
@spock : je comprends l'idée, puisque c'est ce que je pensais faire ^^. Maintenant, il faut que je mette ça en pratique :)

djes a écrit :A mon avis, il faut faire à la façon de photoshop, c'est à dire avec des couches alpha. Une sélection = une couche alpha. Le lasso, c'est un dessin à main levé dans une couche alpha, avec antialiasing (plus ou moins fort). La baguette magique (pixels contigus) c'est un algo de remplissage avec tolérance qui allume ou pas les pixels dans la couche alpha.
pour le moment, c'est ce que je pensais aussi ^^.

Pour la baguette magique, j'ai trouvé un algo de remplissage de Comtois qui fonctionne super bien, il manque juste la tolérance (des pixels plus ou moins proches du pixel sélectionné), mais sinon, ça me semble une bonne technique pour la baguette magique : http://www.purebasic.fr/english/viewtop ... 566#p94566
Mais par contre, je ne sais encore comment je vais convertir ça en couche alpha.



Sinon, voici un essai que j'ai réalisé pour le mask alpha :

Code : Tout sélectionner

; Alpha selection
; by blendman jully 2015

Global w, h
w = 1024
h = 768

Enumeration ; sprite
  
  #Sp_Layer
  #Sp_LayerTempo
  #Sp_Checker
  #Sp_Selection
    
EndEnumeration
Enumeration ;Image
  
  #Img_Layer
  #Img_LayerTempo
  #Img_AlphaSel
  
EndEnumeration

CreateImage(#Img_Layer,w,h,32,#PB_Image_Transparent)
CreateImage(#Img_LayerTempo,w,h,32,#PB_Image_Transparent)
CreateImage(#Img_AlphaSel,w,h,32,#PB_Image_Transparent)

;{ procedure
Procedure cb(x,y,top,bottom)
  ; by wilbert
  If (x!y) & 8; checkerboard pattern
    ProcedureReturn top
  Else 
    ProcedureReturn bottom
  EndIf
EndProcedure
Procedure Filtre_MaskAlpha(x, y, CouleurSource, CouleurDestination)
   ProcedureReturn (CouleurSource & $00FFFFFF) | (Alpha(CouleurSource)*Alpha(CouleurDestination)/255)<<24
EndProcedure
Procedure CanvasUpdate()
  If StartDrawing(SpriteOutput(#Sp_Layer))
    
    ; Box(0, 0, w, h, RGB(160,160,160))
    DrawingMode(#PB_2DDrawing_AlphaChannel)
    Box(0,0,w,h,RGBA(0,0,0,0))
    
    DrawingMode(#PB_2DDrawing_AlphaBlend)
    DrawAlphaImage(ImageID(#Img_Layer),0,0)
    
    
    DrawAlphaImage(ImageID(#Img_AlphaSel),0,0)   
    ; draw the painting
    DrawingMode(#PB_2DDrawing_CustomFilter)
    CustomFilterCallback(@Filtre_MaskAlpha())       
    DrawAlphaImage(ImageID(#Img_LayerTempo),0,0)
    
    StopDrawing()
  EndIf 
  
  ClearScreen(RGB(160,160,160))
  DisplayTransparentSprite(#Sp_Checker,0,0)
  DisplayTransparentSprite(#Sp_Layer,0,0)
  DisplayTransparentSprite(#Sp_Selection,0,0)
  FlipBuffers()

EndProcedure
;}

InitSprite()

OpenWindow(0, 0, 0, w, h, "Selection and alpha", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
screenwidth = 1024
screenheight = 768

If OpenWindowedScreen(WindowID(0),0,0,w, h)=0
  MessageRequester("Error", "Can't Open Screen!", 0)
  End
EndIf

; the image
If StartDrawing(ImageOutput(#Img_Layer))
   DrawingMode(#PB_2DDrawing_AlphaChannel) 
   Box(0,0,w,h,RGBA(0,0,0,0))
   StopDrawing()
 EndIf
If StartDrawing(ImageOutput(#Img_LayerTempo))
   DrawingMode(#PB_2DDrawing_AlphaChannel) 
   Box(0,0,w,h,RGBA(0,0,0,0))
   StopDrawing()
 EndIf
If StartDrawing(ImageOutput(#Img_AlphaSel))
   DrawingMode(#PB_2DDrawing_AlphaChannel) 
    ; create the mask
   Circle(450,350,100,RGBA(0,0,0,255))
   Circle(305,240,145,RGBA(0,0,0,120))
   StopDrawing()
 EndIf
 
; the sprite (for the preview)
 CreateSprite(#Sp_Layer,w,h,#PB_Sprite_AlphaBlending)
 CreateSprite(#Sp_LayerTempo,w,h,#PB_Sprite_AlphaBlending)
 CreateSprite(#Sp_Selection,w,h,#PB_Sprite_AlphaBlending) 
 CreateSprite(#Sp_Checker,w,h,#PB_Sprite_AlphaBlending) ; the checker
 
If StartDrawing(SpriteOutput(#Sp_Checker))
   DrawingMode(#PB_2DDrawing_AlphaBlend)
   Box(0,0,w,h,RGBA(200,200,200,255))
   DrawingMode(#PB_2DDrawing_CustomFilter)
   CustomFilterCallback(@cb())  
   Box(0,0,w,h,RGBA(160,160,160,255))
  StopDrawing()
EndIf
If StartDrawing(SpriteOutput(#Sp_Selection))
  DrawingMode(#PB_2DDrawing_AlphaChannel)
  Box(0,0,w,h,RGBA(0,0,0,0))
  ;DrawingMode(#PB_2DDrawing_Outlined) ; <------------- here, I would like to find a way to see a selection border 
  ;                                                     based on the alpha of the shape (the two icrcle, in this exemple), 
  ;                                                     which could work With image( it's ok if I use only box(), circle()....
  ;DrawAlphaImage(ImageID(#Img_AlphaSel),0,0)   
  StopDrawing()
EndIf

CanvasUpdate()

Repeat
  
  Repeat
    
    Event = WaitWindowEvent(1)
    
    Select Event 
        
      Case #PB_Event_CloseWindow
        End
        
      Case #WM_LBUTTONDOWN ; left buton down
        paint = 1
        
      Case #PB_Event_LeftClick ; left buton up
        paint = 0
        
    EndSelect
    
  Until  event = 0
  
  If paint = 1
    If StartDrawing(ImageOutput(#Img_LayerTempo))
      DrawingMode(#PB_2DDrawing_AlphaBlend) 
      x = WindowMouseX(0)
      y = WindowMouseY(0)
      Circle(x, y, 50, RGBA(255,120,120,255))
      StopDrawing()
    EndIf
    CanvasUpdate()
    
  EndIf

ForEver


Re: Selection et contour

Publié : jeu. 23/juil./2015 15:28
par falsam
Ta baguette magique tu l'avais avec la réponse d'alter Mann qui me semblait pas mal.
http://www.purebasic.fr/english/viewtop ... 11#p468011

Re: Selection et contour

Publié : jeu. 23/juil./2015 16:36
par djes
Si je peux me permettre de répondre à la place de blendman, ça ne fait pas la même chose, c'est plus un algo de contouring, même s'il y a peut-être moyen de l'adapter.

Re: Selection et contour

Publié : jeu. 23/juil./2015 16:51
par falsam
Bonjour djes. Cette algo n'est pas le principe d'une baguette magique dont le principe est justement de sélectionner les contours ? Du moins j'ai connu ce fonctionnement sur Paint :p

Re: Selection et contour

Publié : jeu. 23/juil./2015 17:22
par blendman
@falsam : ce n'est pas tout à fait la même chose ^^. Là, il affiche un contour autour de ce qui est dessiné (d'ailleurs, je n'ai pas encore réussi à l'adapter avec de l'alpha). La baguette magique sélectionne les pixels identiques au pixel que tu choisis (avec point()), C'est plus proche d'un algo de remplissage à mon avis.

Re: Selection et contour

Publié : jeu. 23/juil./2015 17:50
par G-Rom
Pour la selection avec la baguette magique, c'est exactement le même algo que le filling , tu peu stocker tes pixels sélectionner dans un tableau de boolean , la baguette magique peu sélectionner les pixel contiguë ( algo de fill ) ou les tout les pixels de même valeur ( algo de comparaison ).

Pour le lasso à main levé , cela demande un peu plus de gymnastique , mais c'est aussi facilement faisable , je stockerais dans un premier temps dans une image temporaire ma courbe de sélection , dans un second temps , je calculerais le min/max ( la bouding box ) de ma selection , et dans un dernier temps je commencerais à appliqué un algo de filling a l'exterieur de ma bounding box, à partir de là tu as une image temporaire avec le dessin de ta selection , tu peu fabriqué un tableau de boolean à partir des couleur de ton image temporaire.

Re: Selection et contour

Publié : jeu. 23/juil./2015 20:39
par Fig
Concernant la baguette magique

http://www.purebasic.fr/french/viewtopi ... +de+france
Le deuxième listing permet de remplir une figure irrégulière fermée et d'en relever les contours.
Moyennant une petite modification, il peut, bien entendu, et sur le même principe, enregistrer les points de remplissage en fonction d'une tolérance de couleur.

Si personne n'a posté de code fonctionnel d'ici là, je le ferai ce week end.

Ps: quand j'avais 13 ans j'ai fait un soft de dessin, en fait la copie fonctionnel de OCP sur amstrad mais en overscan... ca me rappelle donc de bons souvenirs..; bon courage... :D
(Bon, selection rectangle uniquement, zoom et dessin au point par point seulement... sans internet les infos sur les algos etaient alors maigres...)

Re: Selection et contour

Publié : sam. 25/juil./2015 21:09
par Fig
Bon, c'est un code encore trop lent, il faudrait, je pense, l'optimiser en assembleur...
J'avais fait un code à base de dijkstra au départ mais je pensais qu'en implémentant à la place un "scanline", ça serait plus rapide...
Le code a été modifié pour un accès direct à la mémoire video. c'est un peu moins poussif...
La tolérance s'applique sur la composante Hue de la couleur dans cet exemple.

Re: Selection et contour

Publié : sam. 25/juil./2015 22:09
par falsam
Windows 8.1 - PB 5.31

L̶'̶e̶x̶e̶ ̶f̶r̶e̶e̶z̶e̶ ̶d̶e̶s̶ ̶q̶u̶e̶ ̶j̶e̶ ̶p̶r̶e̶s̶s̶e̶ ̶l̶a̶ ̶t̶o̶u̶c̶h̶e̶ ̶e̶s̶p̶a̶c̶e̶.̶ ̶

Re: Selection et contour

Publié : sam. 25/juil./2015 22:13
par Fig
Il freeze pas, "il réfléchit" sans tenir compte des events windows... :lol:

Recommence en plaçant le carré jaune qui indique ta souris sur une des figure geometrique (le petit carré vert pour commencer) puis presse espace.
Si tu as une optimisation je suis preneur...

Re: Selection et contour

Publié : sam. 25/juil./2015 22:15
par falsam
Fig a écrit :sans tenir compte des events windows...
:mrgreen:
S'agissant d'une baguette magique j'ai bien placé le carré jaune sur une figure géométrique. Je n'ai pas du assez attendre .....

Test again.

Re: Selection et contour

Publié : sam. 25/juil./2015 22:18
par falsam
Ok je n'ai rien dit. Ca fonctionne. Bizarre ce freeze que j'ai eu lors de mon premier test.