01-25-2018, 10:41 PM
(This post was last modified: 01-25-2018, 10:45 PM by mich_lloid.)
Ok, I've refined the script some more.
Sometimes spritesheets contain very small objects that are stray pixels and optionally can be discarded.
So I've opted for two layer groups, one for "bad objects" and one for "good objects" where the objects will be placed on the criteria min_size (I set as default objects smaller than 5x5 pixels are considered "bad", but this can be changed of course).
the code sofar:
Question for you ofnuts if you don't mind:
1) Are there gimp-fu commands for scrolling/panning and zooming on the canvas? On big images it can be hard to find very small objects on the canvas.
In Blender for example you can zoom and focus on an object or its vertices with shortcut numpad ..
Also on the matter of "fuzzy select tool" pdb.gimp_fuzzy_select_full(drawable, x, y, threshold, operation, antialias, feather, feather_radius_x, feather_radius_y, sample_merged, select_transparent, select_criterion).
I think this is the best approach to select objects/islands because fully transparent pixels will never be selected, you can see that if you select the wand and then check-off "Select transparent areas" in Tool Options.
If you click on fully transparent areas on the canvas, the selection turns to none, and you can safely set threshold to 255, only islands/will be selected when you click on them, nothing else.
Sometimes spritesheets contain very small objects that are stray pixels and optionally can be discarded.
So I've opted for two layer groups, one for "bad objects" and one for "good objects" where the objects will be placed on the criteria min_size (I set as default objects smaller than 5x5 pixels are considered "bad", but this can be changed of course).
the code sofar:
Code:
import time
def objects2layers(img, sample = 1, min_size = 10):
time_start = time.time()
#samples = 2
#img = gimp.image_list()[0]
src_layer = img.active_layer
layer = src_layer.copy()
img.add_layer(layer)
counter_good = 1
counter_bad = 1
temp_layer = layer.copy()
extra_wdth = 64 - (layer.width % 64)
extra_hght = 64 - (layer.height % 64)
layer.resize( layer.width + extra_wdth, layer.height + extra_hght, 0, 0)
tile_rows = int(layer.width / 64)
#if(layer.width % 64 > 0):
# tile_rows += 1
tile_cols = int(layer.height / 64)
#if(layer.width % 64 > 0):
# tile_cols += 1
for tile_row in range(tile_rows):
for tile_col in range(tile_cols):
#print(tile_row, tile_col)
#srcTile = layer.get_tile(False, tile_row, tile_col)
srcTile = temp_layer.get_tile(False, tile_row, tile_col)
if srcTile != None:
for tile_x in range(0, srcTile.ewidth, sample):
for tile_y in range(0, srcTile.eheight, sample):
pixel = srcTile[tile_x, tile_y]
R,G,B,A = srcTile[tile_x, tile_y]
# if pixel is not completely transparent
if ord( A) > 0:
layer_pixel_pos_x = tile_col * 64 + tile_x
layer_pixel_pos_y = tile_row * 64 + tile_y
#print( layer.get_pixel((tile_col * 64) + tile_x, (tile_row * 64) + tile_y) )
#pdb.gimp_fuzzy_select(img.active_layer, layer_pixel_pos_x, layer_pixel_pos_y, 254.9 , 2,0,0,0,0)
pdb.gimp_fuzzy_select_full(layer , layer_pixel_pos_x, layer_pixel_pos_y, 255, 2, 0, 0, 0, 0, 0, 0, 0)
newlayer = layer.copy()
x1, y1, x2, y2 = layer.mask_bounds
if x2 - x1 < min_size and y2 - y1 < min_size:
# "bad objects", objects that er too small
if counter_bad == 1:
layer_group_bad = pdb.gimp_layer_group_new(img)
layer_group_bad.name = 'small objects'
img.add_layer(layer_group_bad)
newlayer.name = "trash %03d (%d, %d, %d, %d)" % (counter_bad, x1, y1, x2 - x1, y2 - y1)
counter_bad += 1
img.active_layer = layer_group_bad
img.add_layer(newlayer)
else:
# "good objects"
if counter_good == 1:
layer_group_good = pdb.gimp_layer_group_new(img)
layer_group_good.name = 'objects'
img.add_layer(layer_group_good)
newlayer.name = "object %03d (%d, %d, %d, %d)" % (counter_good, x1, y1, x2 - x1, y2 - y1)
counter_good += 1
img.active_layer = layer_group_good
img.add_layer(newlayer)
newlayer.resize(x2 - x1, y2 - y1, -x1, -y1)
img.active_layer = layer
pdb.gimp_edit_clear(layer)
#update tile by updating temp_layer
temp_layer = layer.copy()
srcTile = temp_layer.get_tile(False, tile_row, tile_col)
img.remove_layer(layer)
time_end = time.time()
print ('time taken: ' + str(time_end - time_start) + ' seconds.')
img = gimp.image_list()[0]
objects2layers(img)
Question for you ofnuts if you don't mind:
1) Are there gimp-fu commands for scrolling/panning and zooming on the canvas? On big images it can be hard to find very small objects on the canvas.
In Blender for example you can zoom and focus on an object or its vertices with shortcut numpad ..
Also on the matter of "fuzzy select tool" pdb.gimp_fuzzy_select_full(drawable, x, y, threshold, operation, antialias, feather, feather_radius_x, feather_radius_y, sample_merged, select_transparent, select_criterion).
I think this is the best approach to select objects/islands because fully transparent pixels will never be selected, you can see that if you select the wand and then check-off "Select transparent areas" in Tool Options.
If you click on fully transparent areas on the canvas, the selection turns to none, and you can safely set threshold to 255, only islands/will be selected when you click on them, nothing else.