Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Searching for python script islands to layers
#27
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:

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...
Reply


Messages In This Thread
RE: Searching for python script islands to layers - by mich_lloid - 01-26-2018, 04:10 PM

Forum Jump: