Как правильно хранить координаты после использования Graphics2D # drawString? - PullRequest
0 голосов
/ 28 октября 2019

Я пытаюсь создать динамическое изображение с напечатанным на нем алфавитом. Я использую 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, которое содержит всю последовательность алфавита, как показано ниже:

sequence of the alphabet generated with the above code

Я хочу, как и ранее, иметь возможность нацеливаться на каждый отдельный символ (в моем случае это специально для рендеринга текстур OpenGL), поэтому иметь точные координаты x, y, width и heightабсолютно необходимо. Имея это в виду, я пытаюсь проверить правильность моих координат. Чтобы сделать это, я пытаюсь разбить каждого персонажа из основного изображения на свои собственные подизображения, а затем записать их с помощью 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
}

Для хранения информации о каждом персонаже я решил использовать java.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 работает немного иначе, чем я ожидал.

На моем ПК приведен фрагмент кода всего этого кода. рендеринг:

messed up alphabet characters

Это, очевидно, не идеально, и я вообще не понимаю, что происходит. Что может происходить?

Редактировать: Для тех, кто не уверен в использовании var, я использую Java 13.

...