首页 > 解决方案 > 使用 Graphics2D#drawString 后如何正确存储坐标?

问题描述

我正在尝试生成一个印有字母的动态图像。我正在利用java.awt.Graphics2D来完成这个。我像这样创建我的图像:

var alphabet = "abcdefghijklmnopqrstuvwxyz";
final var image = new BufferedImage(256, 256, BufferedImage.TYPE_INT_ARGB);
var graphics = image.createGraphics();
{
    graphics.setColor(Color.WHITE);
    graphics.setFont(new Font(Font.SANS_SERIF, Font.PLAIN, 48));
    var metrics = graphics.getFontMetrics();

    for (int i = 0, x = image.getMinX(), y = metrics.getAscent() + image.getMinY(); i < alphabet.length(); ++i) {
        var alpha = alphabet.charAt(i);
        {
            var width = metrics.charWidth(alpha);
            var height = metrics.getHeight();
            if (x + width > image.getWidth()) {
                y += height;
                x = 0;
            }

            graphics.drawString(String.valueOf(alpha), x, y);
            x += width;
        }
    }
}
graphics.dispose();
ImageIO.write(image, "PNG", new File(System.getProperty("java.io.tmpdir"), "image.png"));

这样做,我可以创建一个包含整个字母序列的 256x256 图像,如下所示:

使用上述代码生成的字母序列

如前所述,我希望能够针对每个单独的字符(在我的情况下,它专门用于 OpenGL 纹理渲染),因此具有准确的 x、y、宽度和高度坐标是绝对必须的。考虑到这一点,我正在尝试测试我的坐标是否正确。为了做到这一点,我试图将主图像中的每个字符拆分为它们自己的子图像,然后使用 ImageIO 将它们写出来。为了存储数据,我使用了一个名为 Glyph 的自定义类。

public class Glyph {
    private final int x, y, width, height;

    public Glyph(final int x, final int y, final int width, final int height) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
    }

    // getters
}

为了存储每个角色的信息,我决定使用 ajava.util.Map<Character, Glyph>来让我的生活更轻松一些。

var map = new HashMap<Character, Glyph>();
// previous code, up-to the Graphics2D#drawString part
map.put(alpha, new Glyph(x, y, width, height);

填充此列表后,我尝试获取一个BufferedImage#getSubimage,然后使用ImageIO#write它来直观地查看它是否有效。这就是问题所在。

map.forEach((c, g) -> {
    var sub = image.getSubimage(g.getX(), g.getY(), g.getWidth(), g.getHeight());
    ImageIO.write(sub, new File(System.getProperty("java.io.tmpdir")), c + ".png");
});

问题似乎存在于这里,或者我如何获得我的坐标,因为图像非常偏离。子图像甚至不包含接近我期望的字符的任何地方,这令人困惑。我不确定是不是因为我的坐标不正确,或者 getSubimage 的工作方式与我预期的有点不同。

在我的 PC 上,这是所有这些代码呈现的片段:

搞砸了字母字符

这显然不理想,我根本不明白发生了什么。可能会发生什么?

编辑:对于任何对 的用法感到困惑的人var,我使用的是 Java 13。

标签: javaawttexturesbufferedimagegraphics2d

解决方案


推荐阅读