01-26-2018, 09:14 PM
(This post was last modified: 01-26-2018, 11:23 PM by mich_lloid.)
Ok, now script works for all image modes rgb, grayscale and index, as long as the active layer has transparency
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 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)
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)