将文本内容转换为图像更新。。。

2022-09-01 08:05:01

是否有任何Java库允许将文本内容转换为图像文件?我只知道ImageMagick(在本例中为JMagick),但我不想安装任何外部二进制文件(我的应用程序将作为.war文件部署在Tomcat服务器中,因此我不希望任何其他依赖项超过Java)。

例如,从字符串“Hello”中,我想生成这个简单的图像:

Basic image from string "hello"


答案 1

图形 2D API 应该能够实现您所需的目标。它还具有一些复杂的文本处理功能。

enter image description here

import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;

public class TextToGraphics {

    public static void main(String[] args) {
        String text = "Hello";

        /*
           Because font metrics is based on a graphics context, we need to create
           a small, temporary image so we can ascertain the width and height
           of the final image
         */
        BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = img.createGraphics();
        Font font = new Font("Arial", Font.PLAIN, 48);
        g2d.setFont(font);
        FontMetrics fm = g2d.getFontMetrics();
        int width = fm.stringWidth(text);
        int height = fm.getHeight();
        g2d.dispose();

        img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        g2d = img.createGraphics();
        g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
        g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
        g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
        g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
        g2d.setFont(font);
        fm = g2d.getFontMetrics();
        g2d.setColor(Color.BLACK);
        g2d.drawString(text, 0, fm.getAscent());
        g2d.dispose();
        try {
            ImageIO.write(img, "png", new File("Text.png"));
        } catch (IOException ex) {
            ex.printStackTrace();
        }

    }

}

另请查看写作/保存和图像

警告 我用它来生成90k PNG图像,只是为了发现它们可以在IE中查看,但在Chrome版本70.0.3538.77中却不能查看

上面的代码对我来说工作得很好(我把文本颜色改成了,这样我就可以在chrome中看到它)WHITE

Running in Chrome

我在Mac OS Mojave 10.14上使用Chrome 70.0.3538.77,使用Java 10.0.2。生成的图像为4778x2411像素...

更新。。。

在IE上,它是白底黑字,但在Chrome上是黑底黑字。然而,我将背景设置为白色。

所以你告诉我的是,透明的PNG在不同的浏览器上以不同的方式显示,因为浏览器使用不同的默认背景......你为什么对此感到惊讶?

最初的解决方案,故意使用了基于透明的图像。这在创建图像时使用 中显而易见,该图像应用了基于 Alpha () 的颜色模型。BufferedImage.TYPE_INT_ARGBARGB

这是出乎意料的,因为有g2d.setBackground(Color.white)。

不,实际上,这完全是意料之中的,只要你了解实际的作用以及应该如何使用它setBackground

来自 JavaDocs

设置 Graphics2D 上下文的背景色。背景色用于清除区域。为组件构造 Graphics2D 时,背景色继承自组件。在 Graphics2D 上下文中设置背景色仅影响后续的 clearRect 调用,而不影响组件的背景色。若要更改组件的背景,请使用组件的适当方法。

从事物的“声音”中,您需要一个非透明的图像,具有填充的背景色。所以,再一次,它转到了JavaDocs,一点点阅读就会把你带到,这会删除Alpha通道,但你仍然需要填充图像的背景。BufferedImage.TYPE_INT_RGB

为此,我会使用 和 ,只是因为它有效。Graphics2D#setColorGraphics2D#fillRect

因此,您最终会得到上述内容的修改版本,其外观可能类似于...

img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
g2d = img.createGraphics();
//...
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, img.getWidth(), img.getHeight());
g2d.setColor(Color.BLACK);
g2d.drawString(text, 0, fm.getAscent());
g2d.dispose();
try {
    ImageIO.write(img, "png", new File("Text.png"));
} catch (IOException ex) {
    ex.printStackTrace();
}

如果我更改为“jpg”,那么我在IE和Chrome上都会在黑色背景上获得橙色/粉红色文本

好吧,这与 中一个众所周知的,可悲的是,常见问题/错误有关,该问题/错误试图将透明颜色模型的alpha通道应用于不支持alpha通道的JPG。ImageIO

有关更多详细信息,请参阅使用 ImageIO.write jpg 文件:粉红色背景时出现问题。

但基本解决方案是使用支持 Alpha 通道的 PNG,或者使用非透明图像。

所以,所有这一切的长话和短处都是。问题不在于原始答案,也不在于 、、、AWT 库、Chrome 或 IE,而在于您对这些 API(和示例)的工作原理缺乏了解。ImageIOBufferedImageGraphics


答案 2

在没有任何外部库的情况下,请执行以下操作:

  1. 以像素为单位测量文本大小(请参见测量文本)
  2. 创建一个 java.awt.image.BufferedImage,大小适合文本
  3. 使用 createGraphics() 方法获取 BufferedImage 的图形对象
  4. 绘制文本
  5. 使用 javax ImageIO 类保存映像

编辑 - 修复了链接


推荐