在Java BufferedImage中绘制完全透明的“白色”

2024-02-04

这可能听起来有点奇怪,但请耐心听一下,那里is一个原因:

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

为了生成发光,我创建了一个比文本大的新 BufferedImage,然后将白色文本绘制到图像的画布上,并通过卷积运算 http://docs.oracle.com/javase/7/docs/api/java/awt/image/ConvolveOp.html,希望有这样的事情:

                                                                 enter image description here

起初,当光芒出现时,我有点惊讶darker比文本的灰色背景:

                                                                 enter image description here

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

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

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

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

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

UPDATE:

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

我在图像上绘制一个不透明的白色矩形,然后运行重新缩放操作 http://docs.oracle.com/javase/7/docs/api/java/awt/image/RescaleOp.html将所有 alpha 值设置为 0 的图像。这可行,但就性能而言,这可能是一个糟糕的方法。

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

PS:我也愿意接受完全不同的建议来创建这样的发光效果


最初的方法中辉光显得更暗的主要原因很可能是您没有使用带有预乘 alpha 分量的图像。 JavaDoc 的卷积运算 http://docs.oracle.com/javase/8/docs/api/java/awt/image/ConvolveOp.html包含有关在卷积过程中如何处理 alpha 分量的一些信息。

您可以使用“几乎完全透明的白色”来解决此问题。但另一种方法是,您可以简单地使用带有预乘 alpha 的图像,即具有以下类型的图像TYPE_INT_ARGB_PRE.

这里有一个MCVE https://stackoverflow.com/help/mcve它绘制了一个带有一些文本的面板,以及文本周围的一些脉冲发光(删除计时器并设置固定半径以删除脉冲 - 我无法抗拒在这里玩一点......)。

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);
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在Java BufferedImage中绘制完全透明的“白色” 的相关文章

  • Java 7 中的 Beans Binding 将被什么取代?

    我在某处读到 我忘记了链接 Beans Binding 将不会成为 Java 7 的一部分 有人知道什么会取代它吗 另外 当前版本的 Java 中是否有 Bean 绑定的替代方案 我建议JGoodies 绑定 https binding d
  • 在循环中使用 if 语句? - 加工

    假设我必须在 for 循环中使用 if 语句 并且 for 循环在特定条件下触发 而 if 语句仅在 for 循环达到特定阶段时触发 例如 条件是一个计数器 当发生特定事件 例如球从屏幕上掉下来 时 该计数器会进行计数 每次球穿过屏幕时 都
  • 使用 TLS 证书 JDBC 连接到 Oracle 数据库

    我正在尝试用 Java 编写一个连接类来使用 JDBC 驱动程序连接到 Oracle 数据库 但我想保护用于连接到 Oracle 数据库的参数 例如 jdbcurl 用户名 密码 我必须使用 TLS 证书概念来连接到 Java 中的 Ora
  • GAE 上奇怪的 500 错误

    我今天开始在我的应用程序上收到此错误 根本不记得更改任何内容 每当我在本地尝试时它都工作正常 但部署后我会收到此错误 EXCEPTION java lang ClassNotFoundException se myApp server My
  • “错误:无法找到或加载主类 org.apache.hadoop.util.RunJar”是什么意思?

    我正在尝试运行一个示例 因为它指出 Hadoop 实践 一书 http www manning com lam 第 15 页 这是需要运行的命令 bin hadoop jar hadoop examples jar 但我收到这个错误 Err
  • 在 Java 中对多语言环境字符串进行排序

    我正在尝试按字符串字段 国家 地区 对对象列表进行排序 每个国家 地区都使用其母语 阿根廷 澳大利亚 奥地利 例如 我想要做的是让 出现在 A 国家之后 因为字母 对应于拉丁语 B 我正在尝试使用默认的 Collat er 但非拉丁名称仍然
  • 如何在 JAVA servlet 中处理压缩 (gzip) HTTP 请求(不是响应) - 简单示例?

    我为这个问题苦苦挣扎了很长一段时间 在找到一个简单的解决方案后 想问一个问题和答案 这个问题在堆栈溢出时以不同的方式被多次提出 并且accepted solutions是partially correct and complex或谈论res
  • Java 8 流排序字符串列表[重复]

    这个问题在这里已经有答案了 我正在流上调用排序方法 java 文档说 Sorted 方法返回一个由该流的元素组成的流 并根据自然顺序排序 但是当我运行下面的代码时 List
  • Java 相当于 C# 的 async/await?

    我是一名普通的 C 开发人员 但偶尔也会使用 Java 开发应用程序 我想知道 Java 中是否有相当于 C async await 的东西 简单来说 java 相当于 async Task
  • Lcom/google/firebase/FirebaseApp 类中没有虚拟方法 zzbqo()Z;或其超类(“com.google.firebase.FirebaseApp”的声明

    在我的 Android 应用程序中 编译应用程序时出现错误 我正在最新的 android studio 中工作 并使用 Firebase UI Auth 和 Firebase 数据库 所有版本在应用程序级等级文件中都相同 那么为什么我收到此
  • 在 Java/Android 中查找 UTF-8 字符串中的字符数

    我试图找出字符串以 UTF 8 存储时的长度 我尝试了以下方法 String str Charset UTF8 CHARSET Charset forName UTF 8 byte abc str getBytes UTF8 CHARSET
  • 如何在使用 Web 服务时获取会话对象?

    如何在使用 Web 服务时获取会话对象 服务在两个程序之间调用 如何在使用 Web 服务时获取用户会话对象 不可能使用请求对象获取会话 因为当我们谈论服务时不会有请求或响应 如果您正在与JAX WS https jax ws dev jav
  • Java - 在特定日期执行方法[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我需要在每年的特定日期执行一个方法 我该如何在java中执行此操作 Thanks Chris 按优先顺序排列 The Quartz htt
  • 使用 Arrays.copyOf 复制不同类型的数组时出现问题

    我正在尝试创建一个方法 该方法几乎将任何内容作为参数 并返回带有某些分隔符的值的串联字符串表示形式 public static String getConcatenated char delim Object names String st
  • 在java中的super调用之前创建一个对象

    考虑到简单的java代码是行不通的 public class Bar extends AbstractBar private final Foo foo new Foo bar public Bar super foo 我需要在之前创建一个
  • 注意通知持续时间

    是否可以将抬头通知的持续时间设置为无限 现在它只显示 5 秒 已经尝试过不同的事情 例如更改类别 但持续时间始终为 5 秒 这是我的代码 Notification notification notificationBuilder setCa
  • JFrame 类型的方法 ... 未定义

    我正在尝试制作一个带有两个菜单列表的 gui 每个菜单列表有 3 个项目 我的问题是 当我单击某个项目时 出现错误 JFrame 类型的方法 displayList int AirplaneList 未定义 AirplaneControll
  • javaFX,抛出 NullPointerException,位置是必需的

    我看过其他答案 但没有任何帮助我 抱歉 GUI新手只知道swing的基础知识 这是主课 package application import javafx application Application import javafx fxml
  • 设置滚动条粗细

    有没有办法调整滚动条的粗细JScrollPane 默认值有点笨拙 一个快速但又肮脏的解决方案是将宽度 高度明确设置为例如10 像素通过 jScrollPane getVerticalScrollBar setPreferredSize ne
  • Struts2 中有多种结果类型?

    我有一个使用 Tiles 的 Struts2 应用程序 如何在操作映射中获取多种结果类型 因为我需要将de输出设置为JSON数据 并且同时Tiles 我努力了

随机推荐

  • jQuery UI 可排序动画

    我有一个类似网格的列表 并且按照计划在其中运行可排序功能 我想为每个项目设置动画 除了被操纵以在列表中平滑滑动的项目之外 我在这里设置了一个示例 http jsfiddle net wpmte http jsfiddle net wpmte
  • Vue.js 强制重新渲染包含 v-once 指令的组件

    Vue 2 0 我有一个包含 div 的组件 使用v once防止重新渲染的指令 当 URL 参数更改时 即单击 vue router 链接 更改组件中使用的 url 和参数 该组件会更新它显示的数据 该组件成功地使用新数据重新渲染所有内容
  • Azure MobileApp 自定义身份验证、刷新令牌

    我需要我的应用程序支持针对我们的私人数据库的自定义身份验证 并遵循此处 Adrian Hall 书中的建议https adrianhall github io develop mobile apps with csharp and azur
  • 在Java中,如果子类用实例子变量隐藏静态父变量,继承的方法将使用哪个变量?

    正如中所讨论的 这可能是一件坏事Java中的父类和子类可以有相同的实例变量吗 https stackoverflow com questions 3501060 can parent and child class in java have
  • JPA:无法使 OrderBy 工作

    我正在尝试在保留并检索后打印有序列表 我的实体 Entity public class News Id GeneratedValue private Long id private String content OneToMany casc
  • '没有找到应用程序。要么在视图函数中工作,要么推送应用程序上下文。 [复制]

    这个问题在这里已经有答案了 我正在尝试将 Flask SQLAlchemy 模型分成单独的文件 当我尝试跑步时db create all I get No application found Either work inside a vie
  • 有选择地将不记名令牌添加到 Retrofit 中的标头中

    我想知道是否有任何选项可以根据 Retrofit 中的标志或注释启用 禁用标头拦截器 由于我的 API 中很少有不需要令牌的路径 因此我需要跳过向这些 API 调用添加令牌的过程 目前我有一个简单的拦截器 它将向我的应用程序发出的所有请求添
  • 如何使用 babel/register 忽略非 js 文件

    当我的 Node 应用程序包含来自我的应用程序的路由时 我想忽略非 js 文件 例如 import scss App scss i e via Router js gt Routes js gt App js 目前 Node 显然会抛出解析
  • React 测试库 fireEvent.click 不起作用

    我基本上只是想改变一个计数器并显示该值已经改变 我正在这样做getByTestId那么这可能是问题所在 这是我的组件 import React useState from react import logo from logo svg im
  • Python 3.7 psycopg2 - Xcode 错误“错误:命令‘gcc’失败,退出状态 1”

    对于我目前正在处理的 Python Kivy 项目 使用 PyCharm 我设置了一个 postgreSQL 数据库 当我尝试使用终端安装 psycopg2 适配器时 pip install psycopg2我收到错误 错误 命令 gcc
  • 删除的 DataTable 行在排序后再次添加

    我正在使用数据表 https datatables net用于显示 HTML 表格的 jQuery 插件 我做了一个AJAX发送删除的行删除函数POST后台请求并显示返回的结果HTML消息在 infodiv 并删除相关的HTML行从DOM使
  • IDEA中有@NonNullByDefault注解吗?

    Eclipse 有 NonNullByDefault注释 它将所有值视为 NonNull除非你明确地将它们注释为 Nullable IntelliJ IDEA 中是否有等效的选项 或者您必须始终使用 Nonnull Idea 版本 14 将
  • 使用express/multer时更改文件名

    我在上传 pdf 时遇到问题 我正在使用ng file upload 到达express js的文件json是 fieldname file originalname db pdf encoding 7bit mimetype applic
  • JQuery 模式在提交前询问

    我有一个表单 用户可以在其中输入他的姓名 必填 出生日期 不需要 并且在提交表单之前 有一个确认信息 表明他 她是否确定提交没有出生日期的表单 我正在使用一个模式 它将提交上面的表格 我尝试运行下面的代码 但我看不出为什么不起作用的问题 当
  • 帮助构建修补的 Android 框架

    我是 Android 平台开发的新手 我刚刚成功构建氰化物7 http www cyanogenmod com 应用补丁后的源 这会向系统添加额外的 jar 适合 system framework 目录 刷新设备并检查新的自定义 jar 是
  • MySQL - 获取组的 sum() 分组 max()

    我有如下表结构 每行都是一场游戏 每个人每个月可以玩很多次或不玩 id person score date 1 32 444 2011 05 2 65 528 2011 05 3 77 455 2011 05 4 32 266 2011 0
  • MySQL:主机列中的 % 代表什么以及如何更改用户密码

    嗯 这就是我能看到的 select host user from mysql user host user me 127 0 0 1 root 1 root localhost localhost debian sys maint loca
  • JDBC 字符编码

    我有一个在 GlassFish 3 上运行的 Java Web 应用程序和在 MySQL 上运行的 JPA EclipseLink 我面临的问题是 如果我使用以下命令将实体保存到数据库中update 方法 String领域失去完整性 显示而
  • 在编译时计算小整数的阶乘

    我刚刚实现 再次 一个递归模板 用于在编译时计算整数的阶乘 谁会想到有一天我实际上会需要它 不过 我没有自己动手 而是去了Boost http www boost org 寻找答案 然而 特殊数学中的阶乘函数明确禁止将其与整数类型一起使用
  • 在Java BufferedImage中绘制完全透明的“白色”

    这可能听起来有点奇怪 但请耐心听一下 那里is一个原因 我正在尝试在灰色背景上的文本周围生成白色发光 为了生成发光 我创建了一个比文本大的新 BufferedImage 然后将白色文本绘制到图像的画布上 并通过卷积运算 http docs