2012-05-18 15 views
8

Więc to, co mam na efekt stylu winieta na Androida (obraz jest mapa bitowa):Vignette w Androidzie

public void vignette() { 
    float radius = (float) (image.getWidth()/1.5); 
    RadialGradient gradient = new RadialGradient(image.getWidth()/2, image.getHeight()/2, radius, Color.TRANSPARENT, Color.BLACK, Shader.TileMode.CLAMP); 

    Canvas canvas = new Canvas(image); 
    canvas.drawARGB(1, 0, 0, 0); 

    final Paint paint = new Paint(); 
    paint.setAntiAlias(true); 
    paint.setColor(Color.BLACK); 
    paint.setShader(gradient); 

    final Rect rect = new Rect(0, 0, image.getWidth(), image.getHeight()); 
    final RectF rectf = new RectF(rect); 

    canvas.drawRect(rectf, paint); 

    paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); 
    canvas.drawBitmap(image, rect, rect, paint); 
} 

ten „dzieła”, ale istnieje kilka problemów. Po pierwsze, to nie jest winieta, to tylko gradient, dzięki czemu można zobaczyć fragmenty czerni przechodzące prawie całą drogę do centrum, zamiast wyrywać się bliżej krawędzi.

Zastosowany radialGradient pozwala również na ustawienie promienia okręgu zamiast elipsy. Elipsa byłaby w stanie skuteczniej dopasować wymiary obrazu innego niż kwadratowy.

Jakość gradientu również nie jest doskonała.

Próbuję zreplikować metodę winietowania z ImageMagick (mam na myśli konkretnie wersję php). Mam ten kod w PHP, który produkuje styl obrazu, który chcę:

$im = new IMagick('city.png'); 
$im->vignetteImage($width/1.5, 350, 20, 20); 

Próbowałem budowę ImageMagick z NDK ale bezskutecznie odpowiednio łącząc różne bibliotek graficznych (mam tylko udało się stworzyć z obsługą gif, ale bez png, jpeg lub tiff).

Dołączyłem także obraz porównujący dwie metody pokazane powyżej. Obraz po lewej został wygenerowany za pomocą ImageMagick przez php, a obraz po prawej został wygenerowany za pomocą metody pokazanej powyżej dla Androida.

left: vignette from php/ImageMagick. right: vignette from Android using method shown above

+1

Masz jakieś rozwiązanie ... Jeśli tak, to możesz mi je przekazać .....? ....... Dziękuję – Kalpesh

+0

Do tej pory odpowiedź geeknizera jest najlepsza, jaką mam. Jeszcze tego nie wypróbowałem ... do tego dziś rano. – gregghz

+0

Trochę za późno, ale czy masz jakieś rozwiązanie tego problemu? Czy możesz podać kod? Uratowałbyś moje życie, jeśli tak! @ greggory.hz – Sebastian

Odpowiedz

4

Jeśli spojrzymy uważnie na zdjęcie po lewej stronie, TF używa wykładniczy wzrost alfa (przezroczystości) vs. obraz na prawo, które jest bardzo liniowa.

Oczywiście Shader.TitleMode.CLAMP jest funkcją liniową. Zamiast tego należy użyć RadialGradient(float x, float y, float radius, int[] colors, float[] positions, Shader.TileMode tile), aby zdefiniować 10 lub więcej punktów na obrazie z wykładniczo malejącymi wartościami kolorów (od czarnego do przezroczystego).

Alternatywnie, można zwrócić się do galerii źródło 3d galerii ICS http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android-apps/4.0.1_r1/com/android/gallery3d/photoeditor/filters/VignetteFilter.java?av=h

+0

Wydaje się, że to jest najlepszy sposób aby uzyskać jazdę liniowości gradientu. Prawdopodobnie będę musiał zagrać z tablicą kolorów, aby uzyskać odpowiedni efekt. W jaki sposób układ pozycji wpływa na całość? Nie jestem pewien, czy całkowicie to rozumiem. Teraz gdybym mógł wymyślić jak zrobić elipsę ... – gregghz

1

wiem, jest to stara dyskusja, ale może komuś pomóc. Możesz użyć AccelerateInterpolator, aby wygenerować punkty, o których wspomniał Taranfx, a to się zablokuje.