2012-11-08 14 views
15

próbuję wyciąć kółko z kwadratowym bitmapy za pomocą następującego koduAndroid - cięcie okrąg z kwadratowym Bitmap

 Canvas canvas=new Canvas(bitmapimg); 
     int circleXCoord = bitmapimg .getWidth()/2; 
     int circleYCoord = bitmapimg .getHeight()/2; 
     int circleRadius = bitmapimg .getWidth()/2; 

     Rect rect = new Rect(circleXCoord - circleRadius, circleYCoord - circleRadius, circleXCoord + circleRadius, circleYCoord + circleRadius); 

     int width = rect.width(); 
     int height = rect.height(); 

     Paint paint = new Paint(); 
     paint.setStyle(Paint.Style.STROKE); 
     paint.setColor(Color.BLUE); 
     canvas.drawRect(rect, paint); 
     canvas.drawBitmap(bitmapimg , rect, rect, paint); 
     Path p = new Path(); 
     p.addCircle(circleXCoord, circleYCoord, width/2F, Path.Direction.CW); 
     canvas.clipPath(p, Region.Op.DIFFERENCE); 
     canvas.drawColor(0, PorterDuff.Mode.CLEAR); 

Chodzi o to, aby dołączyć do kwadratu (prostokątne) bitmapy na płótno, a następnie przypiąć okrągła ścieżka. Usuń różnicę między prostokątem a okręgiem (uczyń ją przezroczystą).

Kod działa poprawnie na Androidzie 4, ale na urządzeniu z systemem Android 2.3.3 obszar różnic jest czarny, a nie przezroczysty.

Czy czegoś tu brakuje, czy PorterDuff.Mode.CLEAR nie jest obsługiwany w pierniku? Czy istnieje lepszy sposób na wycięcie koła z kwadratu w systemie Android?

Odpowiedz

36

Wygląda PorterDuff.Mode.Clear nie działa dla pierników

rozwiązało problem (cięcie koła z placu przy użyciu tego kodu)

public Bitmap BitmapCircularCroper(Bitmap bitmapimg){ 
    Bitmap output = Bitmap.createBitmap(bitmapimg.getWidth(), 
      bitmapimg.getHeight(), Bitmap.Config.ARGB_8888); 
    Canvas canvas = new Canvas(output); 

    final int color = 0xff424242; 
    final Paint paint = new Paint(); 
    final Rect rect = new Rect(0, 0, bitmapimg.getWidth(), 
      bitmapimg.getHeight()); 

    paint.setAntiAlias(true); 
    canvas.drawARGB(0, 0, 0, 0); 
    paint.setColor(color); 
    canvas.drawCircle(bitmapimg.getWidth()/2, 
      bitmapimg.getHeight()/2, bitmapimg.getWidth()/2, paint); 
    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); 
    canvas.drawBitmap(bitmapimg, rect, rect, paint); 
    return output; 

} 
+0

coraz okrągły bitmapę ale dlaczego kwadratowy obszar przezroczysty czarny pokazano w moim przypadku? – Ram

2

Dla każdego, że wciąż patrząc na to, to odpowiedź będzie powoduje kilka problemów.

1.) Obszar roboczy, który tworzysz w tym wystąpieniu, nie będzie miał przyspieszania sprzętowego. Nawet jeśli twój obiekt Paint ma wygładzanie, płótno nie będzie. Spowoduje to artefaktowanie, gdy zdecydujesz się na pomalowanie tego z powrotem na oryginalne płótno w wywołaniu onDraw().

2.) To zabiera znacznie więcej zasobów. Musisz stworzyć drugą bitmapę (która może spowodować OOM) i dodatkowe płótno oraz wszystkie inne zmiany, które musisz wykonać.

Proszę sprawdzić odpowiedź Romain Guy. Tworzysz bitmapshader, a następnie tworzysz RoundRect, który daje krąg. Musisz tylko znać wymiary swojego RectF, aby mógł właściwie określić okrąg.

Oznacza to, że jeśli znasz punkt środkowy (x, y) i promień, możesz łatwo określić współczynnik RectF.

left = x - radius; 
top = y - radius; 
right = x + radius; 
bottom = y + radius; 

To oznacza również, że z tym rozwiązaniem pisał poniżej trzeba tylko zwrócić na ekran raz, wszystko odbywa się w buforze poza ekranem.

http://www.curious-creature.com/2012/12/11/android-recipe-1-image-with-rounded-corners/

Najlepszym rozwiązaniem jest znaleźć tutaj:

BitmapShader shader; 
shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); 

Paint paint = new Paint(); 
paint.setAntiAlias(true); 
paint.setShader(shader); 

RectF rect = new RectF(0.0f, 0.0f, width, height); 

// rect contains the bounds of the shape 
// radius is the radius in pixels of the rounded corners 
// paint contains the shader that will texture the shape 
canvas.drawRoundRect(rect, radius, radius, paint); 
+0

Bardzo przydatne do narysowania okrągłego zdjęcia jako dużej ikony powiadomienia, które musi być bitmapą. Dzięki – user3175580

3
import android.graphics.PorterDuff.Mode; 
import android.graphics.Bitmap.Config; 

public static Bitmap getCircularBitmap(Bitmap bitmap) 
{ 
    Bitmap output; 

    if (bitmap.getWidth() > bitmap.getHeight()) { 
     output = Bitmap.createBitmap(bitmap.getHeight(), bitmap.getHeight(), Config.ARGB_8888); 
    } else { 
     output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getWidth(), Config.ARGB_8888); 
    } 

    Canvas canvas = new Canvas(output); 

    final int color = 0xff424242; 
    final Paint paint = new Paint(); 
    final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); 

    float r = 0; 

    if (bitmap.getWidth() > bitmap.getHeight()) { 
     r = bitmap.getHeight()/2; 
    } else { 
     r = bitmap.getWidth()/2; 
    } 

    paint.setAntiAlias(true); 
    canvas.drawARGB(0, 0, 0, 0); 
    paint.setColor(color); 
    canvas.drawCircle(r, r, r, paint); 
    paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); 
    canvas.drawBitmap(bitmap, rect, rect, paint); 

    return output; 
}