I am trying to add some text to an image in Java with the following code:
public static void main(String[] args) throws IOException {
BufferedImage image = ImageIO.read(new File("img.png"));
Graphics g = image.getGraphics();
Rectangle rectangle = new Rectangle(image.getWidth(), image.getHeight());
g.setFont(g.getFont().deriveFont(30f));
drawCenteredString(g, "TexvzgdsfadvcfkgsdASKJDFHJGgkdgfsakagjASGHDJStTexvzgdsfadvcfkgsdASKJDFHJGgkdgfsakagjASGHDJSt", rectangle, g.getFont());
g.dispose();
ImageIO.write(image, "png", new File("out.png"));
}
public static void drawCenteredString(Graphics g, String text, Rectangle rect, Font font) {
FontMetrics metrics = g.getFontMetrics(font);
int x = rect.x + (rect.width - metrics.stringWidth(text)) / 2;
int y = rect.y + ((rect.height - metrics.getHeight()) / 2) + metrics.getAscent();
g.setFont(font);
g.drawString(text, x, y);
}
But I have a problem: I would need to be able to scale the font size or send words to a new line so that the whole string fits in a rectangular region at the center of the image with a maximum size of x,y. How can i do it?
To wrap the text, create TextLayout objects from a LineBreakMeasurer, and use TextLayout.draw instead of drawing with Graphics.drawString.
First, you need to create an AttributedCharacterIterator. You can do that by creating an AttributedString from your text:
AttributedString attrStr = new AttributedString(text);
AttributedCharacterIterator iter = attrStr.getIterator();
Now you can create a LineBreakMeasurer:
Graphics2D g2 = (Graphics2D) g;
LineBreakMeasurer measurer = new LineBreakMeasurer(iter,
g2.getFontRenderContext());
You then obtain the lines as TextLayouts, one at a time, from the LineBreakMeasurer:
List<TextLayout> lines = new ArrayList<>();
while (measurer.getPosition() < text.length()) {
lines.add(measurer.nextLayout(rect.width));
}
Once you have them, you can figure out the total height:
float textHeight = 0;
for (TextLayout line : lines) {
textHeight += line.getAscent() + line.getDescent() + line.getLeading();
}
Finally, you can draw the lines:
float y = (rect.height - textHeight) / 2;
for (TextLayout line : lines) {
Rectangle2D bounds = line.getBounds();
float x = (rect.width - (float) bounds.getWidth()) / 2;
line.draw(g2, x, y + line.getAscent());
y += line.getAscent() + line.getDescent() + line.getLeading();
}