2011-06-21 27 views
9

Estoy creando un mapa de bits; a continuación, dibujo un segundo mapa de bits de color sólido encima. Y ahora quiero cambiar el primer mapa de bits, así que el color sólido que dibujé será transparente.Color de la máscara de mapa de bits de Android, eliminar el color

O simplemente, quiero eliminar todos los píxeles de un color del mapa de bits. He probado todos los filtros de color, y xfermode sin suerte, ¿hay alguna otra posibilidad de eliminar el color que lo hace píxel por píxel?

Respuesta

0

Pixel by pixel no es una mala opción. Simplemente no llame a setPixel dentro de su bucle. Llene una matriz de argb con GetPixels, modifíquela en su lugar si no necesita conservar el original, y luego llame setPixels al final. Puede hacer esta fila por fila si la memoria es una preocupación, o puede hacer todo en una sola toma. No es necesario que llene un mapa de bits completo para el color de superposición ya que simplemente haría una sustitución simple (si el píxel actual es color1, configurado como color2).

+0

Gracias, pero finalmente descubrí cómo hacerlo con porterduff, xfermode (xor) lo hizo, pero se aplicó a otro mapa de bits, primero fusioné la máscara y la fuente e intenté dibujarlo en el lienzo con filtro de color, pero finalmente pensé que debería usar xfermode al dibujar la máscara en el código fuente, no en el lienzo :) – ZZZ

12

Esto funciona para eliminar un color determinado de un mapa de bits. La parte principal es el uso de AvoidXfermode. También debería funcionar si intenta cambiar un color a otro color.

Debo agregar que esto responde al título de pregunta de quitar un color de un mapa de bits. La pregunta específica probablemente se resuelva mejor utilizando PorterDuff Xfermode como dijo el OP.

// start with a Bitmap bmp 

// make a mutable copy and a canvas from this mutable bitmap 
Bitmap mb = bmp.copy(Bitmap.Config.ARGB_8888, true); 
Canvas c = new Canvas(mb); 

// get the int for the colour which needs to be removed 
Paint p = new Paint(); 
p.setARGB(255, 255, 0, 0); // ARGB for the color, in this case red 
int removeColor = p.getColor(); // store this color's int for later use 

// Next, set the alpha of the paint to transparent so the color can be removed. 
// This could also be non-transparent and be used to turn one color into another color    
p.setAlpha(0); 

// then, set the Xfermode of the pain to AvoidXfermode 
// removeColor is the color that will be replaced with the pain't color 
// 0 is the tolerance (in this case, only the color to be removed is targetted) 
// Mode.TARGET means pixels with color the same as removeColor are drawn on 
p.setXfermode(new AvoidXfermode(removeColor, 0, AvoidXfermode.Mode.TARGET)); 

// draw transparent on the "brown" pixels 
c.drawPaint(p); 

// mb should now have transparent pixels where they were red before 
+1

Parece que esto no funciona en el nivel API 16, y el modo EvitarXForo ha quedado obsoleto sin explicación. Sin embargo, esta solución sí funciona hasta el nivel API 15. –

+1

@LeoAccend Al observar el historial de cambios para el código fuente, parece haber quedado obsoleto porque no es compatible con la aceleración de hardware. –

2

user487252's solution funciona como un encanto hasta el nivel API 16 (Jelly Bean), después de lo cual AvoidXfermode no parece funcionar en absoluto.

En mi caso de uso particular, he renderizado una página de un PDF (a través de APV PDFView) en una matriz de píxeles int[] que voy a pasar al Bitmap.createBitmap(int[], int, int, Bitmap.Config). Esta página contiene dibujos lineales dibujados sobre un fondo blanco, y necesito eliminar el fondo conservando el anti-aliasing.

No pude encontrar un modo Porter-Duff que hiciera exactamente lo que quería, así que terminé abrochando e iterando a través de los píxeles y transformándolos uno por uno. El resultado fue sorprendentemente simple y performant:

int [] pixels = ...; 

for(int i = 0; i < pixels.length; i++) { 
    // Invert the red channel as an alpha bitmask for the desired color. 
    pixels[i] = ~(pixels[i] << 8 & 0xFF000000) & Color.BLACK; 
} 

Bitmap bitmap = Bitmap.createBitmap(pixels, width, height, Bitmap.Config.ARGB_8888); 

Esto es perfecto para la línea arte dibujo, puesto que cualquier color puede ser utilizado para las líneas sin perder el anti-aliasing. Estoy usando el canal rojo aquí, pero puede usar verde cambiando 16 bits en lugar de 8, o azul cambiando 24.

+0

me gustaría utilizar su código, pero no tengo ni idea de cómo usar un color personalizado con él. Ayuda por favor –

+0

Puede reemplazar 'Color.BLACK' en el código anterior para obtener líneas de diferentes colores (por ejemplo,' Color.RED', o '0xFF3399FF'). –

+0

¡Muchas gracias! Funciona genial –

Cuestiones relacionadas