Java中将文本添加到图像
1. 概述
有时我们需要在一个图像 或一组图像中添加一些文本。使用图像编辑工具手动执行此操作很容易。但是,当我们想以相同的方式将相同的文本添加到大量图片时,以编程方式执行此操作将非常有用。
在这个快速教程中,我们将学习如何使用 Java向图像添加一些文本。
2. 向图像添加文本
要读取图像并添加一些文本,我们可以使用不同的类。在接下来的部分中,我们将看到几个选项。
2.1. ImagePlus和ImageProcessor
首先,让我们看看如何使用ImageJ 库 中提供的**ImagePlus 和ImageProcessor **类。要使用这个库,我们需要在我们的项目中包含这个依赖项:
<dependency>
<groupId>net.imagej</groupId>
<artifactId>ij</artifactId>
<version>1.51h</version>
</dependency>
要读取图像,我们将使用openImage静态方法。此方法的结果将使用ImagePlus对象存储在内存中:
ImagePlus image = IJ.openImage(path);
一旦我们将图像加载到内存中,让我们使用类ImageProcessor添加一些文本:
Font font = new Font("Arial", Font.BOLD, 18);
ImageProcessor ip = image.getProcessor();
ip.setColor(Color.GREEN);
ip.setFont(font);
ip.drawString(text, 0, 20);
使用这段代码,我们正在做的是在图像的左上角添加指定的绿色文本。请注意,我们使用drawString方法的第二个和第三个参数设置位置,它们分别表示从左侧和顶部的像素数。
2.2. BufferedImage和Graphics
接下来,我们将看看**如何使用BufferedImage 和Graphics **类实现相同的结果。Java 的标准构建包括这些类,因此不需要额外的库。
与我们使用ImageJ的openImage的方式相同,我们将使用ImageIO中可用的read方法:
BufferedImage image = ImageIO.read(new File(path));
一旦我们将图像加载到内存中,让我们使用类Graphics添加一些文本:
Font font = new Font("Arial", Font.BOLD, 18);
Graphics g = image.getGraphics();
g.setFont(font);
g.setColor(Color.GREEN);
g.drawString(text, 0, 20);
正如我们所看到的,这两种选择在使用方式上都非常相似。在这种情况下,方法drawString的第二个和第三个参数的指定方式与我们为ImageProcessor方法所做的相同。
2.3. 基于AttributedCharacterIterator绘制
Graphics中可用的方法drawString允许我们**使用AttributedCharacterIterator **打印文本。这意味着我们可以使用带有一些关联属性的文本,而不是使用普通的String。让我们看一个例子:
Font font = new Font("Arial", Font.BOLD, 18);
AttributedString attributedText = new AttributedString(text);
attributedText.addAttribute(TextAttribute.FONT, font);
attributedText.addAttribute(TextAttribute.FOREGROUND, Color.GREEN);
Graphics g = image.getGraphics();
g.drawString(attributedText.getIterator(), 0, 20);
这种打印文本的方式让我们有机会直接将格式与String关联起来,这比在我们想要更改格式时更改Graphics对象属性更干净。
3. 文本对齐
现在我们已经学会了如何在图像的左上角添加一个简单的文本,现在让我们看看如何在某些位置添加这个文本。
3.1. 居中文本
我们要处理的第一种对齐方式是居中文本。要动态设置我们要写入文本的正确位置,我们需要弄清楚一些信息:
- 图片尺寸
- 字体大小
这些信息可以很容易地获得。在图像大小的情况下,可以通过BufferedImage对象的getWidth和getHeight方法访问此数据。另一方面,要获取与字体大小相关的数据,我们需要使用FontMetrics对象。
让我们看一个例子,我们计算文本的正确位置并绘制它:
Graphics g = image.getGraphics();
FontMetrics metrics = g.getFontMetrics(font);
int positionX = (image.getWidth() - metrics.stringWidth(text)) / 2;
int positionY = (image.getHeight() - metrics.getHeight()) / 2 + metrics.getAscent();
g.drawString(attributedText.getIterator(), positionX, positionY);
3.2. 右下角对齐的文本
我们将要看到的下一种对齐方式是右下角。在这种情况下,我们需要动态获取正确的位置:
int positionX = (image.getWidth() - metrics.stringWidth(text));
int positionY = (image.getHeight() - metrics.getHeight()) + metrics.getAscent();
3.3. 文本位于左上角
最后,让我们看看如何在左上角打印我们的文本:
int positionX = 0;
int positionY = metrics.getAscent();
其余的对齐可以从我们看到的三个中推断出来。
4. 根据图像调整文本大小
当我们在图像中绘制文本时,我们可能会发现这个文本超出了图像的大小。为了解决这个问题,我们必须根据图像大小调整我们正在使用的字体大小。 首先,我们需要使用基本字体获取文本的预期宽度和高度。为了实现这一点,我们将使用FontMetrics 、GlyphVector 和Shape 类。
FontMetrics ruler = graphics.getFontMetrics(baseFont);
GlyphVector vector = baseFont.createGlyphVector(ruler.getFontRenderContext(), text);
Shape outline = vector.getOutline(0, 0);
double expectedWidth = outline.getBounds().getWidth();
double expectedHeight = outline.getBounds().getHeight();
下一步是检查是否需要调整字体大小。为此,让我们比较文本的预期大小和图像的大小:
boolean textFits = image.getWidth() >= expectedWidth && image.getHeight() >= expectedHeight;
最后,如果我们的文本不适合图像,我们必须减小字体大小。我们将为此使用方法derivedFont:
double widthBasedFontSize = (baseFont.getSize2D()*image.getWidth())/expectedWidth;
double heightBasedFontSize = (baseFont.getSize2D()*image.getHeight())/expectedHeight;
double newFontSize = widthBasedFontSize < heightBasedFontSize ? widthBasedFontSize : heightBasedFontSize;
newFont = baseFont.deriveFont(baseFont.getStyle(), (float)newFontSize);
请注意,我们需要根据宽度和高度获取新的字体大小并应用它们中的最小值。