2011-03-23 2 views
0

Voici le code que je utilise en ce moment:Cairo (w/Python): Est-il possible de remplir un polygone avec une ligne transparente?

surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, *image.size) 
context = cairo.Context(surface) 
context.set_source_rgba(1, 1, 1, 1) 
context.new_path() 
for i in xrange(len(points)): 
    context.line_to(*points[i]) 

context.close_path() 
context.fill() 

Le problème est qu'il remplit le polygone avec la même couleur que je dessine. J'ai essayé de dessiner un nouveau polygone sur celui-ci et de faire juste context.stroke() au lieu de fill() mais cela ne fonctionne que si j'utilise une couleur différente, sinon la couleur blanche est sous. J'ai essayé avec (0,0,0,0) donc ce serait transparent, mais alors le blanc est en dessous.

Je peux dessiner une ligne de couleur (par exemple (0.5,0.5,0.5,1)), enregistrez-le sur une image avec write_to_png, chargez avec PIL, convertir en numpy.array et remplacer chaque pixel avec la bonne couleur avec la couleur d'arrière-plan (0, 0, 0, 0), mais ce n'est pas efficace.

J'ai également essayé de définir la largeur de ligne à 0 et cela ne fonctionne pas non plus.

Aussi, je vais bien avec d'autres méthodes qui me permettent de faire ce qui ne sont pas le Caire. J'ai essayé le polygon d'ImageDraw mais il ne dessine pas la forme exacte (je ne suis pas sûr de savoir comment l'expliquer, mais il attire en quelque sorte des pixels supplémentaires à l'extérieur du polygone), ainsi ImageDraw n'aidera pas moi.

+0

Je ne comprends pas exactement ce que vous voulez. On ne "remplit" pas une forme avec une "ligne" - que voulez-vous faire? Si vous voulez juste le contour du polygone, essayez d'utiliser ".stroke()" au lieu de ".fill()". Si vous souhaitez que la couleur de dessin soit transparente, utilisez des valeurs intermédiaires pour Alpha (le 4ème composant sur la couleur - vous le définissez toujours sur 1) – jsbueno

+0

lorsque j'utilise le remplissage, trace un contour sur le polygone. Je ne veux pas ce contour/ligne. – pppphhhhuuuu

Répondre

0

Je l'ai maintenant. SO, il n'y a aucun moyen de le faire - toutes les API de dessin 2D sur le style de Cairo supposent que "remplir" inclut la bordure. Cela fonctionne de la sorte sur la plupart des backends que rend le Caire, comme Postscript et SVG, donc il est difficile d'imaginer comment cela pourrait être différent. La méthode "propre" consiste à itérer sur votre polygone pour générer des points qui ne délimitent que la zone que vous avez remplie, c'est-à-dire que vous devez calculer vous-même la zone de ligne.

Votre hack, d'un autre côté, semble intelligent, il n'est pas possible de le faire entièrement au Caire car il s'agit de raster. Mais au lieu de sauvegarder sur le disque et de recharger, il y a d'autres façons de le faire - par exemple, vous pouvez utiliser les données de surface Cairo comme surface SDL dans Pygame pour simuler des opérations de "copier-coller".

http://doswa.com/blog/2010/03/29/using-cairo-in-pygame/ http://www.pygame.org/wiki/CairoPygame

(En fait, je ,. essayé de penser à un flux de travail en utilisant Pyagame et ne pouvait pas - les options pour manipuler les pixels alpha et copier/coller il est plutôt limité).

Ma dernière suggestion pour vous: N'utilisez pas pycairo pour cela - Vérifiez si l'API GIMP Python vous convient. GIMP est un programme de dessin 2D complet avec une API complète pouvant être utilisée depuis Python. Vous pouvez dessiner vos polygones avec des objets "Vecteurs" GIMP, et bien que le "remplissage" inclura également la ligne de polygone, il y a un "gimp_selection_shrink" que vous pouvez appeler jsut avant le remplissage, par exemple. Ou, vous pouvez utiliser des couches pour obtenir l'effet exact que vous voulez. Depuis l'intérieur de GIMP, vous pouvez vérifier l'ensemble de l'API dans le menu de la base de données Aide-> Procédure. Une fois que votre script est prêt, il est possible d'exécuter GIMP avec une ligne coomand pour exécuter votre programme, sans avoir besoin d'un affichage graphique.

Voici le flux de travail dont vous avez besoin à l'aide pygimp:

  • Créer des vecteurs GIMP objet avec vos points de poligon: pdb.gimp_image_add_vectors, pdb.gimp_vectors_stroke_new_from_points
  • Créer une nouvelle couche (dessus de la couche avec l'image vous souhaitez conserver le long de la ligne) pdb.gimp_layer_new (il existe d'autres fonctions qui doivent être appelées pour lier la couche à l'image)
  • Convertir votre polygone en sélection - pdb.gimp_vectors_to_selection
  • Remplir la nouvelle couche, avec le pdb.gimp_edit_bucket_fill de couleur souhaitée
  • Convertir la sélection pour une sélection « épaisse » avec pdb.gimp_selection_border
  • pixels coupés à partir de la couche - pdb.gimp_Edit_cut
  • de fusion de la nouvelle couche dans votre image précédente - pdb.gimp_image_merge_down
1
fill_preserve() 
context.set_source_rgba(0, .6, 1, .7) #line color 
context.set_line_width(2.35) 
context.stroke() 
Questions connexes