Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Searching for python script islands to layers
#28
Ok, now script works for all image modes rgb, grayscale and index, as long as the active layer has transparency

Code:
import time

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 = 'RGB'
       if img.active_layer.bpp != 4:
           print('this layer has no alpha')
           return
   # if image is greyscale and has alpha channel
   if img.base_type == 1:
       img_mode = 'Greyscale'
       if img.active_layer.bpp != 2:
           print('this layer has no alpha')
           return
   # if image is indexed mode (gif) and has alpha channel
   if img.base_type == 2:
       img_mode = 'Indexed'
       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
   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)
   temp_layer = layer.copy()
   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_y in range(0, srcTile.eheight, sample):
                   for tile_x in range(0, srcTile.ewidth, sample):
                       pixel = srcTile[tile_x, tile_y]
                       #RGBA image
                       if img_mode == 'RGB':
                           R,G,B,A = srcTile[tile_x, tile_y]
                       #indexed image like gif
                       if img_mode == 'Greyscale' or img_mode == 'Indexed':
                           I,A = srcTile[tile_x, tile_y]
                       # if pixel is not completely transparent
                       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(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 and (img_mode == 'RGB' or img_mode == 'Greyscale'):
                                   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
                               if img_mode == 'RGB' or img_mode == 'Greyscale':
                                   img.active_layer = layer_group_bad
                           else:
                               # "good objects"
                               if counter_good == 1 and (img_mode == 'RGB' or img_mode == 'Greyscale'):
                                   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
                               if img_mode == 'RGB' or img_mode == 'Greyscale':
                                   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)
Now I have a strange bug, the script only works on somewhat square images. For example 640 x 320 image objects on right side won't be picked and on 640 x 320 objects on the bottom won't be picked. If I resize the images to 640 x 640 and "Layer to image size" all objects get picked. What  am I doing wrong?

Edit: finally got everything to work, no need to create extra width, I just made mistake and switched layer.width with layer.height
Code:


Code:
import time

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 = 'RGB'
        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:
        img_mode = 'Greyscale'
        if img.active_layer.bpp != 2:
            print('this layer has no alpha')
            return
    # if image is indexed mode (gif) and has alpha channel
    if img.base_type == 2:
        img_mode = 'Indexed'
        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
    tile_rows = int( (layer.height + tile_height - 1) / tile_height)
    tile_cols = int( (layer.width  + tile_width - 1) / tile_width)
    temp_layer = layer.copy()
    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_y in range(0, srcTile.eheight, sample):
                for tile_x in range(0, srcTile.ewidth, sample):
                    pixel = srcTile[tile_x, tile_y]
                    #RGBA image
                    if img_mode == 'RGB':
                        R,G,B,A = srcTile[tile_x, tile_y]
                    #indexed image like gif
                    if img_mode == 'Greyscale' or img_mode == 'Indexed':
                        I,A = srcTile[tile_x, tile_y]
                    # if pixel is not completely transparent
                    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(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 and (img_mode == 'RGB' or img_mode == 'Greyscale'):
                                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
                            if img_mode == 'RGB' or img_mode == 'Greyscale':
                                img.active_layer = layer_group_bad
                        else:
                            # "good objects"
                            if counter_good == 1 and (img_mode == 'RGB' or img_mode == 'Greyscale'):
                                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
                            if img_mode == 'RGB' or img_mode == 'Greyscale':
                                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)
    del(temp_layer)
    time_end = time.time()
    print ('time taken: ' + str(time_end - time_start) + ' seconds.')

img = gimp.image_list()[0]
objects2layers(img)
Reply


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

Forum Jump: