14

我在手指触摸移动时使用下面的代码在位图画布上画线......在这里我发布了部分代码,它工作正常......

如下图所示,触摸拖动时删除的黑白位图。我使画布透明,因此父布局背景(彩色图像)变得可见。

我想知道,擦除了多少区域(如位图的 50% 或 60%).. 有什么办法可以找到吗?

在此处输入图像描述

//Erasing paint

         mDrawPaint = new Paint();
    mDrawPaint.setAntiAlias(true); 
    mDrawPaint.setDither(true);  
    mDrawPaint.setStyle(Paint.Style.STROKE); 
    mDrawPaint.setStrokeJoin(Paint.Join.ROUND);
    mDrawPaint.setStrokeCap(Paint.Cap.ROUND);
    mDrawPaint.setStrokeWidth(50); 
    mDrawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
    BlurMaskFilter mBlur = new BlurMaskFilter(10, BlurMaskFilter.Blur.NORMAL);
    mDrawPaint.setMaskFilter(mBlur);

private void doDraw(Canvas c) {

    c.drawBitmap(mBitmap, 0, 0,null );

}

private float mX, mY;
private static final float TOUCH_TOLERANCE = 1;

void touch_start(float x, float y) {
    mPath.reset();
    mPath.moveTo(x, y);
    mX = x;
    mY = y;
}
void touch_move(float x, float y) {
    float dx = Math.abs(x - mX);
    float dy = Math.abs(y - mY);
    if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
        mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
        mX = x;
        mY = y;
    }

     canvas.drawPath(mPath, mDrawPaint ); //Erasing Black and white image

}
void touch_up() {
    mPath.lineTo(mX, mY);
    // commit the path to our offscreen
    mCanvas.drawPath(mPath, mDrawPaint);
    // kill this so we don't double draw
    mPath.reset();
}
4

5 回答 5

7

尝试使用蒙特卡罗方法估计透明区域的百分比。我认为这是一种最快、最简单的方法。在透明蒙版上取大约 50 个(取决于您需要的精度)随机像素并检查它们的颜色。然后计算 ans = TransparentPixelsCount/TestPixelCount。

使用路径坐标计算用户绘图的平方非常困难。而且迭代所有像素的时间很长。所以,恕我直言,蒙特卡洛是您的选择。

于 2013-01-21T10:15:22.460 回答
4

要获得准确(且缓慢)的答案,您需要检查每个像素并计算数字是否透明并除以像素总数。如果您的要求允许进行一些估计,最好对图像进行采样。

您可以缩小图像并在较小的图像上运行上述过程。这样做的缺点是缩放操作可能会通过所有像素使其变慢。我建议使用网格采样,它类似于缩小尺寸,但会跳过像素。基本上,我们将 x 个样本点均匀地分布在图像上的网格上。然后计算透明的样本点的数量。透明百分比的估计是透明样本总数/透明样本数。您可以通过少量(例如 100 个)样本获得合理的准确度(通常在 5% 以内)。这是实现此方法的代码函数 - bm 是Bitmap并且scale是每个轴的样本数,因此设置scale = 10提供 100 个总样本(图像上的 10x10 采样网格)。

static public float percentTransparent(Bitmap bm, int scale) {

        final int width = bm.getWidth();
        final int height = bm.getHeight();

        // size of sample rectangles
        final int xStep = width/scale;
        final int yStep = height/scale;

        // center of the first rectangle
        final int xInit = xStep/2;
        final int yInit = yStep/2;

        // center of the last rectangle
        final int xEnd = width - xStep/2;
        final int yEnd = height - yStep/2;

        int totalTransparent = 0;

        for(int x = xInit; x <= xEnd; x += xStep) {
            for(int y = yInit; y <= yEnd; y += yStep) {
                if (bm.getPixel(x, y) == Color.TRANSPARENT) {
                    totalTransparent++;
                }
            }
        }
        return ((float)totalTransparent)/(scale * scale);

    }

作为参考,下面是通过计算每个像素为您提供结果的慢速方法。可用于测试上述估计量的参考。

static public float percentTransparent(Bitmap bm) {
        final int width = bm.getWidth();
        final int height = bm.getHeight();

        int totalTransparent = 0;
        for(int x = 0; x < width; x++) {
            for(int y = 0; y < height; y++) {
                if (bm.getPixel(x, y) == Color.TRANSPARENT) {
                    totalTransparent++;
                }
            }
        }
        return ((float)totalTransparent)/(width * height);

    }
于 2013-01-23T05:59:12.283 回答
1

您需要检测位于绘制多边形内的点。这是函数,它采用包含所有绘制点的数组,第二个参数是点本身,即 x ,y。

// Return true if the dot { x,y } is within any of the polygons in the list

function pointInPolygons( polygons, dot )

      for (i=1, [polygons count] i++)
         {
           if (pointInPolygon( polygons[i], dot )) 
                    return true
         } 

      return false
end

// Returns true if the dot { x,y } is within the polygon 
//defined by points table { {x,y},-    --{x,y},{x,y},... }

function pointInPolygon( points, dot )
    local i, j = #points, #points
    local oddNodes = false

    for i=1, #points do
            if ((points[i].y < dot.y and points[j].y>=dot.y
                    or points[j].y< dot.y and points[i].y>=dot.y) and (points[i].x<=dot.x
                    or points[j].x<=dot.x)) then
                    if (points[i].x+(dot.y-points[i].y)/(points[j].y-points[i].y)*(points[j].x-points[i].x)<dot.x) then
                            oddNodes = not oddNodes
                    end
            end
            j = i
    end

    return oddNodes
   end
于 2013-01-28T06:59:46.743 回答
1

对此有一种不同的方法:您可以使用ComputeBounds计算每条路径的大小。然后将其与视图的大小进行比较并确定绘图的百分比应该很简单。

只是你需要记住,路径可以自己绘制,所以你需要小心并在计算中处理它。

于 2013-01-26T02:12:01.207 回答
1

将所有点 x 和 y 值存储在两个不同的排序集中,一个用于点的 x 值,另一个用于点的 y 值。界限的最终值将是 point(min_x,min_y) 和 point(max_x,max_y)。

于 2013-01-26T19:15:40.743 回答