2013-01-17 6 views
15

Mam niestandardową View, która zawsze rysuje Bitmap przy określonym obrocie. Zastępuję metodę onDraw, obracam Canvas i rysuję mapę bitową za pomocą wygładzonego Paint.Bitmapa nie jest wytłoczona wygładzona

public RotatedImageView(Context context, AttributeSet attrs, int defStyle) { 
    super(context, attrs, defStyle); 
    someBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.placeholder); 
} 

@Override 
protected void onDraw(Canvas canvas) { 

    // Save and rotate canvas 
    canvas.save(); 
    canvas.rotate(3F, getWidth()/2, getHeight()); 

    // Draw the icon 
    Paint p = new Paint(Paint.ANTI_ALIAS_FLAG); 
    canvas.drawBitmap(someBitmap, 0, 0, p); 
    canvas.drawRoundRect(new RectF(75, 50, 225, 200), 10, 10, p); 

    // All done; restore canvas 
    canvas.restore(); 
} 

Jednak zawsze otrzymuję postrzępione krawędzie w bitmapie. Zwróć uwagę, że prostokąt o prostokątach ma ładnie wygładzone krawędzie. Ponadto, po zastosowaniu p.setFilterBitmap(true); działa to (powierzchnia bitmapy jest poprawnie filtrowana/wygładzona). Czy czegoś brakuje?

No anti-aliasing on the photo

Oto minimalne Android projekt z izolowanym przykład jednym ekranie, który pokazuje View, która wciąga bez wygładzoną bitmapę, ładowany z zasobu: https://bitbucket.org/erickok/antialiastest

UPDATE: mam próbowałem również:

Paint p = new Paint(); 
    p.setAntiAlias(true); 
    p.setFilterBitmap(true); 
    p.setDither(true); 
    canvas.drawBitmap(someBitmap, 0, 0, p); 

ale to nie pomaga, jak setFilterBitmap filtruje powierzchni; nie zapobiega wygładzaniu krawędzi. Ponadto, setAntiAlias działa tak samo, jak bezpośrednio ustawia flagę w konstruktorze Paint. W razie wątpliwości wypróbuj mój minimalny projekt testowy. Dziękuję bardzo za każdą pomoc!

Odpowiedz

17

Znalazłem, dlaczego nie otrzymałem anty-aliasingu: przyspieszenie sprzętowe. Po tym, jak zostałem (przez czysty przypadek) przetestowany na moim Nexusie, nagle zadziałało, a mój Nexus 7 nie. Okazuje się, że ANTI_ALIAS_FLAG nic nie robi, gdy Canvas jest rysowany przy użyciu przyspieszenia sprzętowego. Z tym wglądem znalazłem Romain Guy's answer on StackOverflow, który odpowiada na moje pytanie.

Rozwiązaniami wydają się być: dodanie przezroczystej ramki do każdej bitmapy (ręcznie lub w locie) lub "zrobienie czegoś z shaderem".Nie są dla mnie zbyt atrakcyjne. Zamiast tego I disabled hardware acceleration w moim widoku niestandardowym przy użyciu metody setLayerType. Zauważ, że jest to dostępne od poziomu API 11, ale (nie przez przypadek) nie będziesz musiał zajmować się akceleracją sprzętową w jakikolwiek inny sposób. Dlatego dodałem, w widoku konstruktora:

if (android.os.Build.VERSION.SDK_INT >= 11) { 
     setLayerType(View.LAYER_TYPE_SOFTWARE, null); 
    } 

Zaktualizowałem powyższy projekt open-source na BitBucket dla zainteresowanych.

6

W moim przypadku to zrobił, ale może być ona lubi zrobiłeś:

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

Wystarczy spróbować.

Powodzenia!

+0

Dzięki za odpowiedź. Jest to równe temu, co zrobiłem niestety, więc ma ten sam efekt (lub raczej nie ma wpływu na postrzępione krawędzie). –

18

Użyj setFilterBitmap (true).

paint_object.setFilterBitmap(true); 

to działa na mnie zbyt .. mam go od tej kwestii

Drawing rotated bitmap with anti alias

zestaw zarówno Wygładzanie flagi i FilterBitmap flaga true, oni razem stanowić będzie bitmapy krawędzie gładkie, przetestowałem je na Samsung Galaxy Ace, Android 2.2 ...

Mój kod testowy to

Paint p = new Paint(); 
p.setAntiAlias(true); 
p.setFilterBitmap(true); 
canvas.drawBitmap(someBitmap, new Matrix(), p); 
+0

Przepraszam, ale nie. Filtrowanie bitmapy wygładza powierzchnię treści obrazu. Nie ma ant alias krawędzi. Zaktualizowałem moje pytanie, aby to odzwierciedlić. –

+0

'setFilterBitmap()' w połączeniu z 'setLayerType (View.LAYER_TYPE_SOFTWARE, null)' faktycznie działa bardzo dobrze dla mnie. Z samą warstwą oprogramowania miałem jeszcze trochę artefaktów. – Brian

3

Testowałem poprzednie sugestie i one działają dla mnie. Może problemy są w twojej mapie bitowej? Może w twoim urządzeniu? Oto kod, który tworzy wbudowaną mapę bitową. Sprawdź, czy ten przykład działa dla Ciebie.

public class BitmapRotateActivity extends Activity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(new MyView(this)); 
    } 
    class MyView extends View { 

    Bitmap bitmap; 
    public MyView(Context context) { 
     super(context); 

     bitmap = Bitmap.createBitmap(160, 160, Bitmap.Config.RGB_565); 
     Paint p = new Paint(); 
     p.setColor(Color.RED); 
     p.setStyle(Paint.Style.FILL); 
     Canvas c = new Canvas(bitmap); 
     c.drawRect(0, 0, bitmap.getWidth(), bitmap.getHeight(), p); 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
     Paint pbg = new Paint(); 
     pbg.setStyle(Paint.Style.FILL); 
     pbg.setColor(0xffe0e0ff); 
     canvas.drawRect(0, 0, getWidth(), getHeight(), pbg); 

     Paint p = new Paint(); 
     p.setAntiAlias(true); 
     p.setFilterBitmap(true); 

     canvas.save(); 
     canvas.rotate(3F, getWidth()/2, getHeight()/2); 
     canvas.drawBitmap(bitmap, 30, 30, p); 
     canvas.restore(); 
    } 
    } 
} 
+0

Mimo że odpowiedź nie była bezpośrednią odpowiedzią na moje pytanie, uwaga: "Może w twoim urządzeniu?" (i przypadkowe testy na moim Nexusie One) stawiają mnie na dobrej drodze, więc nagrodzę cię nagrodą. Dzięki za (wszystkie) Twój czas! –

2

Miałem ten sam problem i wypróbowałem wszystkie te poprawki. Co w końcu pracował globalnie wyłączyć akcelerację sprzętową w pliku AndroidManifest.xml:

<application 
     android:hardwareAccelerated="false" 
    ... 
> 

a następnie wyłączenie inSampleSize kiedy załadowany mój obraz mapy bitowej, dzięki czemu (jak mniemam) obraz będzie ładować w wystarczająco wysokiej jakości, aby uniknąć wszelkie zygzaki, a następnie, dla mojego rzeczywistego ImageView, korzystając z powyższej porady: ustawienie typu warstwy na View.LAYER_TYPE_SOFTWARE, z obiektem malowania z bitmapą filtra ustawioną na true (jak wyżej) i antyaliasing na.

+0

jak @ eric-kok stwierdził: wyłączenie go dla niestandardowego widoku jest wystarczające ... prawdopodobnie nie spowolnisz całej aplikacji – martyglaubitz