参考:http://blog.csdn.net/orbit/article/details/7323090
先上图一发:
如图效果实现,用了两种算法:
1.递归种子填充算法
分为4联通算法和8联通算法,这里使用4联通算法
开始时先从c++底层调用图片解析出png图片每个像素的alpha值,然后用"_"连接起来,变成一个string,传递到Lua,然后做逻辑处理即可
--图片相对于屏幕原点左下角的偏移量
local off_x,off_y
--从每个点开始延伸的四个方向
ColorLayer.direction4 = {
{x=-1,y=0},
{x=0,y=1},
{x=1,y=0},
{x=0,y=-1}
}
--核心算法
--种子填充算法
function ColorLayer:FloodSeedFill(x,y)
--检查触摸点是否是图片的图形区域
if not self:isBorder(x-off_x, y-off_y) then
--检查当前点的透明度
if self:getPixelAlpha(x-off_x,y-off_y) == 0 then
--修改当前点的像素信息,避免进入死循环
self:setPixelAlpha(x- off_x, y-off_y,-1)
--在当前点画点
self:drawPoint(x, y)
--朝四个方向进行递归
for i=1,table.nums(ColorLayer.direction4) do
self:FloodSeedFill(x+ColorLayer.direction4[i].x,y+ColorLayer.directi on4[i].y)
end
end
end
end
2.扫描线种子填充算法
递归种子填充算法虽然简单,但是使用了大量递归算法,需要大量的栈空间来存储相连的点,效率特别低,会有明显的卡顿现象,所以不得已只好换另一种算法。
--存储种子
local curSeed = 0
local seedT = {}
--直线扫描算法
function ColorLayer:LineSeedFill(x,y)
--检查边界
if not self:isBorder(x-off_x, y-off_y) then
--检查种子
while seedT[curSeed+1] do
--扫描种子左边
self:seekLineLeft(seedT[curSeed+1][1], seedT[curSeed+1][2],0,-1,true)
--扫描种子右边
self:seekLineRight(seedT[curSeed+1][1]+1, seedT[curSeed+1][2],0,-1,true)
--在种子的上下两行寻找新的种子
self:seekLineNewSeed(left,right,seedT[curSeed+1][2]-1,0)
self:seekLineNewSeed(left,right,seedT[curSeed+1][2]+1,0)
--下一个种子
curSeed = curSeed + 1
end
end
end
--寻找新的种子点
function ColorLayer:seekLineNewSeed(left,right,y,value)
local temp_x = left
local isFindNewSeed = false
while temp_x <= right do
isFindNewSeed = false
while self:getPixelAlpha(temp_x-off_x,y-off_y) == value and temp_x < right do
isFindNewSeed = true
temp_x = temp_x + 1
end
if isFindNewSeed then
if self:getPixelAlpha(temp_x-off_x,y-off_y) == value and temp_x == right then
table.insert(seedT, {temp_x,y})
else
table.insert(seedT, {temp_x-1,y})
end
end
temp_x = temp_x + 1
end
end