Подтвердить что ты не робот

Стереть части растровых изображений, используя режим PorterDuff

Я пытаюсь стереть части растрового изображения в приложении для Android, используя Porter-Duff Xfermodes.

У меня есть зеленый фон, который накладывается синим растровым изображением. Когда я прикасаюсь к экрану, должно быть создано "отверстие" в наложенном растровом изображении, что делает зеленый фон видимым. Вместо отверстия мой текущий код создает черную точку.

Ниже мой код. Любые идеи, что я здесь делаю неправильно?

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
            WindowManager.LayoutParams.FLAG_FULLSCREEN);
    setContentView(new DrawView(this));
}

public class DrawView extends View implements OnTouchListener {

    private int x = 0;
    private int y = 0;

    Bitmap bitmap;
    Canvas bitmapCanvas;

    private final Paint paint = new Paint();
    private final Paint eraserPaint = new Paint();

    public DrawView(Context context) {
        super(context);
        setFocusable(true);
        setFocusableInTouchMode(true);

        this.setOnTouchListener(this);

        // Set background
        this.setBackgroundColor(Color.GREEN);

        // Set bitmap
        bitmap = Bitmap.createBitmap(320, 480, Bitmap.Config.RGB_565);
        bitmapCanvas = new Canvas();
        bitmapCanvas.setBitmap(bitmap);
        bitmapCanvas.drawColor(Color.BLUE);

        // Set eraser paint properties
        eraserPaint.setAlpha(0);
        eraserPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
        eraserPaint.setAntiAlias(true);
    }

    @Override
    public void onDraw(Canvas canvas) {
        bitmapCanvas.drawColor(Color.BLUE);
        bitmapCanvas.drawCircle(x, y, 10, eraserPaint);

        canvas.drawBitmap(bitmap, 0, 0, paint);
    }

    public boolean onTouch(View view, MotionEvent event) {
        x = (int) event.getX();
        y = (int) event.getY();

        invalidate();
        return true;
    }

}
4b9b3361

Ответ 1

Сначала подумал, я не уверен, что установка альфа-кода на объект стирания - это хорошая идея. Это может сделать все это неэффективным.

Кроме того, вы всегда должны использовать Bitmap.Config.ARGB_8888, если вы имеете дело с альфами.

Если у вас возникли проблемы с материалом PorterDuff, я бы предложил упростить свой подход, чтобы ТОЛЬКО делать это (временно). Это поможет вам сузить часть, которая не работает. Прокомментируйте все, что касается касания и просмотра обновлений.

Затем вы можете указать, какая часть чертежа работает неправильно. Настройте свой конструктор следующим образом:

DrawView()
{
    /* Create the background green bitmap */
    ...

    /* Create foreground transparent bitmap */
    ...

    /* Draw a blue circle on the foreground bitmap */
    ...

    /* Apply the foreground to the background bitmap
       using a PorterDuff method */
    ...
}

onDraw()
{
    /* Simply draw the background bitmap */
    ...
}

Если вы настроите это так, вы сможете рассказать, как ваш метод PD влияет на зеленый растровый рисунок, и соответствующим образом изменить его.

Ответ 2

Вот рабочий код... может помочь кому-то

public class ImageDemo extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(new Panel(this));   
    }

    class Panel extends View {

        private Bitmap  mBitmap;
        private Canvas  mCanvas;
        private Path    mPath;
        private Paint   mPaint;

        Bitmap bitmap;
        Canvas pcanvas;

        int x = 0;
        int y =0;
        int r =0;

        public Panel(Context context) {
            super(context);

            Log.v("Panel", ">>>>>>");

            setFocusable(true);
            setBackgroundColor(Color.GREEN);

            // setting paint 
            mPaint = new Paint();
            mPaint.setAlpha(0);
            mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
            mPaint.setAntiAlias(true);

            // getting image from resources
            Resources r = this.getContext().getResources();

            Bitmap bm = BitmapFactory.decodeResource(getResources(),  R.drawable.mickey);

            // converting image bitmap into mutable bitmap  
            bitmap =  bm.createBitmap(295, 260, Config.ARGB_8888);
            pcanvas = new Canvas();
            pcanvas.setBitmap(bitmap);    // drawXY will result on that Bitmap
            pcanvas.drawBitmap(bm, 0, 0, null);           
        }

        @Override
        protected void onDraw(Canvas canvas) {  
            // draw a circle that is  erasing bitmap            
            pcanvas.drawCircle(x, y, r, mPaint);

            canvas.drawBitmap(bitmap, 0, 0,null);

            super.onDraw(canvas);
        }       

        @Override
        public boolean onTouchEvent(MotionEvent event) {        
             // set parameter to draw circle on touch event
             x = (int) event.getX();
             y = (int) event.getY();

             r =20;
             // At last invalidate canvas
             invalidate();
             return true;
        }
    }
}

Ответ 3

Вот еще одно продвижение для вашего решения... См. демонстрационный пример

public class MainActivity extends Activity {

    Bitmap bp;
    Canvas bitmapCanvas;
    DrawView drawImg;
    LinearLayout ln1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);
        ln1 = (LinearLayout) findViewById(R.id.ln1);
        drawImg = new DrawView(this);
        ln1.addView(drawImg);

    }



    public class DrawView extends View implements View.OnTouchListener {

        private int x = 0;
        private int y = 0;

        Bitmap bitmap;
        Path circlePath;
        Paint circlePaint;

        private final Paint paint = new Paint();
        private final Paint eraserPaint = new Paint();


        public DrawView(Context context){
            super(context);
            setFocusable(true);
            setFocusableInTouchMode(true);
            this.setOnTouchListener(this);

            // Set background
            this.setBackgroundColor(Color.CYAN);
            bp = BitmapFactory.decodeResource(getResources(), R.drawable.bg);

            // Set bitmap
            bitmap = Bitmap.createBitmap(320, 480, Bitmap.Config.ARGB_8888);
            bitmapCanvas = new Canvas();
            bitmapCanvas.setBitmap(bitmap);
            bitmapCanvas.drawColor(Color.TRANSPARENT);
            bitmapCanvas.drawBitmap(bp, 0, 0, null);

            circlePath = new Path();
            circlePaint = new Paint();
            circlePaint.setAntiAlias(true);
            circlePaint.setColor(Color.BLUE);
            circlePaint.setStyle(Paint.Style.STROKE);
            circlePaint.setStrokeJoin(Paint.Join.MITER);
            circlePaint.setStrokeWidth(4f);

            // Set eraser paint properties
            eraserPaint.setAlpha(0);
            eraserPaint.setStrokeJoin(Paint.Join.ROUND);
            eraserPaint.setStrokeCap(Paint.Cap.ROUND);
            eraserPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
            eraserPaint.setAntiAlias(true);

        }

        @Override
        public void onDraw(Canvas canvas) {

            canvas.drawBitmap(bitmap, 0, 0, paint);
            bitmapCanvas.drawCircle(x, y, 30, eraserPaint);

            canvas.drawPath(circlePath, circlePaint);
        }

        public boolean onTouch(View view, MotionEvent event) {
            x = (int) event.getX();
            y = (int) event.getY();

            bitmapCanvas.drawCircle(x, y, 30, eraserPaint);

            circlePath.reset();
            circlePath.addCircle(x, y, 30, Path.Direction.CW);

            int ac=event.getAction();
            switch(ac){
                case MotionEvent.ACTION_UP:
                    Toast.makeText(MainActivity.this, String.valueOf(x), Toast.LENGTH_SHORT).show();
                    circlePath.reset();
                    break;
            }
            invalidate();
            return true;
        }
    }
}

подробнее