如何计算android中位图的擦除面积百分比?

如何计算android中位图的擦除面积百分比?,android,canvas,bitmap,paint,touch-event,Android,Canvas,Bitmap,Paint,Touch Event,我不熟悉安卓系统。我正在做一个应用程序,可以擦除画布上使用手指位图。类似于手指涂鸦橡皮擦的东西。我想计算被擦除区域的百分比(例如,60%已从完整图像中擦除)。请帮我做这件事。。提前谢谢 我尝试了一些方法。它总是给我0%。它不起作用。请参见该方法的代码底部 自定义视图 public class MyView extends View { private final Paint mPaint; private Bitmap mBitmap; private Canvas mC

我不熟悉安卓系统。我正在做一个应用程序,可以擦除画布上使用手指位图。类似于手指涂鸦橡皮擦的东西。我想计算被擦除区域的百分比(例如,60%已从完整图像中擦除)。请帮我做这件事。。提前谢谢

我尝试了一些方法。它总是给我0%。它不起作用。请参见该方法的代码底部

自定义视图

public class MyView extends View
{
    private final Paint mPaint;
    private Bitmap mBitmap;
    private Canvas mCanvas;
    private final Path mPath;
    private final Paint mBitmapPaint;
    private Bitmap eraseableBitmap;

    public MyView(Context context)
    {
        super(context);
        if (Build.VERSION.SDK_INT >= 11)
        {
            setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        }
        mPaint = new Paint();
        mPath = new Path();
        mBitmapPaint = new Paint(Paint.DITHER_FLAG);
    }

    protected void PaintObjectInit()
    {
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setStrokeWidth(30);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh)
    {
        super.onSizeChanged(w, h, oldw, oldh);

        try
        {
            //mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
            eraseableBitmap =
                BitmapFactory.decodeResource(this.getResources(), R.drawable.tharu_rena_over).copy(
                    Bitmap.Config.ARGB_8888, true);

            eraseableBitmap = getResizedBitmap(eraseableBitmap, h, w);

            mCanvas = new Canvas(eraseableBitmap );
        }
        catch (Exception e)
        {
            // TODO: handle exception
            e.printStackTrace();
        }
    }

    public Bitmap getResizedBitmap(Bitmap bm, int newHeight, int newWidth)
    {
        int width = bm.getWidth();
        int height = bm.getHeight();
        float scaleWidth = ((float) newWidth) / width;
        float scaleHeight = ((float) newHeight) / height;
        // CREATE A MATRIX FOR THE MANIPULATION
        Matrix matrix = new Matrix();
        // RESIZE THE BIT MAP
        matrix.postScale(scaleWidth, scaleHeight);

        // "RECREATE" THE NEW BITMAP
        Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false);
        return resizedBitmap;
    }

    @Override
    protected void onDraw(Canvas canvas)
    {

        //canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
        canvas.drawBitmap(eraseableBitmap, 0, 0, mBitmapPaint);
        canvas.drawPath(mPath, mPaint);
    }

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

    private void touch_start(float x, float y)
    {
        //        mPath.reset();
        mPath.moveTo(x, y);
        mX = x;
        mY = y;
    }

    private 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;
        }
    }

    private void touch_up()
    {
        mPath.lineTo(mX, mY);
        // commit the path to our offscreen
        mCanvas.drawPath(mPath, mPaint);
        // kill this so we don't double draw
        Toast.makeText(getContext(), "Deleted: " + percentTransparent(eraseableBitmap, 10), Toast.LENGTH_SHORT).show();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event)
    {
        float x = event.getX();
        float y = event.getY();

        switch (event.getAction())
        {
            case MotionEvent.ACTION_DOWN:
                touch_start(x, y);
                invalidate();
                break;
            case MotionEvent.ACTION_MOVE:
                touch_move(x, y);
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                touch_up();
                invalidate();
                break;
        }
        return true;
    }

    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);

    }

}

问题是您未能调用
PaintObjectInit()
方法,因此您使用默认绘制,因此使用
Color.BLACK
而不是
Color.TRANSPARENT
绘制。在构造函数底部添加对
PaintObjectInit()
的调用,它应该可以工作

另外,下面创建一个不可变的位图!看见因此,您的位图永远不会被修改。通过绘制路径和位图,可以在用户界面上隐藏这一事实

// "RECREATE" THE NEW BITMAP
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false);
return resizedBitmap;
尝试制作这样的可变位图--


我不知道为什么它不起作用,但是为什么不调试一下你的函数,看看你所有的变量是否正确,比如
xStep
,或者用1个像素的步数尝试函数,检查它是否进入for循环,如果是这样,你可以记录
bm.getPixel(x,y)
。然后你可能会自己弄明白为什么它不起作用。它进入循环内部。并且总是bm.getPixel(x,y)非零。因为我给它标度10,每次它迭代100次。所以我经历了大约20次迭代。对于所有这些像素,我得到了一个非零值。而且总是0.0%删除。我不知道为什么。你在哪里设置“擦除”像素为颜色。透明?触摸时,它会使像素颜色。沿路径右侧透明。?我认为覆盖绘制路径的所有像素都将设置为Color.TRANSPARENT。我从sdk的finger paint示例应用程序中获得了该代码。您知道如何计算擦除区域的百分比吗?请分享!谢谢,没有。在将视图对象添加到布局之前,我在activity类中调用它。因此,我的擦除部分正在工作。如果activity类是视图的受保护方法,您如何从该类调用
PaintObjectInit()
?您是否在此代码之外对对象的状态进行了任何其他更改?最好是让视图本身进行初始化,因此这一步是在重用视图时执行的。这是一件容易忘记的事情,当我复制你的代码时,显然遇到了麻烦。错误的根源是在
getResizedBitmap
方法中分配的不可变位图。编辑答案。现在我有另一个问题。现在像素变得透明了。但当我画这条线的时候,它就被复制了(画了两条线),当我在图像中触摸到上面的区域时。底部区域也将被删除。我想现在有两个位图。我用矩阵展开了它(作为你的答案),它只拉伸图像,而不改变原始位图中的宽度和高度(我实际上想要从这个方法中得到什么)。请帮我整理一下。非常感谢。
// "RECREATE" THE NEW BITMAP
Bitmap resizedBitmap = Bitmap.createBitmap(bm, 0, 0, width, height, matrix, false);
return resizedBitmap;
// "RECREATE" THE NEW BITMAP
        Bitmap resizedBitmap = Bitmap.createBitmap(newWidth, newHeight, Bitmap.Config.ARGB_8888);
        Canvas c = new Canvas(resizedBitmap);
        c.setMatrix(matrix);
        c.drawBitmap(bm, matrix, null);
        return resizedBitmap;