A plug-in that I don't know if it's going to work or not for client yet but it works for my intended purpose But it's probably a basic enough functionality that I thought I would share.
#!/usr/bin/env python
# Author: Tin Tran
# Created On: 2024.11.03
# License: Open source whatever the GIMP's license is.
# Revisions:
# 0.1 Initial Version
from gimpfu import *
import os
import math
def same_shape(image,layer,tilelayer):
pdb.gimp_image_select_item(image,CHANNEL_OP_REPLACE,tilelayer)
mean_,std_dev,median,pixels,count1,percentile = pdb.gimp_drawable_histogram(tilelayer,HISTOGRAM_VALUE,0,1)
pdb.gimp_image_select_item(image,CHANNEL_OP_REPLACE,layer)
pdb.plug_in_sel2path(image,layer)
active_vectors = pdb.gimp_image_get_active_vectors(image)
num_strokes,stroke_ids = pdb.gimp_vectors_get_strokes(active_vectors)
shapes = []
#make new layer to put work on
work_layer = pdb.gimp_layer_new(image,image.width,image.height,RGBA_IMAGE,layer.name+" after plugin",100,LAYER_MODE_NORMAL)
pdb.gimp_image_insert_layer(image,work_layer,None,0)
for i in range(0,num_strokes):
temp_vectors = pdb.gimp_vectors_new(image,"shape" + str(i+1))
pdb.gimp_image_insert_vectors(image,temp_vectors,None,0)
type_,num_points,controlpoints,closed = pdb.gimp_vectors_stroke_get_points(active_vectors,stroke_ids[i])
stroke_new = pdb.gimp_vectors_stroke_new_from_points(temp_vectors,type_,num_points,controlpoints,closed)
pdb.gimp_image_select_item(image,CHANNEL_OP_REPLACE,temp_vectors)
mean_,std_dev,median,pixels,count,percentile = pdb.gimp_drawable_histogram(layer,HISTOGRAM_VALUE,0,1)
#if within 1 percentage difference, we consider it the same shape
if (abs(count-count1)<count1*0.01):
pdb.gimp_edit_copy(layer)
float_sel = pdb.gimp_edit_paste(work_layer,TRUE)
pdb.gimp_floating_sel_anchor(float_sel)
#remove it when done to save memory, clean up
pdb.gimp_image_remove_vectors(image,temp_vectors)
#shapes.append(temp_vectors)
#pdb.gimp_message("shape" + str(i+1) + ": " + str(count))
pdb.gimp_selection_none(image)
register(
"python_fu_same_shape",
"Select same shapes",
"Select same shapes",
"author name",
"copyright name",
"2025.01.02",
"A Same Shape",
"RGB*", # Alternately use RGB, RGB*, GRAY*, INDEXED etc.
[
#INPUT BEGINS
(PF_IMAGE, "image", "Image", None),
(PF_DRAWABLE, "layer", "Drawable", None),
(PF_DRAWABLE, "tilelayer", "Tile Layer:", None),
#INPUT ENDS
],
[],
same_shape,
menu="<Image>/Python-Fu")
main()
# Below is all the example input types for INPUTS for the plug-in which can be cut and pasted into #INPUT BEGINS section and edited to taste (found online years back that I didn't want to constantly look up)
# Since GIMP is free anyways, I thought it would be handy here for me to CUT and PASTE, CHANGE, USE.
# (PF_INT, "p0", "_INT:", 0), # PF_INT8, PF_INT16, PF_INT32 similar but no difference in Python.
# (PF_FLOAT, "p02", "_FLOAT:", 3.141),
# (PF_STRING, "p03", "_STRING:", "foo"), # alias PF_VALUE
# (PF_TEXT, "p04", "TEXT:", "bar"),
# # PF_VALUE
# # Pick one from set of choices
# (PF_OPTION,"p1", "OPTION:", 0, ["0th","1st","2nd"]), # initially 0th is choice
# (PF_RADIO, "p16", "RADIO:", 0, (("0th", 1),("1st",0))), # note bool indicates initial setting of buttons
# # PF_RADIO is usually called a radio button group.
# # SLIDER, ADJUSTMENT types require the extra parameter of the form (min, max, step).
# (PF_TOGGLE, "p2", "TOGGLE:", 1), # initially True, checked. Alias PF_BOOL
# # PF_TOGGLE is usually called a checkbox.
# (PF_SLIDER, "p3", "SLIDER:", 0, (0, 100, 10)),
# (PF_SPINNER, "p4", "SPINNER:", 21, (1, 1000, 50)), # alias PF_ADJUSTMENT
# # Pickers ie combo boxes ie choosers from lists of existing Gimp objects
# (PF_COLOR, "p14", "_COLOR:", (100, 21, 40) ), # extra param is RGB triple
# # PF_COLOUR is an alias by aussie PyGimp author lol
# (PF_IMAGE, "p15", "IMAGE:", None), # should be type gimp.image, but None works
# (PF_FONT, "p17", "FONT:", 0),
# (PF_FILE, "p18", "FILE:", 0),
# (PF_BRUSH, "p19", "BRUSH:", 0),
# (PF_PATTERN, "p20", "PATTERN:", 0),
# (PF_GRADIENT, "p21", "GRADIENT:", 0),
# (PF_PALETTE, "p22", "PALETTE:", 0),
# (PF_LAYER, "p23", "LAYER:", None),
# (PF_CHANNEL, "p24", "CHANNEL:", None), # ??? Usually empty, I don't know why.
# (PF_DRAWABLE, "p25", "DRAWABLE:", None),
# # Mostly undocumented, but work
# (PF_VECTORS, "p26", "VECTORS:", None),
# (PF_FILENAME, "p27", "FILENAME:", 0),
# (PF_DIRNAME, "p28", "DIRNAME:", 0)
# # PF_REGION might work but probably of little use. See gimpfu.py.