Actionscript 3 as3:在透明图像上绘制笔划

Actionscript 3 as3:在透明图像上绘制笔划,actionscript-3,flash,bitmap,Actionscript 3,Flash,Bitmap,我试图将photoshop的魔杖工具复制到用户上传的位图中 为了达到这个效果,我使用阈值选择一些像素,然后操纵这些像素,甚至使用这种技术添加笔划 使用上述技术,我可以在位图对象中获得所需的笔划 问题是位图被变换以适合特定区域,因此最终结果模糊或具有可变笔划大小。此外,我想结合魔杖工具和多边形套索工具,我已经实现了与绘图API,这是使用矢量图形 我认为我可以找到笔划像素,然后为每个像素指定一个点,最后以某种方式连接这些点 这就是我被卡住的地方,因为点没有明显的顺序,所以我不能使用绘图API来“连

我试图将photoshop的魔杖工具复制到用户上传的位图中

为了达到这个效果,我使用阈值选择一些像素,然后操纵这些像素,甚至使用这种技术添加笔划

使用上述技术,我可以在位图对象中获得所需的笔划

问题是位图被变换以适合特定区域,因此最终结果模糊或具有可变笔划大小。此外,我想结合魔杖工具和多边形套索工具,我已经实现了与绘图API,这是使用矢量图形

我认为我可以找到笔划像素,然后为每个像素指定一个点,最后以某种方式连接这些点

这就是我被卡住的地方,因为点没有明显的顺序,所以我不能使用绘图API来“连接点”

任何帮助或指向正确方向都会非常有帮助,
thanx提前

我不建议您使用您提到的方法创建笔划。它只能为简单或小的形状提供令人满意的结果。 相反,您可以对每个像素的每个邻居进行采样,以确定其是否与静止颜色一致

这是一个用于标记透明图像轮廓的像素弯曲器代码示例(请注意,在较新的flash播放器中不再支持这一点。它现在由flash vm执行)。颜色只是轮廓的颜色,阈值定义像素将被视为不透明的alpha值

evaluatePixel()
{
    float2 oc = outCoord();
    dst = sampleNearest(src,oc);

    float4 nN = sampleNearest(src,float2(oc.x, oc.y - 1.0));
    float4 nNE = sampleNearest(src,float2(oc.x + 1.0, oc.y - 1.0));
    float4 nE = sampleNearest(src,float2(oc.x + 1.0 , oc.y));
    float4 nSE = sampleNearest(src,float2(oc.x + 1.0, oc.y + 1.0));
    float4 nS = sampleNearest(src,float2(oc.x, oc.y + 1.0));
    float4 nSW = sampleNearest(src,float2(oc.x - 1.0, oc.y + 1.0));
    float4 nW = sampleNearest(src,float2(oc.x - 1.0, oc.y));
    float4 nNW = sampleNearest(src,float2(oc.x - 1.0, oc.y - 1.0));

    float4 av = nN + nNE + nE + nSE + nS + nSW + nW + nNW;
    av *= 0.125;
    if(dst.a <= threshold && av.a > 0.0 && av.a < 1.0) dst = color;
    else if( dst.a > 0.0) dst = body;
    else{
        dst = color;
        dst.a = 0.0;
    }
}
evaluatePixel()
{
float2 oc=outCoord();
dst=sampleNearest(src,oc);
float4 nN=sampleNearest(src,float2(oc.x,oc.y-1.0));
浮动4 nNE=sampleNearest(src,浮动2(oc.x+1.0,oc.y-1.0));
浮动4 nE=sampleNearest(src,浮动2(oc.x+1.0,oc.y));
float4 nSE=sampleNearest(src,float2(oc.x+1.0,oc.y+1.0));
float4 nS=sampleNearest(src,float2(oc.x,oc.y+1.0));
新南威尔士州浮动4=sampleNearest(src,浮动2(oc.x-1.0,oc.y+1.0));
float4 nW=sampleNearest(src,float2(oc.x-1.0,oc.y));
float4 nNW=sampleNearest(src,float2(oc.x-1.0,oc.y-1.0));
浮动4 av=nN+nNE+nE+nSE+nS+nSW+nW+nNW;
av*=0.125;
如果(dst.a 0.0&&av.a<1.0)dst=颜色;
否则,如果(dst.a>0.0)dst=主体;
否则{
dst=颜色;
dst.a=0.0;
}
}
将此应用于该图像:

你得到这个:

由于阿尔法褪色,在某个点你会得到更厚的轮廓。您可以通过应用另一个过滤器来修复它,该过滤器将只通过与不透明(红色)区域直接相邻的像素。方法与上面的方法非常相似。 之后,您将获得一个像素厚的线条:


现在您可以确定此轮廓的矢量形状

  • 开始向某个方向移动,直到找到第一个白色像素并将其标记为顶点

  • 测试相邻顶点以确定其是否已连接(为白色)

  • 如果是,则移动到该像素并重复步骤2 另外,如果下一个白色像素位于不同的方向,则最后一个将其标记,最后一个将其标记为顶点(保持顺序),否则将其置为空白

  • 重复此操作,直到回到第一个顶点或当前像素没有连接为止

    在某些情况下,如果将边拆分为多条线,则可能无法选择正确的路径,如下所示:

    您可能希望移回像素有更多连接的位置,然后尝试其他路径


    从位图中查找形状的另一种方法:

  • 在某个方向上移动,当你们碰到边时,标记顶点,然后在你们原来的方向上移动一段预定义的距离

  • 开始绕最后一个顶点为圆心的圆移动,向后移动的距离为圆的半径。当您点击边标记顶点并沿垂直于最后两个顶点形成的线的方向向后移动时。重复此步骤,直到最后一个顶点接近第一个顶点


  • 第二种方法是根据给定的距离获得近似的形状,得到的垂直数取决于形状边缘的长度,但不需要以任何特定的方式准备位图。另一方面,第一种方法可以为简单的锐利形状(如矩形)提供很少的顶点,而不管其大小如何;对于复杂形状,可以提供更多的顶点

    下面是这两种方法的实时可视化

    另外,请理解,这些只是我想法的实验性实现,可以显著改进,我不能向您保证这些方法是解决您问题的最佳方法,也不知道在photoshop这样的专业软件中是如何实现的,因为我甚至都没有搜索这些信息。
    不过,我希望它在某种程度上对你有用

    关于套索,如果你仔细看Photoshop,你会发现套索选择像素而不是曲线。矢量图形生成与像素不对齐的曲线。你可以这样使用套索:抓取套索图形,使用
    readGraphicsData
    ,然后在将路径应用到另一个精灵之前添加一个
    beginfl()
    ,然后调用
    endFill()
    ,你将得到一个填充了像素所在颜色的精灵。然后将其绘制在遮罩
    位图数据
    上,这将获得套索像素集。谢谢您的回答Vesper,但readGraphicsData需要FP 11.6,我无法将其与我的flash cs 5.5配合使用。无论如何,我会进一步调查你的建议。非常感谢。然后你可以用另一种方式记录这些点,比如说将它们放入一个与你画的套索一致的数组中,然后从这些记录中构造图形路径。是的,这是我的想法,但这不是很容易,或者我想不出连接这些点的正确方法。非常感谢。