22

色が加算されるようにキャンバスにグラフィックをペイントしたい。たとえば、これを生成したい:
適切な加法混色

しかし、代わりに、私はこれを取得します:
私の結果

アルファが両方の背景とどのように相互作用するかを確認するために、半分が白で半分が黒の背景は意図的なものであることに注意してください。どちらのバックグラウンドでもこの作品をお楽しみいただければ幸いです。これが私のコードです:

public class VennColorsActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        class VennView extends View {
            public VennView(Context context) {
                super(context);
            }

            @Override
            protected void onDraw(Canvas canvas) {
                super.onDraw(canvas);
                int alpha = 60, val = 255;
                int ar = Color.argb(alpha, val, 0, 0);
                int ag = Color.argb(alpha, 0, val, 0);
                int ab = Color.argb(alpha, 0, 0, val);
                float w = canvas.getWidth();
                float h = canvas.getHeight();
                float cx = w / 2f;
                float cy = h / 2;
                float r = w / 5;
                float tx = (float) (r * Math.cos(30 * Math.PI / 180));
                float ty = (float) (r * Math.sin(30 * Math.PI / 180));
                float expand = 1.5f;
                Paint paint = new Paint();
                paint.setColor(Color.WHITE);
                canvas.drawRect(new Rect(0, 0, (int) w, (int) (h / 2)), paint);
                PorterDuff.Mode mode = android.graphics.PorterDuff.Mode.ADD;
                paint = new Paint(Paint.ANTI_ALIAS_FLAG);
                paint.setColorFilter(new PorterDuffColorFilter(ar, mode));
                paint.setColor(ar);
                canvas.drawCircle(cx, cy - r, expand * r, paint);
                paint.setColorFilter(new PorterDuffColorFilter(ag, mode));
                paint.setColor(ag);
                canvas.drawCircle(cx - tx, cy + ty, expand * r, paint);
                paint.setColorFilter(new PorterDuffColorFilter(ab, mode));
                paint.setColor(ab);
                canvas.drawCircle(cx + tx, cy + ty, expand * r, paint);
            }
        }
        this.setContentView(new VennView(this));
    }
}

Androidグラフィックスで加法混色を使用してペイントする方法を理解するのを手伝ってもらえますか?

4

2 に答える 2

33

あなたは正しい方向に進んでいます。コードには3つの主要な問題があります。

  • xferモードのisoカラーフィルターを設定する必要があります
  • 画像のレンダリングに一時ビットマップを使用する
  • 探している結果を得るには、アルファを0xFFにする必要があります

これがxferモードを使用して得たものです。私がやっていることは、すべてを一時的なビットマップに描画してから、ビットマップ全体をメインキャンバスにレンダリングすることです。

xferモードのルール

なぜ一時ビットマップが必要なのですか?良い質問!メインキャンバスにすべてを描画している場合、メインキャンバスの背景色と色がブレンドされるため、すべての色が混乱します。透明な一時ビットマップは、UIの他の部分から色を遠ざけるのに役立ちます

何も割り当てていないことを確認してくださいonDraw()。この方法ですぐにメモリが不足します。また、必要がなくなったときに一時ビットマップをリサイクルしたことを確認してください。

package com.example.stack2;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.os.Bundle;
import android.view.View;

public class YouAreWelcome extends Activity {

    Bitmap tempBmp = Bitmap.createBitmap(1, 1, Config.ARGB_8888);
    Canvas c = new Canvas();
    Paint paint = new Paint();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        class VennView extends View {
            public VennView(Context context) {
                super(context);

            }

            protected void onDraw(Canvas canvas) {
                super.onDraw(canvas);
                if(tempBmp.isRecycled() || tempBmp.getWidth()!=canvas.getWidth() || tempBmp.getHeight()!=canvas.getHeight())
                {
                    tempBmp.recycle();
                    tempBmp = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Config.ARGB_8888);
                    c.setBitmap(tempBmp);
                }

                    //clear previous drawings
                c.drawColor(Color.TRANSPARENT, Mode.CLEAR);

                int alpha = 255, val = 255;
                int ar = Color.argb(alpha, val, 0, 0);
                int ag = Color.argb(alpha, 0, val, 0);
                int ab = Color.argb(alpha, 0, 0, val);
                float w = canvas.getWidth();
                float h = canvas.getHeight();
                float cx = w / 2f;
                float cy = h / 2;
                float r = w / 5;
                float tx = (float) (r * Math.cos(30 * Math.PI / 180));
                float ty = (float) (r * Math.sin(30 * Math.PI / 180));
                float expand = 1.5f;
                paint.setAntiAlias(true);
                paint.setXfermode(new PorterDuffXfermode(Mode.ADD));
                paint.setColor(ar);
                c.drawCircle(cx, cy - r, expand * r, paint);
                paint.setColor(ag);
                c.drawCircle(cx - tx, cy + ty, expand * r, paint);
                paint.setColor(ab);
                c.drawCircle(cx + tx, cy + ty, expand * r, paint);
                canvas.drawBitmap(tempBmp, 0, 0, null);
            }
        }
        this.setContentView(new VennView(this));
    }
}
于 2012-08-07T02:03:15.317 に答える
3

再びパベルに感謝します。それは私が自分で理解するのは非常に困難だったでしょう。私は自分の質問に答えて詳細を掘り下げていますが、あなたの質問を最良の答えとして受け入れました。

画面外のビットマップ(およびCanvas)を作成および管理する必要がないことを私が好むのはあなたの言うとおりです。これが基本的に、この作業を行うには黒または白の背景で十分だと述べた理由です。

何かが機能しているのを見る前は、パフォーマンスには関心がありませんが、それ以降は注意が必要です。バージョンを編集して修正し、それらのメンバーを削除すると、以下の実装が得られます。

これは堅牢ですか?Canvas.drawColor()への2つの呼び出しも、1つに組み合わせることができると思われることに注意してください。

package com.superliminal.android.test.venn;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.os.Bundle;
import android.view.View;

public class VennColorsActivity extends Activity {
    private Paint paint = new Paint();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        class VennView extends View {
            public VennView(Context context) {
                super(context);
            }

            @Override
            protected void onDraw(Canvas canvas) {
                super.onDraw(canvas);
                canvas.drawColor(Color.BLACK);
                canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
                int alpha = 255, val = 255;
                int ar = Color.argb(alpha, val, 0, 0);
                int ag = Color.argb(alpha, 0, val, 0);
                int ab = Color.argb(alpha, 0, 0, val);
                float w = canvas.getWidth();
                float h = canvas.getHeight();
                float cx = w / 2f;
                float cy = h / 2;
                float r = w / 5;
                float tx = (float) (r * Math.cos(30 * Math.PI / 180));
                float ty = (float) (r * Math.sin(30 * Math.PI / 180));
                float expand = 1.5f;
                paint.setAntiAlias(true);
                paint.setXfermode(new PorterDuffXfermode(Mode.ADD));
                paint.setColor(ar);
                canvas.drawCircle(cx, cy - r, expand * r, paint);
                paint.setColor(ag);
                canvas.drawCircle(cx - tx, cy + ty, expand * r, paint);
                paint.setColor(ab);
                canvas.drawCircle(cx + tx, cy + ty, expand * r, paint);
            }
        }
        setContentView(new VennView(this));
    }
}
于 2012-08-07T03:41:52.537 に答える