0

ユーザーが画面上で指をドラッグすると、ブラシは下の画像/ビットマップのアルファのみを変更するブラシ効果を作成したいと思います。たとえば、ブラシの不透明度が 50% に設定されている場合、ブラシを適用する必要があります。

  1. その領域のアルファ/不透明度を設定します。ビットマップ全体ではなく、その領域のみを設定します。
  2. ビットマップ領域の基になる色は変更しないでください。

つまり、ブラシは色ではなくアルファ透明度にのみ影響する必要があります。私は次のコードから始めています:

public class DrawingView extends View {

    //drawing path
    private Path drawPath;
    //drawing and canvas paint
    private Paint drawPaint, canvasPaint;
    //initial color
    private int paintColor = 0xFFFF0000, paintAlpha = 255;
    //canvas
    private Canvas drawCanvas;
    //canvas bitmap
    private Bitmap canvasBitmap;

    //constructor
    public DrawingView(Context context, AttributeSet attrs){
        super(context, attrs);
        setupDrawing();
    }

    //prepare drawing
    private void setupDrawing(){
        drawPath = new Path();
        drawPaint = new Paint();
        drawPaint.setColor(paintColor);
        drawPaint.setAntiAlias(true);
        drawPaint.setStrokeWidth(50);
        drawPaint.setStyle(Paint.Style.STROKE);
        drawPaint.setStrokeJoin(Paint.Join.ROUND);
        drawPaint.setStrokeCap(Paint.Cap.ROUND);
        canvasPaint = new Paint(Paint.DITHER_FLAG);
    }

    //view assigned size
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
        drawCanvas = new Canvas(canvasBitmap);
    }

    //draw view
    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
        canvas.drawPath(drawPath, drawPaint);
    }

    //respond to touch interaction
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float touchX = event.getX();
        float touchY = event.getY();
        //respond to down, move and up events
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            drawPath.moveTo(touchX, touchY);
            break;
        case MotionEvent.ACTION_MOVE:
            drawPath.lineTo(touchX, touchY);
            break;
        case MotionEvent.ACTION_UP:
            drawPath.lineTo(touchX, touchY);
            drawCanvas.drawPath(drawPath, drawPaint);
            drawPath.reset();
            break;
        default:
            return false;
        }
        //redraw
        invalidate();
        return true;
    }

    //return current alpha
    public int getPaintAlpha(){
        return Math.round((float)paintAlpha/255*100);
    }

    //set alpha
    public void setPaintAlpha(int newAlpha){
        paintAlpha=Math.round((float)newAlpha/100*255);
        drawPaint.setColor(paintColor);
        drawPaint.setAlpha(paintAlpha);
    }
}

お気づきのように、このブラシには塗りつぶしの色が必要です。それは避けたいものです。透明度のあるブラシが必要ですが、色は必要ありません。

目的を達成するための別の方法があれば、それで問題ありません。

4

1 に答える 1

0

絶対アルファ値を設定すると、ビットマップでピクセルをいじる必要が生じる可能性があります。

必要なものに最も近い Porter-Duff モードは、消しゴムのように機能する DST_OUT です。

このコードを試して、それに近いかどうかを確認してください。

       drawPaint.setColor(Color.BLACK);  // the color doesn't really matter
       drawPaint.setAlpha(255 - alpha);  // inverse of the alpha result you want
       drawPaint.setXferMode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));

これにより、同じ場所を描画するたびに画像のピクセルがどんどん明るくなりますが、これはおそらくあなたが望んでいることではありません。その場合、より複雑になり、カラー + アルファ パスを別のビットマップに描画し、次にを使用して画像ビットマップ上にそのPorterDuff.Mode.DST_OUTビットマップを描画する必要があります。

ColorFilter残念なことに、自分のやりたいことを正確に実行するカスタムを単純に実装することはできません。これらのグラフィックス操作はすべてネイティブ スペースで行われ、Google は私たちが単なる人間がそのようなことをいじることを望んでいません。

于 2016-11-18T16:09:44.697 に答える