Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Alternative to Drawable.get_tile() for Gimp 3?
#1
I'm trying to port a Gimp 2 script to Gimp 3 and got most of it figured out by trying stuff out in the python console.


Code:
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import time
from gimpfu import *

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='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 {: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))

                        # '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 {: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))


                        # Add object to active layer which is one of the two layer groups
                        #image.add_layer(object_layer)
                        # "Auto crop" 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 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))

### 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-sprites-2-layers"
blurb      = "Objects to layers"
help       = "Separates objects on one layer to their own layer. Handy for Spritesheets"
author     = "Mich"
copyright  = "Mich"
date       = "2018-01-28"
menu_item  = "sprites2layers..."
imagetypes = "*"
params     = [imageParm, layerParm, sampleParm, mindimParm]
results    = []
function   = sprites2layers
menupath   = "<Image>/Layer"

### Registrations
register(
    name      ,
    blurb     ,
    help      ,
    author    ,
    copyright ,
    date      ,
    menu_item ,
    imagetypes,
    params    ,
    results   ,
    function  ,
    menupath
)

main()


I've hit a snag with lines 65 and 129 with "Tile = layer_offscreen.get_tile(False, tile_row, tile_col)". 
in Gimp 3 "drawable.get_tile()" doesn't exist, what is the alternative to this?
Reply


Messages In This Thread
Alternative to Drawable.get_tile() for Gimp 3? - by joeyeroq - 03-25-2025, 01:21 AM

Forum Jump: