01-24-2018, 10:54 PM
(This post was last modified: 01-24-2018, 10:58 PM by mich_lloid.)
I didn't notice that my script didn't work for layers that aren't divisible by 64 without remainder, I mostly work with images with power of 2 like 1024x1024 or 2048x2048 for game related stuff.
The script did work on layers not divisible by 64 like 500x500, but sprites on the right and bottom edge didn't get picked up as objects.
I removed the "if srcTile != None:" line and I got AttributeError: 'NoneType' object has no attribute 'ewidth', the tiles at the right and lower corners of the layer was something wrong.
I was digging into it but didn't get the cause of the error so I thought, just make the "temp_layer" divisible by 64 with "extra_wdth" and "extra_hght" so new version yet again:
I'm off to hunting for more bugs in the script, yay!
Some further questions ofnuts if you don't mind:
1) What is the pdb or gimp-fu equivalent of selecting all non-transparent pixels of a layer, the "Alpha to Selection" option when you right-click on layer in layers tab?
I wish gimp was more like blender, you can hover over almost every button and you can get a python equivalent which you can use in the python interpretor, it makes learning python and programming more fun!
2) Do you know how to make the mask of a layer into a new layer manually and with python-fu?
3) fuzzy select suggests "pdb.gimp_image_select_contiguous_color(image, operation, drawable, x, y)" as a replacement, you have to set "context setters" for this to work? How would I go about doing this and how is this better than "pdb.gimp_fuzzy_select_full()"?
PS: about "tile.flush()"
"tile.flush()" doesn't seem to work for me.
My steps to reproduce:
1) create a new image 64x64
2) create a new transparent layer
3) zoom in and draw one pixel at position (1,1) with pencil tool with size 1
4) in gimp console:
5) rectangle select tool over pixel or select everything and "edit_clear" by delete
6) in gimp console:
the pixel at srcTile[1,1] is still 255 while it should be 0
if I do this in console:
still no 0 but if I now do this:
finally srcTile is updated
The script did work on layers not divisible by 64 like 500x500, but sprites on the right and bottom edge didn't get picked up as objects.
I removed the "if srcTile != None:" line and I got AttributeError: 'NoneType' object has no attribute 'ewidth', the tiles at the right and lower corners of the layer was something wrong.
I was digging into it but didn't get the cause of the error so I thought, just make the "temp_layer" divisible by 64 with "extra_wdth" and "extra_hght" so new version yet again:
Code:
import time
def loop_tiles(img, sample = 1):
time_start = time.time()
#samples = 2
#img = gimp.image_list()[0]
src_layer = img.active_layer
layer = src_layer.copy()
img.add_layer(layer)
counter = 1
temp_layer = layer.copy()
extra_wdth = 64 - (layer.width % 64)
extra_hght = 64 - (layer.height % 64)
layer.resize( layer.width + extra_wdth, layer.height + extra_hght, 0, 0)
tile_rows = int(layer.width / 64)
#if(layer.width % 64 > 0):
# tile_rows += 1
tile_cols = int(layer.height / 64)
#if(layer.width % 64 > 0):
# tile_cols += 1
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]
R,G,B,A = srcTile[tile_x, tile_y]
# if pixel is not completely transparent
if ord( A) > 0:
layer_pixel_pos_x = tile_col * 64 + tile_x
layer_pixel_pos_y = tile_row * 64 + tile_y
#print( layer.get_pixel((tile_col * 64) + tile_x, (tile_row * 64) + 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)
newlayer = layer.copy()
img.add_layer(newlayer)
x1, y1, x2, y2 = layer.mask_bounds
newlayer.name = "Layer %03d (%d, %d, %d, %d)" % (counter, x1, y1, x2 - x1, y2 - y1)
counter += 1
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]
loop_tiles(img)
I'm off to hunting for more bugs in the script, yay!
Some further questions ofnuts if you don't mind:
1) What is the pdb or gimp-fu equivalent of selecting all non-transparent pixels of a layer, the "Alpha to Selection" option when you right-click on layer in layers tab?
I wish gimp was more like blender, you can hover over almost every button and you can get a python equivalent which you can use in the python interpretor, it makes learning python and programming more fun!
2) Do you know how to make the mask of a layer into a new layer manually and with python-fu?
3) fuzzy select suggests "pdb.gimp_image_select_contiguous_color(image, operation, drawable, x, y)" as a replacement, you have to set "context setters" for this to work? How would I go about doing this and how is this better than "pdb.gimp_fuzzy_select_full()"?
PS: about "tile.flush()"
"tile.flush()" doesn't seem to work for me.
My steps to reproduce:
1) create a new image 64x64
2) create a new transparent layer
3) zoom in and draw one pixel at position (1,1) with pencil tool with size 1
4) in gimp console:
Code:
➤> img = gimp.image_list()[0]
➤> layer = img.active_layer
➤> srcTile = layer.get_tile(False, 0, 0)
➤> ord(srcTile[1,1][-1])
255
5) rectangle select tool over pixel or select everything and "edit_clear" by delete
6) in gimp console:
Code:
➤> srcTile.flush()
➤> ord(srcTile[1,1][-1])
255
the pixel at srcTile[1,1] is still 255 while it should be 0
if I do this in console:
Code:
➤> srcTile = layer.get_tile(False, 0, 0)
➤> ord(srcTile[1,1][-1])
255
still no 0 but if I now do this:
Code:
➤> img = gimp.image_list()[0]
➤> layer = img.active_layer
➤> srcTile = layer.get_tile(False, 0, 0)
➤> ord(srcTile[1,1][-1])
0
finally srcTile is updated