如题,我的需求是:as3加载一个图片进来,点击某个点之后,让和该点颜色值类似的相连区域被选中。(就是ps里魔棒的选择效果),求大神给点意见。
------解决思路----------------------
思路就是图的连通分量求解
------解决思路----------------------
有三个疑问,1、你所说的类似如何理解,有没有什么约定?2、你所说的选中是指什么?3、选中以后你想干什么?
------解决思路----------------------
你是想增强BitmapData的floodFill () 方法吗?这个我写过,你确定个容差公式,也就是你认为怎么样算是相似,我把你的公式填进去就Ok了。
------解决思路----------------------
我写的是一个替换颜色的代码,可以把它改写成返回记录符合阈值的点的坐标一个数组,然后,进行什么操作就在这个数组基础上实现了
/**
* 对给定的BitmapData对象,以px和py指定的位置为基准,使用洪泛法(FloodFill)将颜色符合阈值要求的点替换成nc指定的新颜色。
* @param bmpData BitmapData 被操作的Bitmap数据
* @param px int 初始点横坐标
* @param py int 初始点纵坐标
* @param nc uint 要被替换成的颜色
* @param dc unit 阈值
*
*/
private function replaceColor(bmpData:BitmapData, px:int, py:int, nc:uint, dc:uint=0):void
{
var bw:int=bmpData.width;
var bh:int=bmpData.height;
//获取起始点的颜色
var c:uint = bmpData.getPixel(px, py);
var oc:Color = new Color(c);
//初始化访问标识
var visited:Array=new Array();
for (var i:int=0; i < bw; i++)
{
var col:Array=new Array();
for (var j:int=0; j < bh; j++)
{
col[j]=false;
}
visited[i]=col;
}
//初始化访问队列
var queue:Vector.<Point> = new Vector.<Point>();
//将起始点加入队列
queue.push(new Point(px,py));
//进入循环
while(queue.length > 0){
//取得一个坐标点
var p:Point = queue.shift();
//获取当前点的颜色
var cc:uint=bmpData.getPixel(p.x, p.y);
//如果当前点颜色在阈值范围内
if (oc.isSimilar(cc, dc))
{
//trace("当前点和取样点颜色相似");
//替换当前点的颜色
bmpData.setPixel(p.x, p.y, nc);
//将当前点的未进入队列的相邻点加入队列
//左一列
if (p.x - 1 >= 0)
{
if (p.y - 1 >= 0 && !visited[p.x - 1][p.y - 1])
{
visited[p.x - 1][p.y - 1] = true;
queue.push(new Point(p.x - 1, p.y - 1));
}
if (!visited[p.x - 1][p.y])
{
visited[p.x - 1][p.y] = true;
queue.push(new Point(p.x - 1, p.y));
}
if (p.y + 1 < bh && !visited[p.x - 1][p.y + 1])
{
visited[p.x - 1][p.y + 1] = true;
queue.push(new Point(p.x - 1, p.y + 1));
}
}
if (p.y - 1 >= 0 && !visited[p.x][p.y - 1])
{
visited[p.x][p.y - 1] = true;
queue.push(new Point(p.x, p.y - 1));
}
if (p.y + 1 < bh && !visited[p.x][p.y + 1])
{
visited[p.x][p.y + 1] = true;
queue.push(new Point(p.x, p.y + 1));
}
//左一列
if (p.x + 1 < bw)
{
if (p.y - 1 >= 0 && !visited[p.x + 1][p.y - 1])
{
visited[p.x + 1][p.y - 1] = true;
queue.push(new Point(p.x + 1, p.y - 1));
}
if (!visited[p.x + 1][p.y])
{
visited[p.x + 1][p.y] = true;
queue.push(new Point(p.x + 1, p.y));
}
if (p.y + 1 < bh && !visited[p.x + 1][p.y + 1])
{
visited[p.x + 1][p.y + 1] = true;
queue.push(new Point(p.x + 1, p.y + 1));
}
}
}
}
}
------解决思路----------------------
这个方法用到了一个Color类,是我自定义的
package zys59.display
{
public class Color
{
private var _R:uint;
private var _G:uint;
private var _B:uint;
public function Color(num:uint)
{
_R = num >> 16;
var gb:uint = num - (_R << 16);
_G = gb >> 8;
_B = gb - (_G << 8);
}
public function get R():uint
{
return _R;
}
public function set R(value:uint):void
{
_R = value;
}
public function get G():uint
{
return _G;
}
public function set G(value:uint):void
{
_G = value;
}
public function get B():uint
{
return _B;
}
public function set B(value:uint):void
{
_B = value;
}
/**
* 获取当前颜色的16进制字符串表示形式
* @return
*
*/
public function toHexString():String{
var sc:String = toUint().toString(16).toUpperCase();
sc = "000000" + sc;
sc = sc.substring(sc.length - 6);
sc = "0x"+sc;
return sc;
}
/**
* 判断指定颜色与当前颜色的相似性
* @param nc uint 参与比较的另一个颜色
* @param dc uint 阈值
* @return Boolean 是否相似
*
*/
public function isSimilar(nc:uint, dc:uint=0):Boolean
{
var onc:Color=new Color(nc);
var dr:int=Math.abs(this.R - onc.R);
var dg:int=Math.abs(this.G - onc.G);
var db:int=Math.abs(this.B - onc.B);
if (dr + dg + db <= dc)
{
return true;
}
else
{
return false;
}
}
/**
* 获取当前颜色的反相颜色
* @return
*
*/
public function getInverse():Color{
return new Color(((255 - _R) << 16) + ((255 - _G) << 8) + ((255 - _B)));
}
/**
* 获取当前颜色的uint表现形式
* @return
*
*/
public function toUint():uint{
return (_R << 16) + (_G << 8) + _B;
}
}
}
------解决思路----------------------
问题解决了,把分赏了吧,嘿嘿