这就是我在Android中的vignette风格效果(图像是一个位图):
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);
}这是“可行的”,但也有一些问题。首先,这不是真正的渐变,它只是一个渐变,所以你可以看到一些黑色几乎一直到中心,而不是羽化到更靠近边缘的地方。
使用的RadialGradient还只允许设置圆的半径,而不允许设置椭圆的半径。椭圆将能够比圆形更有效地匹配非正方形图像的尺寸。
渐变的质量也不是很好。
我正在尝试从ImageMagick复制vignetteImage方法(我特别指的是php版本)。我用PHP编写了这段代码,它可以生成我想要的图像样式:
$im = new IMagick('city.png');
$im->vignetteImage($width/1.5, 350, 20, 20);我尝试过使用NDK构建ImageMagick,但未能正确链接各种图像库(我只成功地构建了支持gif的图像库,但没有png、jpeg或tiff)。
我还附上了一张比较上面显示的两种方法的图像。左边的图片是用ImageMagick通过php生成的,右边的图片是使用上面的Android方法生成的。

发布于 2012-05-22 14:59:18
如果你仔细观察左边的图像,tf使用指数增长的Alpha (透明度)与右边的图像,这是非常线性的。
显然,Shader.TitleMode.CLAMP是一个线性函数。相反,您应该使用RadialGradient(float x, float y, float radius, int[] colors, float[] positions, Shader.TileMode tile)在图像上定义10个或更多的点,这些点的颜色值呈指数递减(从黑色到透明)。
或者,您也可以参考图库3d源来获取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
发布于 2013-08-11 19:09:53
我知道这是一个古老的讨论,但它可能会对某些人有所帮助。您可以使用AccelerateInterpolator生成Taranfx提到的点,它将锁定非常棒。
https://stackoverflow.com/questions/10658828
复制相似问题