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

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


Messages In This Thread
RE: Searching for python script islands to layers - by mich_lloid - 01-29-2018, 12:23 PM

Forum Jump: