01-26-2018, 04:10 PM
(This post was last modified: 01-26-2018, 04:52 PM by mich_lloid.)
Ok, I updated the script by replacing '64' with 'tile_width' and 'tile_height' so it works if gimp ever lets tilesize be changed from 64 to something else.
I also replaced 'deprecated' gimp_fuzzy_select_full with gimp_image_select_contiguous_color if gimp ever decides to remove deprecated functions which I doubt.
Also sanity check if layer has alpha and works on rgb, greyscale and indexed (gif) images, if no alpha found print in console that there was no alpha found and stop script.
So only requirements for this script to work with an image:
-layer of image must have an alpha
-must apply layer mask if layer has one
script:
Edit: I thought this script also worked for indexed images, the sprites/objects were showing in the layer preview but not on the canvas. I thought "what the ?!", turns out indexed images don't allow layer groups, I'll have to patch that later...
I also replaced 'deprecated' gimp_fuzzy_select_full with gimp_image_select_contiguous_color if gimp ever decides to remove deprecated functions which I doubt.
Also sanity check if layer has alpha and works on rgb, greyscale and indexed (gif) images, if no alpha found print in console that there was no alpha found and stop script.
So only requirements for this script to work with an image:
-layer of image must have an alpha
-must apply layer mask if layer has one
script:
Code:
def objects2layers(img, sample = 1, min_size = 10):
time_start = time.time()
src_layer = img.active_layer
# if image is rgb mode and has alpha channel
if img.base_type == 0:
img_mode = 1
if img.active_layer.bpp != 4:
print('this layer has no alpha')
return
# if image is greyscale or indexed mode (gif) and has alpha channel
if img.base_type == 1 or img.base_type == 2:
img_mode = 2
if img.active_layer.bpp != 2:
print('this layer has no alpha')
return
layer = src_layer.copy()
tile_width = gimp.tile_width()
tile_height = gimp.tile_height()
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)
img.add_layer(layer)
counter_good = 1
counter_bad = 1
temp_layer = layer.copy()
extra_wdth = tile_width - (layer.width % tile_width)
extra_hght = tile_height - (layer.height % tile_height)
layer.resize( layer.width + extra_wdth, layer.height + extra_hght, 0, 0)
tile_rows = int(layer.width / tile_width)
tile_cols = int(layer.height / tile_height)
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]
#RGBA image
if img_mode == 1:
R,G,B,A = srcTile[tile_x, tile_y]
#indexed image like gif
if img_mode == 2:
I,A = srcTile[tile_x, tile_y]
# if pixel is not completely transparent
if ord( A) > 0:
layer_pixel_pos_x = tile_col * tile_width + tile_x
layer_pixel_pos_y = tile_row * tile_height + tile_y
#print( layer.get_pixel((tile_col * tile_size) + tile_x, (tile_row * tile_size) + 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)
pdb.gimp_image_select_contiguous_color(img, 2, layer, layer_pixel_pos_x, layer_pixel_pos_y)
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
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)
Edit: I thought this script also worked for indexed images, the sprites/objects were showing in the layer preview but not on the canvas. I thought "what the ?!", turns out indexed images don't allow layer groups, I'll have to patch that later...