2012-08-07 35 views
15

キャンバスにグラフィックスをペイントして、色が追加されるようにしたい。例えば、私はこれを生成します:アルファでペイントする方法は?


Proper additive colorsをしかし、その代わりに、私はこれを取得:ハーフ&ハーフ、白、黒の背景にはちょうどアルファは両方と対話する方法を確認するために、意図的であることを
My results

注意を背景。私はどちらのバックグラウンドでもこの仕事をすることができてうれしいです。ここに私のコードは次のとおりです。

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のグラフィックスに添加剤の色でペイントする方法を理解する助けてくださいことはできますか?

答えて

26

あなたは正しい方向にあります。あなたのコード内の3つの主要な問題があります:あなたは、あなたのイメージレンダリングのためのモード、ISOカラーフィルタに

  • 使用の一時ビットマップをXFER設定する必要が

    • アルファは、あなたが探している結果を得るためには0xFFをする必要があります

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

    xfer mode rules

    は、なぜあなたは一時ビットマップが必要なのでしょうか?良い質問!メインキャンバス上のすべてを描画している場合、色はメインキャンバスの背景色とブレンドされ、すべての色が混乱することになります。あなたはこのように非常にすぐにメモリを実行します..また、あなたがあなたの一時ビットマップを再利用していることを確認します - 透明一時ビットマップは、あなたがonDraw()に何を割り当てていないことを確認してください離れてUI

    の他の部分のあなたの色を維持するのに役立ちますあなたがもはやそれを必要としないとき。

    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)); 
        } 
    } 
    
  • +1

    ありがとうございました。とても速い! –

    +3

    BTW、SDKバージョン8と互換性のあるPorterDuff.Mode.ADDの代替案がありますか?ドキュメンテーションによると、ADDはバージョン8で追加されましたが、それはあります。これはバージョン11で実際に導入され、私のウィジェットをインストールすることが許可されていない古いデバイスでクラッシュしました。 –

    +1

    これは素晴らしいことです!お互いに重なるビットマップにこのテクニックを適用できますか? –

    2

    おかげさまでもう一度パベル。それは私が自分で考え出したことは非常に困難でした。細部まで掘り下げるために私自身の質問に答えていますが、私はあなたを最高の答えとして受け入れました。

    私はオフスクリーンのビットマップ(とキャンバス)を作成して管理する必要がない方がいいです。それは本質的に、私は黒や白の背景がこの仕事をする上でうまくいくと述べました。

    私は何か動作する前にパフォーマンスに関心を持つことはありませんが、その後は注意を共有します。バージョンを編集してそれらのメンバーを削除すると、以下の実装が得られます。

    これは堅牢ですか? 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)); 
        } 
    } 
    
    +1

    この解決法も正しいです。別のビットマップを使用することを提案しました。通常、必要な色のみをブレンドし、UIの残りの部分と混乱させたくないからです。あなたのコードに対する唯一のコメントは 'canvas.drawColor(Color.BLACK);'呼び出しは 'canvas.drawColor(Color.TRANSPARENT、Mode.CLEAR);'を呼び出して領域全体をクリアしているので役に立たないということです。だから理論的にはこの行を削除することができます –

    +0

    @Melinda Greenどのように私は、異なるネットバックグラウンドの色を与えることができるように自分のアクティビティ内のすべてのボタンクリックでキャンバスのペイントの色を変更することができます – Erum

    +0

    @Erum HannanちょうどボタンのonClickメソッドで色を保存し、その色をonDrawでcanvas.drawColorの背景色として使用します。 –

    関連する問題