8

所以这就是我在 Android 中的晕影风格效果(图像是位图):

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 方法生成的。

左:来自 php/ImageMagick 的小插图。 右:使用上述方法的 Android 小插图

4

2 回答 2

4

如果您仔细查看左侧的图像,tf 使用 Alpha(透明度)与右侧图像的指数增加,这是非常线性的。

显然Shader.TitleMode.CLAMP是一个线性函数。你应该做的是使用RadialGradient(float x, float y, float radius, int[] colors, float[] position, Shader.TileMode tile)在图像上定义 10 个或更多点,颜色值呈指数下降(黑色到透明)。

或者,您可以参考 ICS 画廊的画廊 3d 源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

于 2012-05-22T06:59:18.230 回答
1

我知道这是一个古老的讨论,但它可能对某人有所帮助。您可以使用AccelerateInterpolator生成 Taranfx 提到的点,它会锁定真棒。

于 2013-08-11T11:09:53.237 回答