gpt4 book ai didi

java - 在 Java BufferedImage 中绘制完全透明的 "white"

转载 作者:行者123 更新时间:2023-11-30 06:16:53 26 4
gpt4 key购买 nike

这可能听起来有点奇怪,但请耐心等待,是有原因的:

我正在尝试在灰色背景上的文本周围生成白光。

为了产生光晕,我创建了一个比文本大的新 BufferedImage,然后我将白色文本绘制到图像的 Canvas 上,并通过 ConvolveOp 在图像上运行高斯模糊。 ,希望是这样的:

enter image description here

起初我有点惊讶,因为发光比文本的灰色背景:

enter image description here

但经过一番思考,我明白了问题所在:

卷积在每个颜色 channel (R、G、B 和 A)上独立运行以计算模糊图像。图片的透明背景色值为0x00000000,即全透明的黑色!因此,当卷积过滤器运行在图像上时,它不仅混合了 alpha 值,而且还将黑色混合到白色像素的 RGB 值中。这就是发光变暗的原因。

要解决这个问题,我需要将图像初始化为 0x00FFFFFF,即完全透明的 white,但是如果我只是设置该颜色并用它填充一个矩形,它就不会像 Java 那样执行任何操作说“好吧,你正在绘制一个完全透明的矩形!这不会改变图像......让我为你优化它......完成......不客气。”。

如果我改为将颜色设置为 0x01FFFFFF,即几乎完全透明的白色,它会绘制矩形并且发光看起来很漂亮,除了我最终在它周围有一个非常微弱的白色框...

有没有办法可以将图像到处初始化为 0x00FFFFFF?

更新:

我找到了一种方法,但它可能不是您能得到的最佳方法:

我在图像上绘制了一个不透明的白色矩形,然后运行 ​​RescaleOp在将所有 alpha 值设置为 0 的图像上。这可行,但就性能而言,这可能是一种糟糕的方法。

我能以某种方式做得更好吗?

PS:对于创建这种发光效果,我也愿意接受完全不同的建议

最佳答案

在您的初始方法中,辉光显得更暗的主要原因很可能是您没有使用带有预乘 alpha 分量的图像。 ConvolveOp 的 JavaDoc包含一些关于在卷积过程中如何处理 alpha 分量的信息。

您可以使用“几乎完全透明的白色”来解决这个问题。但或者,您可以简单地使用具有预乘 alpha 的图像,即类型为 TYPE_INT_ARGB_PRE 的图像。

这是一个MCVE它绘制了一个带有一些文本的面板,文本周围有一些脉冲发光(删除计时器并设置固定半径以删除脉冲 - 我忍不住在这里玩了一会儿......)。

Glow

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.awt.image.ConvolveOp;
import java.awt.image.Kernel;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class TextGlowTest
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
createAndShowGUI();
}
});
}

private static void createAndShowGUI()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(new TextGlowPanel());
f.setSize(300,200);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}

class TextGlowPanel extends JPanel
{
private BufferedImage image;
private int radius = 1;

TextGlowPanel()
{
Timer t = new Timer(50, new ActionListener()
{
long startMillis = -1;

@Override
public void actionPerformed(ActionEvent e)
{
if (startMillis == -1)
{
startMillis = System.currentTimeMillis();
}
long d = System.currentTimeMillis() - startMillis;
double s = d / 1000.0;
radius = (int)(1 + 15 * (Math.sin(s * 3) * 0.5 + 0.5));
repaint();
}
});
t.start();
}

@Override
protected void paintComponent(Graphics gr)
{
super.paintComponent(gr);
gr.setColor(Color.GRAY);

int w = getWidth();
int h = getHeight();
gr.fillRect(0, 0, w, h);

if (image == null || image.getWidth() != w || image.getHeight() != h)
{
// Must be prmultiplied!
image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE);
}

Graphics2D g = image.createGraphics();
Font font = g.getFont().deriveFont(70.0f).deriveFont(Font.BOLD);
g.setFont(font);

g.setComposite(AlphaComposite.Src);
g.setColor(new Color(255,255,255,0));
g.fillRect(0,0,w,h);

g.setComposite(AlphaComposite.SrcOver);
g.setColor(new Color(255,255,255,0));
g.fillRect(0,0,w,h);

g.setColor(Color.WHITE);
g.drawString("Glow!", 50, 100);

image = getGaussianBlurFilter(radius, true).filter(image, null);
image = getGaussianBlurFilter(radius, false).filter(image, null);

g.dispose();

g = image.createGraphics();
g.setFont(font);
g.setColor(Color.BLUE);
g.drawString("Glow!", 50, 100);
g.dispose();

gr.drawImage(image, 0, 0, null);
}


// From
// http://www.java2s.com/Code/Java/Advanced-Graphics/GaussianBlurDemo.htm
public static ConvolveOp getGaussianBlurFilter(
int radius, boolean horizontal)
{
if (radius < 1)
{
throw new IllegalArgumentException("Radius must be >= 1");
}

int size = radius * 2 + 1;
float[] data = new float[size];

float sigma = radius / 3.0f;
float twoSigmaSquare = 2.0f * sigma * sigma;
float sigmaRoot = (float) Math.sqrt(twoSigmaSquare * Math.PI);
float total = 0.0f;

for (int i = -radius; i <= radius; i++)
{
float distance = i * i;
int index = i + radius;
data[index] =
(float) Math.exp(-distance / twoSigmaSquare) / sigmaRoot;
total += data[index];
}

for (int i = 0; i < data.length; i++)
{
data[i] /= total;
}

Kernel kernel = null;
if (horizontal)
{
kernel = new Kernel(size, 1, data);
}
else
{
kernel = new Kernel(1, size, data);
}
return new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
}
}

关于java - 在 Java BufferedImage 中绘制完全透明的 "white",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26569638/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com