Cómo pintar con alfa?

Quiero pintar gráficos en una lona de manera que los colores sean aditivos. Por ejemplo, quiero producir esto:
Colores aditivos adecuados

Pero en su lugar, tengo esto:
Mis resultados

Tenga en cuenta que el medio fondo blanco, medio negro es intencional, sólo para ver cómo el alfa interactúa con ambos fondos. Estaré feliz de tener este trabajo con cualquier fondo. Aquí está mi código:

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

¿Puede alguien por favor ayudarme a entender cómo pintar con colores aditivos en los gráficos de Android?

Estás en el camino correcto. Existen 3 problemas principales en su código:

  • Usted necesita fijar el filtro del iso del modo del xfer
  • Utilice el mapa de bits temporal para representar su imagen
  • Alpha debe ser 0xFF para obtener resultados que busca

Esto es lo que tengo usando el modo xfer. Lo que estoy haciendo – está dibujando todo en mapa de bits temporal y, a continuación, la representación de mapa de bits completo a la lona principal.

reglas del modo xfer

Usted pregunta por qué necesita bitmap de temp? ¡Buena pregunta! Si usted está dibujando todo en un lienzo principal, sus colores serán mezclados con el color principal del fondo de la lona, ​​así que todos los colores conseguirán desordenado. El mapa de bits temporal transparente ayuda a mantener los colores alejados de otras partes de la interfaz de usuario

Asegúrese de que no está asignando nada en onDraw() – se agotará la memoria muy pronto de esta manera .. También asegúrese de que ha reciclado su mapa de bits temp cuando ya no lo necesita.

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

Gracias de nuevo Pavel. Eso habría sido muy difícil para mí haber descubierto por mi cuenta. Estoy respondiendo a mi propia pregunta para profundizar en detalles, pero he aceptado la suya como la mejor respuesta.

Tienes razón que prefiero no tener que crear y administrar un Bitmap (y un lienzo) fuera de la pantalla. Esa es la razón esencial por la que he mencionado que un fondo negro o blanco estaría bien para hacer que este trabajo.

Nunca estoy preocupado por el rendimiento antes de ver algo funcionando, pero comparto su precaución después de ese punto. Editar su versión para corregir eso y quitar esos miembros da la puesta en práctica abajo.

¿Es esto robusto? Tenga en cuenta las dos llamadas a Canvas.drawColor () que sospecho que también podría ser combinado en uno.

 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)); } } 
FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.