如何增加高斯模糊的不透明度 [英] how to increase opacity in gaussian blur

查看:189
本文介绍了如何增加高斯模糊的不透明度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Java应用程序,我需要在图像上绘制文本。文本,字体和图像都是在运行时确定的。文本需要看起来不错,但在图像上方可读(足够对比)。

I have a Java application where I need to draw text on top of an image. The text, the font, and the image are all determined at run time. The text needs to look nice, yet be readable (sufficiently contrastive) on top of the image.

为了满足这些要求,我创建了一个投影。这是通过在空白/透明BufferedImage上绘制不透明黑色文本,然后应用高斯模糊滤镜来完成的。然后,我再次以不透明的白色在阴影顶部绘制文本。所以我有不透明的白色文字,周围有黑色模糊的阴影,很快就会变成完全透明。然后我可以在背景图像上绘制这个图像。

To meet these requirements, I create a drop shadow. This is done by drawing the text in opaque black, on a blank/transparent BufferedImage, then applying a Gaussian blur filter. I then draw the text again, in opaque white, on top of the drop shadow. So I have opaque white text, with a black blurred shadow around it that quickly fades to full transparency. I can then draw this image on top of the background image.

我想解决的问题是投影看起来太透明了。因此,对于明亮,繁忙的背景,它不会给白色文本足够的分离。

The problem I'm trying to solve is that the drop shadow seems too transparent. So against bright, busy backgrounds, it doesn't give the white text enough separation.

那么如何增加阴影的不透明度?我已经尝试增加高斯模糊的半径,这使阴影更宽,但不会使它更不透明。

So how to increase the opacity of the shadow? I've tried increasing the radius of the gaussian blur, and that makes the shadow wider, but doesn't make it more opaque.

我使用的代码基于这个DropShadowDemo 。我使用他的createDropShadow()和gaussianBlurFilter()。但是,不是在 paintComponent()期间单独绘制投影和文本,而是将它们预先绘制到BufferedImage上;然后我在 paintComponent()期间在背景上绘制这个单独的BufferedImage。也许那是我的问题?但我不明白这会如何降低阴影的不透明度。我在 paintComponent()期间没有使用 g2.setComposite()

The code I'm using is based on this DropShadowDemo by Romain Guy. I use his createDropShadow() and gaussianBlurFilter(). But instead of painting the drop shadow and the text separately during paintComponent(), I draw them both onto a BufferedImage in advance; and I draw this single BufferedImage on top of the background during paintComponent(). Maybe that's my problem? But I don't see how that would decrease the opacity of the shadow. I'm not using g2.setComposite() during paintComponent().

我看过使用某种 BufferedImageOp ,例如LookupOp。但是对于一个简单的调整似乎需要做很多工作(我想这会创建四个数组)。我不认为RescaleOp会起作用,因为我希望结果alpha与源alpha相同的范围(0到1)。如果我可以指定一个设置新alpha = sqrt(旧alpha)的BufferedImageOp,或类似的东西,那将是理想的。但我不知道一个简单的方法。

I've looked at adjusting the opacity of the drop shadow using some kind of BufferedImageOp, such as a LookupOp. But it seems like a lot of work for a simple adjustment (creating four arrays of numbers, I guess). I don't think a RescaleOp would work, since I want the result alpha to fall in the same range (0 to 1) as the source alpha. If I could specify a BufferedImageOp that sets new alpha = sqrt(old alpha), or something like that, that would be ideal. But I don't know an easy way to do that.

这里可以看到代码的详细信息:

Details of the code can be seen here:

  • ShadowedText.java (creates the text-with-drop-shadow image)
  • SetBeforeMe.java (implements paintComponent() that draws the image)

我会在这里包含相关的代码块,但似乎相关的代码量太大(代码墙)...也许只是提供源代码的链接文件。

I would include relevant code blocks here, but it seems like the relevant amount of code is too big (wall of code)... might as well just give links to the source files.

看起来像更改BufferedImage的alpha值?将是一种改变drop shad的不透明度的方法ow ...基本上重新计算每个像素的alpha值,一个接一个。 TBD:它是否可移植(例如64位机器),以及它是否足够快。如果我在每个像素上执行 a = sqrt(a) a = sin(a * pi * 0.5)(想到 a 在0到1的范围内,那会慢吗?我很高兴知道是否有一种更简单的方法可以利用可用的优化,例如内置的BufferedImageOps。也许答案是为LookupOp构建数组。有人知道一些示例代码吗?

It looks like Change the alpha value of a BufferedImage? would be a way to change the opacity of the drop shadow... basically recalculating the alpha value of each pixel, one by one. TBD: whether it's portable (to 64-bit machines, e.g.), and whether it's fast enough. If I do a = sqrt(a) or a = sin(a * pi * 0.5) on every pixel (thinking of a in the range 0 to 1), will that be slow? I would be happy to know if there's a simpler way that takes advantage of available optimizations, like the built-in BufferedImageOps presumably do. Maybe the answer is building arrays for LookupOp after all. Anybody know of some example code for that?

使用LookupOp解决;请参阅下面的代码。

Solved using a LookupOp; see code below.

推荐答案

以下是我最终要使BufferedImage更加不透明的代码。我决定继续使用LookupOp,而不是在每个像素上使用getRGB / setRGB进行潜在的不可移植和慢速循环。设置Lookup数组的工作并不是那么糟糕。

Below is the code I ended up with to make a BufferedImage more opaque. I decided to go ahead and use a LookupOp, rather than a potentially unportable and slow loop over getRGB / setRGB on each pixel. The work to set up Lookup arrays wasn't so bad.

/* Make alpha channel more opaque.
 * Modify the alpha (opacity) channel so that values are higher, but still
 * continuous and monotonically increasing.
 */
private static void adjustOpacity(BufferedImage shadowImage) {
    // Use a lookup table with four arrays;
    // the three for RGB are identity arrays (no change).
    byte identityArray[] = new byte[256];
    for (int i=0; i < 256; i++)
        identityArray[i] = (byte)i;

    byte alphaArray[] = new byte[256];
    // map the range (0..256] to (0..pi/2]
    double mapTo90Deg = Math.PI / 2.0 / 256.0;
    for (int i=0; i < 256; i++) {
        alphaArray[i] = (byte)(Math.sin(i * mapTo90Deg) * 256);
    }

    byte[][] tables = {
            identityArray,
            identityArray,
            identityArray,
            alphaArray
    };
    ByteLookupTable blut = new ByteLookupTable(0, tables);
    LookupOp op = new LookupOp(blut, null);

    // With LookupOp, it's ok for src and dest to be the same image.
    op.filter(shadowImage,  shadowImage);
}

它似乎有效(尽管我之前没有采取过 - 而且 - 截图后进行比较)。

It seems to work (though I haven't taken before-and-after screenshots for comparison).

这篇关于如何增加高斯模糊的不透明度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆