Skip to content

Instantly share code, notes, and snippets.

@JacquesDuflos
Created May 14, 2023 04:11
Show Gist options
  • Save JacquesDuflos/0a4914099d497631cff9211737e2f24f to your computer and use it in GitHub Desktop.
Save JacquesDuflos/0a4914099d497631cff9211737e2f24f to your computer and use it in GitHub Desktop.
a plug-in for python that draws a path around a text.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# GIMP plugin to draw convex hulls around shapes
# (c) Jacques Duflos 2023
#
# History:
#
# v0.0: 2023-xx-xx: First published version
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#credit https://gist.github.com/lvngd for the ConvexHull class
import random
import sys, os
from gimpfu import *
import gimpcolor
"""
Computes the Convex Hull with the Graham Scan algorithm
Use:
h = ConvexHull()
print(h.hull)
"""
debug = True
def trace(s):
if debug:
print "**** "
print s
print "**** "
trace("convex_hull test")
class ConvexHull:
def __init__(self, points):
if not points:
self.points = [(random.randint(0,100),random.randint(0,100)) for i in range(50)]
else:
self.points = points
self.hull = self.compute_convex_hull()
def get_cross_product(self,p1, p2, p3):
return ((p2[0] - p1[0])*(p3[1] - p1[1])) - ((p2[1] - p1[1])*(p3[0] - p1[0]))
def get_slope(self,p1, p2):
if p1[0] == p2[0]:
return float('inf')
else:
return 1.0*(p1[1]-p2[1])/(p1[0]-p2[0])
def compute_convex_hull(self):
hull = []
self.points.sort(key=lambda x:[x[0],x[1]])
start = self.points.pop(0)
hull.append(start)
self.points.sort(key=lambda p: (self.get_slope(p,start), -p[1],p[0]))
for pt in self.points:
hull.append(pt)
while len(hull) > 2 and self.get_cross_product(hull[-3],hull[-2],hull[-1]) < 0:
hull.pop(-2)
return hull
def PointsFromVectors(vectors):
num_strokes, ids = pdb.gimp_vectors_get_strokes(vectors)
listOfPoints = []
for stroke_id in ids:
type_, num_points, controlpoints, closed = pdb.gimp_vectors_stroke_get_points(vectors, stroke_id)
listOfPoints += controlpoints
trace(listOfPoints)
return listOfPoints
def ConvexHullVectors(image,vectors=None):
if vectors == None : vectors = pdb.gimp_image_get_active_vectors(image)
# get the list of every points of the vectors's stroke
listOfPoints = PointsFromVectors(vectors)
# organize the list to be compatible with the class
listOfPointsTupple=[]
while len(listOfPoints)>1:
listOfPointsTupple.append((listOfPoints.pop(0),listOfPoints.pop(0)))
trace ("list")
trace (listOfPointsTupple)
listOfPointsTupple = list(dict.fromkeys(listOfPointsTupple))
# todo : delet at once the duplicated consecutive points (when tengents are superposed with the point)
trace("list sans doublons")
trace(listOfPointsTupple)
h = ConvexHull(listOfPointsTupple)
trace ("convex hull")
trace (h.hull)
hull=h.hull
#triple each element to get a list with tengants
hull = [[i,i,i] for i in hull]
trace(hull)
hull = [item for sublist in hull for item in sublist]
trace(hull)
#flatten the hull to be easyer tu use with gimp
hullFlattened = [item for sublist in hull for item in sublist]
trace ("flattened")
trace (hullFlattened)
#create the new vector
hullVectors = pdb.gimp_vectors_new(image, "convex hull")
stroke_id = pdb.gimp_vectors_stroke_new_from_points(hullVectors, VECTORS_STROKE_TYPE_BEZIER , len(hullFlattened), hullFlattened, True)
pdb.gimp_image_insert_vectors(image, hullVectors, None, 0)
trace ("fini")
return hullVectors
def ConvexHullText(image,layer):
vectorsText = pdb.gimp_vectors_new_from_text_layer(image, layer)
ConvexHullVectors(image,vectorsText)
### Registrations
whoiam='\n'+os.path.abspath(sys.argv[0])
register(
'convex-hull',
'creer un convex hull autour d un texte %s' % whoiam,
'creer un convex hull autour d un texte',
'Jacques Duflos','Jacques Duflos','2023',
'creer un convex hull autour d un texte...',
'*',
[
(PF_IMAGE, 'image', 'Image', None),
(PF_DRAWABLE, 'drawable', 'Drawable', None)
],
[],
ConvexHullText,
menu='<Image>/Layer'
)
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment