sprites2layers gimp 3
Also in GIMP 3 python console:
I did a quick test port to Gimp 3 but had to take GimpTile code out and just used a Python loop over pixels. The other difference is that I used Python console and not as plugin, but I don't think that would significantly change speed.
results:
GIMP 2.10, 2.710 seconds.
GIMP 3.0.0-1, 109.061 seconds!
I thought it was 10x slower but its much more than that! Any solution to the GimpTile problem?
Code:
def sprites2layers(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='Warning\nThis layer has no alpha, please add an alpha channel for this script to work.'
image_base_type = image.get_base_type()
match image_base_type:
case 0:
image_mode = 'RGB'
if layer.get_bpp() != 4:
Gimp.message(no_alpha_warning)
return
case 1:
image_mode = 'Greyscale'
if layer.get_bpp() != 2:
Gimp.message(no_alpha_warning)
return
case 2:
image_mode = 'Indexed'
if layer.get_bpp() != 2:
Gimp.message(no_alpha_warning)
return
layer_copy = layer.copy()
image.insert_layer(layer_copy, layer.get_parent(), 0)
# Context setters for pdb.gimp_image_select_contiguous_color().
Gimp.context_set_antialias(0)
Gimp.context_set_feather(0)
Gimp.context_set_sample_merged(0)
Gimp.context_set_sample_criterion(0)
Gimp.context_set_sample_threshold(1)
Gimp.context_set_sample_transparent(0)
# Counters for objects in layer groups.
counter_good = 1
counter_bad = 1
# Create an 'off-screen' copy of layer_copy (not added to the canvas).
layer_offscreen = layer_copy.copy()
# Loop over pixels.
for pixel_y in range(0, layer_copy.get_height(), sample):
for pixel_x in range(0, layer_copy.get_width(), sample):
pixel = layer_copy.get_pixel(pixel_x, pixel_y).get_rgba()
# Split components of imag_mode to get the alpha
# RGBA image
if image_mode == 'RGB':
R,G,B,A = pixel
# Greyscale or Indexed image
if image_mode == 'Greyscale' or image_mode == 'Indexed':
I,A = pixel
# If pixel is not completely transparent select it and neighbouring non-transparent pixels.
if A > 0:
image.select_contiguous_color(2, layer_copy, pixel_x, pixel_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 = Gimp.GroupLayer.new(image, 'small objects')
image.insert_layer(layer_group_bad, layer.get_parent(), 0)
object_layer.set_name("trash {:04d} ({: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
# Add object to layer_group_bad at the last position.
#pdb.gimp_image_insert_layer(image, object_layer, layer_group_bad, len(layer_group_bad.layers))
image.insert_layer(object_layer, layer_group_bad, len(layer_group_bad.get_children()))
# 'objects' layer group.
else:
if counter_good == 1 and (image_mode == 'RGB' or image_mode == 'Greyscale'):
layer_group_good = Gimp.GroupLayer.new(image, 'objects')
image.insert_layer(layer_group_good, layer.get_parent(), 0)
object_layer.set_name("object {:04d} ({: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 layer_group_good at the last position.
#pdb.gimp_image_insert_layer(image, object_layer, layer_group_good, len(layer_group_good.layers))
image.insert_layer(object_layer, layer_group_good, len(layer_group_good.get_children()))
# "Auto crop" object layer.
object_layer.resize(x2 - x1, y2 - y1, -x1, -y1)
# Remove/erase selection from layer_copy
#image.active_layer = layer_copy
layer_copy.edit_clear()
# 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_copy)
del(layer_offscreen)
# Reset context settings to their default values.
Gimp.context_set_defaults()
# End timer and display number of objects, small objects and timer seconds up to milliseconds in error console
time_end = time.time()
Gimp.message('INFO:\n-{:d} objects found\n'.format(counter_good - 1) +
'-{:d} small objects found\n'.format(counter_bad - 1) +
'-time taken: {:.3f} seconds'.format(time_end - time_start))
Also in GIMP 3 python console:
Code:
import time
image = Gimp.get_images()[0]
layer = image.get_layers()[0]
sprites2layers(image, layer, 1, 10)
I did a quick test port to Gimp 3 but had to take GimpTile code out and just used a Python loop over pixels. The other difference is that I used Python console and not as plugin, but I don't think that would significantly change speed.
results:
GIMP 2.10, 2.710 seconds.
GIMP 3.0.0-1, 109.061 seconds!
I thought it was 10x slower but its much more than that! Any solution to the GimpTile problem?