01-29-2018, 12:23 PM
My first plugin ever, I copy-pasted everything from ofnut's "ofn-extract-objects.py" and made a few changes, like content of the function, parameters and registrations, like they say "Imitation is the sincerest form of flattery".
"mich-extract-objects.py" :
To run this plugin Filters > Mich's Gimp-Fu's > objects2layers...
Question:
1) In "Parameters" I had to comment out line 138,139 and 151 because I got error that I had 6 parameters in stead of 4?
"mich-extract-objects.py" :
Code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import time
from gimpfu import *
def objects2layers(image, layer, sample, minimal_dimensions) :
'''
Separates objects on one layer to their own layer. Handy for Spritesheets
Parameters:
image -- The current image.
layer -- The layer of the image that is selected.
sample -- sample every nth pixel of layer tile
minimal_dimensions -- minimal dimension of object to be placed in "objects" layer group
'''
# Start timer
time_start = time.time()
# Check image type (RGB/Greyscale or Indexed) and if layer has alpha, if not stop this script with a warning
no_alpha_warning='This layer has no alpha, please add an alpha channel for this script to work'
if image.base_type == 0:
image_mode = 'RGB'
if layer.bpp != 4:
gimp.message(no_alpha_warning)
return
if image.base_type == 1:
image_mode = 'Greyscale'
if layer.bpp != 2:
gimp.message(no_alpha_warning)
return
if image.base_type == 2:
image_mode = 'Indexed'
if layer.bpp != 2:
gimp.message(no_alpha_warning)
return
tile_width = gimp.tile_width()
tile_height = gimp.tile_height()
layer_copy = layer.copy()
image.add_layer(layer_copy)
# Context setters for pdb.gimp_image_select_contiguous_color()
pdb.gimp_context_set_antialias(0)
pdb.gimp_context_set_feather(0)
pdb.gimp_context_set_sample_merged(0)
pdb.gimp_context_set_sample_criterion(0)
pdb.gimp_context_set_sample_threshold(1)
pdb.gimp_context_set_sample_transparent(0)
# Counters for objects in layer groups
counter_good = 1
counter_bad = 1
# Tile rows and columns of layer_copy
tile_rows = int( (layer_copy.height + tile_height - 1) / tile_height)
tile_cols = int( (layer_copy.width + tile_width - 1) / tile_width)
# create an 'off-screen' copy of layer_copy (not added to the canvas)
layer_offscreen = layer_copy.copy()
# Loop over tiles of layer_offscreen
for tile_row in range(tile_rows):
for tile_col in range(tile_cols):
Tile = layer_offscreen.get_tile(False, tile_row, tile_col)
# Loop over pixels of tiles
for tile_y in range(0, Tile.eheight, sample):
for tile_x in range(0, Tile.ewidth, sample):
pixel = Tile[tile_x, tile_y]
# Split components of imag_mode to get the alpha
# RGBA image
if image_mode == 'RGB':
R,G,B,A = Tile[tile_x, tile_y]
# Greyscale or Indexed image
if image_mode == 'Greyscale' or image_mode == 'Indexed':
I,A = Tile[tile_x, tile_y]
# If pixel is not completely transparent select it and neighbouring non-transparent pixels
if ord( A ) > 0:
layer_pixel_pos_x = tile_col * tile_height + tile_x
layer_pixel_pos_y = tile_row * tile_width + tile_y
pdb.gimp_image_select_contiguous_color(image, 2, layer_copy, layer_pixel_pos_x, layer_pixel_pos_y)
# Create a layer for an object and assign it to 'small objects' layer group or
# 'objects layer group' based on criteria "min_dimensions"
object_layer = layer_copy.copy()
x1, y1, x2, y2 = layer_copy.mask_bounds
# 'small objects' layer group
if x2 - x1 < minimal_dimensions and y2 - y1 < minimal_dimensions:
if counter_bad == 1 and (image_mode == 'RGB' or image_mode == 'Greyscale'):
layer_group_bad = pdb.gimp_layer_group_new(image)
layer_group_bad.name = 'small objects'
image.add_layer(layer_group_bad)
object_layer.name = "trash {:4d} ({:d}, {:d}, {:d}, {:d})".format(counter_bad, x1, y1, x2 - x1, y2 - y1)
counter_bad += 1
if image_mode == 'RGB' or image_mode == 'Greyscale':
image.active_layer = layer_group_bad
# 'objects' layer group
else:
if counter_good == 1 and (image_mode == 'RGB' or image_mode == 'Greyscale'):
layer_group_good = pdb.gimp_layer_group_new(image)
layer_group_good.name = 'objects'
image.add_layer(layer_group_good)
object_layer.name = "object {:4d} ({:d}, {:d}, {:d}, {:d})".format(counter_good, x1, y1, x2 - x1, y2 - y1)
counter_good += 1
if image_mode == 'RGB' or image_mode == 'Greyscale':
image.active_layer = layer_group_good
# Add object to active layer which is one of the two layer groups and "Auto crop" object layer
image.add_layer(object_layer)
object_layer.resize(x2 - x1, y2 - y1, -x1, -y1)
# Remove/erase selection from layer_copy
image.active_layer = layer_copy
pdb.gimp_edit_clear(layer_copy)
# Update tile, by updating layer_offscreen, by copying layer_copy
layer_offscreen = layer_copy.copy()
Tile = layer_offscreen.get_tile(False, tile_row, tile_col)
# Remove layer_copy and layer_offscreen from canvas and memory
image.remove_layer(layer_copy)
del(layer_offscreen)
# Reset context settings to their default values.
pdb.gimp_context_set_defaults()
# End timer and display timer seconds up to milliseconds in error console
time_end = time.time()
gimp.message('INFO: time taken: {:.3f} seconds'.format(time_end - time_start))
### Parameters
#imageParm = (PF_IMAGE, "image", 'Input image' , None)
#layerParm = (PF_DRAWABLE, 'layer', 'Input layer' , None)
sampleParm = (PF_INT, 'sample', 'Sample every nth pixel', 1)
mindimParm = (PF_INT, 'minimal_dimensions', 'Minimal dimension' , 10)
### Registrations
name = "mich-objects-2-layers"
blurb = "Objects to layers"
help = "Separates objects on one layer to their own layer. Handy for Spritesheets"
author = "Mich"
copyright = "Open source (BSD 3-clause license)"
date = "2018-01-28"
imagetypes = "*"
#params = [imageParm, layerParm, sampleParm, mindimParm]
params = [sampleParm, mindimParm]
results = []
menupath = "<Image>/Filters/Mich's Gimp-Fu's/objects2layers..."
function = objects2layers
### Registrations
register(
name ,
blurb ,
help ,
author ,
copyright ,
date ,
menupath ,
imagetypes ,
params ,
results ,
function
)
main()
To run this plugin Filters > Mich's Gimp-Fu's > objects2layers...
Question:
1) In "Parameters" I had to comment out line 138,139 and 151 because I got error that I had 6 parameters in stead of 4?