Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vignette in Android

So this is what I have for a vignette style effect in Android (image is a Bitmap):

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

This "works" but there are a couple of problems. First of all, this is not really a vignette, it's just a gradient so you can see bits of the black going nearly all the way to the center rather than feathering out closer to the edges.

The RadialGradient used also only allows for setting the radius of a circle rather than an ellipse. An ellipse would be able to more effectively match the dimensions of a non-square image than a circle.

The quality of the gradient is also not superb.

I'm trying to replicate the vignetteImage method from ImageMagick (I'm referring specifically to the php version). I have this code in PHP that produces the style of image that I want:

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

I've tried building ImageMagick with the NDK but have been unsuccessful in properly linking the various image libraries (I've only successfully built with gif support but no png, jpeg or tiff).

I've also attached an image comparing the two methods shown above. The image on the left was generated with ImageMagick through php and the image on the right was generated using the method shown above for Android.

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

like image 266
gregghz Avatar asked May 18 '12 19:05

gregghz


2 Answers

If you look carefully at the image on left, tf uses exponential increase in Alpha (transparency) vs. image on right which is very linear.

Clearly Shader.TitleMode.CLAMP is a linear function. What you should do instead is use RadialGradient(float x, float y, float radius, int[] colors, float[] positions, Shader.TileMode tile) to define 10 or more points on the image with exponentially decreasing color values (black to transparent).

Alternatively, you can refer gallery 3d source for ICS gallery 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

like image 154
Taranfx Avatar answered Oct 26 '22 22:10

Taranfx


I know this is an old discussion but it may help someone. You can use AccelerateInterpolator to generate the points that Taranfx had mentioned and it will lock awesome.

like image 21
Radu Nastasa Avatar answered Oct 26 '22 23:10

Radu Nastasa