像素区域比较
Pixels regions comparision
我正在尝试为 GIMP 编写一个 python 脚本,其目的是将图片分割成一个图块集(识别图片中每个唯一的 16x16 图块)。
到目前为止,我能够读取图块(实际上是一个 16x16 像素的区域)并将其写入某处。
但是我所有比较图块的尝试都失败了。
我错过了什么吗?
我的脚本如下:
#!/usr/bin/env python
from gimpfu import *
# compare 2 tiles,
# return 1 if identical, false otherwise
def tileCompare(tile1, tile2):
if(tile1 == tile2):
return 1
return 0
# return tile at (x, y) coordinates
def readTile(layer, x, y):
pr = layer.get_pixel_rgn(x,y,16,16)
return pr[x:x+16, y:y+16]
# write tile at (x, y) coordinates on given layer
def writeTile(layer, x, y, tile):
pr = layer.get_pixel_rgn(x,y,16,16)
pr[x:x+16, y:y+16] = tile
def TilesSlicer(sourceLayer, targetLayer):
# Actual plug-in code will go here
# iterate tiles (result in tileSource)
for x in range(0, sourceLayer.width, 16):
for y in range(0, sourceLayer.height, 16):
tileSource = readTile(sourceLayer, x, y)
found = 0
# iterate tiles again (result in tileIterator)
for a in range(0, sourceLayer.width, 16):
for b in range(0, sourceLayer.height, 16):
tileIterator = readTile(sourceLayer, x, y)
# compare tiles
# if identical and not yet found
# write it in the target layer
if (tileCompare(tileSource, tileIterator) == 1):
if(found == 0):
writeTile(tileIterator, a, b, tileSource)
found = 1
register(
"TilesSlicer",
"Tiles slicer",
"Slice a picture into tiles",
"Fabrice Lambert",
"Fabrice Lambert",
"April 2019",
"Tiles slicer...",
"RGB*",
[
(PF_DRAWABLE, "sourceLayer", "Source Layer: ", None),
(PF_DRAWABLE, "targetLayer", "Target Layer: ", None),
],
[],
TilesSlicer,
menu="<Image>/Filters/My Scripts")
main()
感谢您的建议。
Nvm,
我发现了问题:
tileIterator = readTile(sourceLayer, a, b)
而不是:
tileIterator = readTile(sourceLayer, x, y)
好的,
稍加修改后的脚本如下:
- 添加了瓷砖宽度和高度以处理任何瓷砖尺寸。
- 删除了目标层参数,脚本现在创建它。
- 添加了实时显示以向用户提供反馈(遗憾的是,进度条不起作用)。
- 提高了速度。
#!/usr/bin/env python
from gimpfu import *
# compare 2 tiles,
# return 1 if identical, 0 otherwise
def tileCompare(tile1, tile2):
if(tile1 == tile2):
return 1
return 0
# return tile at (x, y) coordinates
def readTile(layer, x, y, width, height):
pr = layer.get_pixel_rgn(x, y, width, height)
return pr[x:x+width, y:y+height]
# write tile at (x, y) coordinates on given layer
def writeTile(layer, x, y, width, height, tile):
pr = layer.get_pixel_rgn(x, y, width, height)
pr[x:x+width, y:y+height] = tile
layer.update(x, y, width, height)
gimp.displays_flush()
def TilesSlicer(sourceLayer, tileWidth, tileHeight):
# Actual plug-in code will go here
if((sourceLayer.width % tileWidth) != 0):
gimp.message("The layer width is not multiple of " + str(tileWidth))
gimp.quit()
if((sourceLayer.height % tileWidth) != 0):
gimp.message("The layer height is not multiple of " + str(tileHeight))
gimp.quit()
totalTiles = (sourceLayer.width / tileWidth) * (sourceLayer.height / tileHeight)
tilesProcessed = 0
gimp.progress_init("Processing...")
gimp.progress_update(0.0)
sourceImage = sourceLayer.image
targetLayer = pdb.gimp_layer_new(sourceImage, sourceLayer.width, sourceLayer.height, sourceImage.base_type, "Target", 100.0, sourceLayer.mode)
targetLayer.add_alpha()
targetLayer.fill(TRANSPARENT_FILL)
sourceImage.add_layer(targetLayer, 0)
# iterate tiles (result in tileSource)
for x in range(0, sourceLayer.width, tileWidth):
for y in range(0, sourceLayer.height, tileHeight):
tileSource = readTile(sourceLayer, x, y, tileWidth, tileHeight)
found = 0
# iterate tiles again (result in tileIterator)
for a in range(0, sourceLayer.width, tileWidth):
for b in range(0, sourceLayer.height, tileHeight):
tileIterator = readTile(sourceLayer, a, b, tileWidth, tileHeight)
# compare tiles
# if identical and not yet found
# write it in the target layer
# and abort iteration (for speed purpose)
if (tileCompare(tileSource, tileIterator) == 1):
if(found == 0):
writeTile(targetLayer, a, b, tileWidth, tileHeight, tileIterator)
found = 1
break
if(found == 1):
break
tilesProcessed = tilesProcessed + 1
gimp.progress_update(tilesProcessed / totalTiles)
gimp.displays_flush()
register(
"TilesSlicer",
"Tiles slicer",
"Slice a picture into tiles",
"Fabrice Lambert",
"Fabrice Lambert",
"April 2019",
"Tiles slicer...",
"RGB*",
[
(PF_DRAWABLE, "sourceLayer", "Source Layer: ", None),
(PF_INT8, "tileWidth", "Tile width: ", 16),
(PF_INT8, "tileHeight", "Tile height: ", 16),
],
[],
TilesSlicer,
menu="<Image>/Filters/My Scripts")
main()
可能还可以再细化一下,如果有人对进度条有什么处理,请告诉我。
我乐于接受建议。
我正在尝试为 GIMP 编写一个 python 脚本,其目的是将图片分割成一个图块集(识别图片中每个唯一的 16x16 图块)。
到目前为止,我能够读取图块(实际上是一个 16x16 像素的区域)并将其写入某处。 但是我所有比较图块的尝试都失败了。
我错过了什么吗? 我的脚本如下:
#!/usr/bin/env python
from gimpfu import *
# compare 2 tiles,
# return 1 if identical, false otherwise
def tileCompare(tile1, tile2):
if(tile1 == tile2):
return 1
return 0
# return tile at (x, y) coordinates
def readTile(layer, x, y):
pr = layer.get_pixel_rgn(x,y,16,16)
return pr[x:x+16, y:y+16]
# write tile at (x, y) coordinates on given layer
def writeTile(layer, x, y, tile):
pr = layer.get_pixel_rgn(x,y,16,16)
pr[x:x+16, y:y+16] = tile
def TilesSlicer(sourceLayer, targetLayer):
# Actual plug-in code will go here
# iterate tiles (result in tileSource)
for x in range(0, sourceLayer.width, 16):
for y in range(0, sourceLayer.height, 16):
tileSource = readTile(sourceLayer, x, y)
found = 0
# iterate tiles again (result in tileIterator)
for a in range(0, sourceLayer.width, 16):
for b in range(0, sourceLayer.height, 16):
tileIterator = readTile(sourceLayer, x, y)
# compare tiles
# if identical and not yet found
# write it in the target layer
if (tileCompare(tileSource, tileIterator) == 1):
if(found == 0):
writeTile(tileIterator, a, b, tileSource)
found = 1
register(
"TilesSlicer",
"Tiles slicer",
"Slice a picture into tiles",
"Fabrice Lambert",
"Fabrice Lambert",
"April 2019",
"Tiles slicer...",
"RGB*",
[
(PF_DRAWABLE, "sourceLayer", "Source Layer: ", None),
(PF_DRAWABLE, "targetLayer", "Target Layer: ", None),
],
[],
TilesSlicer,
menu="<Image>/Filters/My Scripts")
main()
感谢您的建议。
Nvm,
我发现了问题:
tileIterator = readTile(sourceLayer, a, b)
而不是:
tileIterator = readTile(sourceLayer, x, y)
好的,
稍加修改后的脚本如下:
- 添加了瓷砖宽度和高度以处理任何瓷砖尺寸。
- 删除了目标层参数,脚本现在创建它。
- 添加了实时显示以向用户提供反馈(遗憾的是,进度条不起作用)。
- 提高了速度。
#!/usr/bin/env python
from gimpfu import *
# compare 2 tiles,
# return 1 if identical, 0 otherwise
def tileCompare(tile1, tile2):
if(tile1 == tile2):
return 1
return 0
# return tile at (x, y) coordinates
def readTile(layer, x, y, width, height):
pr = layer.get_pixel_rgn(x, y, width, height)
return pr[x:x+width, y:y+height]
# write tile at (x, y) coordinates on given layer
def writeTile(layer, x, y, width, height, tile):
pr = layer.get_pixel_rgn(x, y, width, height)
pr[x:x+width, y:y+height] = tile
layer.update(x, y, width, height)
gimp.displays_flush()
def TilesSlicer(sourceLayer, tileWidth, tileHeight):
# Actual plug-in code will go here
if((sourceLayer.width % tileWidth) != 0):
gimp.message("The layer width is not multiple of " + str(tileWidth))
gimp.quit()
if((sourceLayer.height % tileWidth) != 0):
gimp.message("The layer height is not multiple of " + str(tileHeight))
gimp.quit()
totalTiles = (sourceLayer.width / tileWidth) * (sourceLayer.height / tileHeight)
tilesProcessed = 0
gimp.progress_init("Processing...")
gimp.progress_update(0.0)
sourceImage = sourceLayer.image
targetLayer = pdb.gimp_layer_new(sourceImage, sourceLayer.width, sourceLayer.height, sourceImage.base_type, "Target", 100.0, sourceLayer.mode)
targetLayer.add_alpha()
targetLayer.fill(TRANSPARENT_FILL)
sourceImage.add_layer(targetLayer, 0)
# iterate tiles (result in tileSource)
for x in range(0, sourceLayer.width, tileWidth):
for y in range(0, sourceLayer.height, tileHeight):
tileSource = readTile(sourceLayer, x, y, tileWidth, tileHeight)
found = 0
# iterate tiles again (result in tileIterator)
for a in range(0, sourceLayer.width, tileWidth):
for b in range(0, sourceLayer.height, tileHeight):
tileIterator = readTile(sourceLayer, a, b, tileWidth, tileHeight)
# compare tiles
# if identical and not yet found
# write it in the target layer
# and abort iteration (for speed purpose)
if (tileCompare(tileSource, tileIterator) == 1):
if(found == 0):
writeTile(targetLayer, a, b, tileWidth, tileHeight, tileIterator)
found = 1
break
if(found == 1):
break
tilesProcessed = tilesProcessed + 1
gimp.progress_update(tilesProcessed / totalTiles)
gimp.displays_flush()
register(
"TilesSlicer",
"Tiles slicer",
"Slice a picture into tiles",
"Fabrice Lambert",
"Fabrice Lambert",
"April 2019",
"Tiles slicer...",
"RGB*",
[
(PF_DRAWABLE, "sourceLayer", "Source Layer: ", None),
(PF_INT8, "tileWidth", "Tile width: ", 16),
(PF_INT8, "tileHeight", "Tile height: ", 16),
],
[],
TilesSlicer,
menu="<Image>/Filters/My Scripts")
main()
可能还可以再细化一下,如果有人对进度条有什么处理,请告诉我。
我乐于接受建议。