2011-06-21 10 views
9

Tworzę mapę bitową, następnie rysuję na niej drugą mapę bitową koloru jednolitego. A teraz chcę zmienić pierwszą bitmapę, aby stały kolor, który narysowałem, był przezroczysty.Kolor maski bitmapy Androida, usuń kolor

Po prostu chcę usunąć wszystkie piksele jednego koloru z bitmapy. Próbowałem wypróbować każdy filtr kolorów i xfermode bez powodzenia, czy jest jakaś inna możliwość usunięcia koloru innego niż piksel po pikselu?

Odpowiedz

0

Piksel po pikselu nie jest złą opcją. Po prostu nie wołaj setPixel w pętli. Wypełnij tablicę argb int za pomocą getPixels, zmodyfikuj ją w miejscu, jeśli nie potrzebujesz zachować oryginału, a następnie wywołaj setPixels na końcu. Możesz zrobić to rząd po rzędzie, jeśli pamięć jest problemem, lub możesz po prostu zrobić wszystko w jednym ujęciu. Nie musisz wypełniać całej bitmapy dla koloru nakładki, ponieważ właśnie wykonujesz prostą zamianę (jeśli bieżącym pikselem jest color1, ustaw na color2).

+0

Dzięki, ale w końcu zorientowałem się, jak to zrobić z porterduff, xfermode (xor) zrobił to, ale zastosowałem do innej bitmapy, najpierw scaliłem maskę i źródło i próbowałem narysować to na płótnie z filtrem koloru, ale w końcu zrozumiałem że powinienem używać xfermode podczas rysowania maski na źródle, a nie na płótnie :) – ZZZ

12

Umożliwia usunięcie określonego koloru z bitmapy. Główną częścią jest użycie AvoidXfermode. Powinno to również działać, jeśli próbujesz zmienić jeden kolor na inny.

Należy dodać, że to odpowiada na pytanie tytuł usuwania koloru z bitmapy. Konkretne pytanie jest prawdopodobnie lepiej rozwiązane przy użyciu PorterDuff Xfermode, jak powiedział 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

To nie działa na poziomie interfejsu API 16, a AvoidXferMode został przestarzały bez objaśnień. To rozwiązanie rzeczywiście działa aż do poziomu interfejsu API 15. –

+1

@LeoAccend Patrząc na historię zmian kodu źródłowego, wydaje się, że została ona uznana za przestarzałą, ponieważ nie jest obsługiwana przy akceleracji sprzętowej. –

2

user487252's solution działa jak czar się aż do poziomu API 16 (Jelly Bean), po czym AvoidXfermode nie wydają się działać w ogóle.

W moim przypadku użycia renderowałem stronę PDF (przez APV PDFView) do tablicy pikseli int[], którą zamierzam przekazać Bitmap.createBitmap(int[], int, int, Bitmap.Config). Ta strona zawiera rysunki rysowane na białym tle i muszę usunąć tło, zachowując antyaliasing.

Nie mogłem znaleźć trybu Porter-Duff, który zrobił dokładnie to, co chciałem, więc skończyłem na wyboczeniu i iteracji poprzez piksele i przekształceniu ich jeden po drugim. Wynik był zaskakująco prosty i wydajnych:

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

Jest idealny do rysowania linii sztuki, ponieważ każdy kolor może być stosowany dla linii bez utraty antyaliasingu. Używam tutaj czerwonego kanału, ale możesz użyć koloru zielonego przesuwając bity 16 zamiast 8 lub niebieski, przesuwając 24.

+0

Chciałbym użyć twojego kodu, ale nie mam pojęcia, jak używać z nim niestandardowego koloru. Proszę o pomoc –

+0

Możesz zamienić 'Color.BLACK' w powyższym kodzie, aby uzyskać różne kolorowe linie (np.' Color.RED' lub '0xFF3399FF'). –

+0

Wielkie dzięki! Działa świetnie –

Powiązane problemy