2010-08-12 10 views
14

Intento borrar partes de un mapa de bits en mi aplicación Android utilizando Porter-Duff Xfermodes.Borrar partes del mapa de bits utilizando el modo PorterDuff

Tengo un fondo verde que se superpone con un mapa de bits azul. Cuando toco la pantalla, se supone que se creará un "agujero" en el mapa de bits superpuesto, haciendo que el fondo verde sea visible. En lugar de un agujero, mi código actual produce un punto negro.

A continuación se muestra mi código. ¿Alguna idea, qué estoy haciendo mal aquí?

/** 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; 
    } 

} 

Respuesta

6

En primer lugar, no estoy seguro de si ajustar el alfa a 0 en su objeto de pintura de borrado es una buena idea. Eso podría hacer que todo sea ineficaz.

Además, siempre debe usar Bitmap.Config.ARGB_8888 si está tratando con alfas.

Si tiene problemas con las cosas de PorterDuff, sugiero simplificar su enfoque para SOLAMENTE hacer eso (temporalmente). Eso te ayudará a reducir la parte que no funciona. Comente todo lo que tenga que ver con tocar y ver actualizaciones.

A continuación, puede seleccionar qué parte del dibujo no está funcionando bien. Configurar el constructor de la siguiente manera:

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 */ 
    ... 
} 

Si configura las cosas de esa manera, usted debería ser capaz de decir cómo su método PD está afectando el mapa de bits verde, y cambiar las cosas en consecuencia.

+0

Muchas gracias Josh! Crear el mapa de bits usando Bitmap.Config.ARGB_8888 en lugar de Bitmap.Config.RGB_565 resolvió el problema. En cuanto a efectivos: planeo aplicar el alfa de una ruta de pintura a mi mapa de bits en primer plano como siguiente paso. ¿Qué enfoque sugeriría en lugar de utilizar Porter-Duff con respecto al rendimiento del dibujo? – Philipp

+0

1. Cuando obtenga eventos táctiles en onTouch, use drawPath de vez en cuando para dibujar una ruta negra a una imagen transparente. Este es tu mapa de bits borrador. Si todavía no lo hace, la aplicación FingerPaint en demostraciones de API tiene un bonito código de ejemplo. 2. En onDraw, aplique el mapa de bits del borrador al mapa de bits azul ORIGINAL con el método PorterDuff adecuado. Esto cortará un todo en el mapa de bits azul con la forma de lo que has borrado (el camino negro) hasta el momento. 3. Todavía en onDraw, coloque el mapa de bits verde en la pantalla, seguido por el mapa de bits azul recién cortado. – Josh

+0

Tenga en cuenta que lo anterior podría ser costoso en cada ciclo de extracción: busque en las regiones de recorte para limitar el área que está actualizando a solo lo que el usuario ha cambiado en el mapa de bits del borrador. – Josh

9

código Aquí está trabajando ... puede ayudar a alguien

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

gracias Me pareció útil, puede convertir el mapa de bits así sin embargo con nuestra codificación dura del tamaño. 'bitmap = bm.copy (Config.ARGB_8888, true);' – schwiz

+0

Gracias también encontré esto realmente útil. Estaba buscando esta solución el año pasado. – Sourabh

+0

Tenga en cuenta que si desea hacer un agujero en la imagen, simplemente debe establecer el color de fondo en Color.TRANSPARENT en lugar de Color.GREEN. Estaba teniendo mucho tiempo para armar el código de trabajo de todos los ejemplos a medias, muchas gracias por publicar un ejemplo completo :) – adavea

0

Aquí es otro avance para su solución ... See Demo example

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

read more

Cuestiones relacionadas