I assume that this is an example of an XY-problem. If your goal is to generate an image, with a certain text, automatically adjusted for some font and line breaks, then you could do this on your own. You could use FontMetrics
and its methods to compute the proper size of the image, and the proper locations that are then drawn with drawString
calls.
But this is complicated. And it's far, far, far more complicated than it looks at the first glance. I'm not even talking about النص العربي (arabic text), but even about the seemingly most trivial elements of fonts.
The most simple solution therefore is probably to rely on the hundreds of thousands of lines of time-tested code that have already been written by experts in this field, in order to solve this problem.
Which means:
Just drop the text into a JTextArea
, and then create an image from that.
The following is an MCVE that shows how this could be achieved.

The core is the createTextImage
method, which allows you to create an image from the text, with a certain font and colors. Optionally, you may specify the width of the image, and leave the daunting task of doing the line breaks to the JTextArea
.
You may notice the "HTML" checkbox at the top. When it is enabled, the input is passed to a createHtmlImage
method, so that you can even enter something like
<html>
This is <u>underlined</u> <br>
or in <i>italics</i>
</html>
to obtain an image of the rendered HTML output.
The full code is here:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.image.BufferedImage;
import javax.swing.BorderFactory;
import javax.swing.JCheckBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
public class GenerateTextImage {
public static void main(String[] args) {
String text = "This is a text" + "\n"
+ "with one line that is muuuuuuuuuuuuuuuuch longer than the others" + "\n"
+ "and some empty lines" + "\n"
+ "\n"
+ "\n"
+ "as a test.";
SwingUtilities.invokeLater(() -> createAndShowGui(text));
}
private static void createAndShowGui(String initialText) {
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().setLayout(new BorderLayout());
JPanel controlPanel = new JPanel();
JCheckBox htmlCheckBox = new JCheckBox("HTML", false);
controlPanel.add(htmlCheckBox);
f.getContentPane().add(controlPanel, BorderLayout.NORTH);
JPanel mainPanel = new JPanel(new GridLayout(1, 2));
f.getContentPane().add(mainPanel, BorderLayout.CENTER);
JTextArea inputTextArea = new JTextArea();
JScrollPane sp0 = new JScrollPane(inputTextArea);
sp0.setBorder(BorderFactory.createTitledBorder("Input:"));
mainPanel.add(sp0);
ImagePanel imagePanel = new ImagePanel();
JScrollPane sp1 = new JScrollPane(imagePanel);
sp1.setBorder(BorderFactory.createTitledBorder("Image:"));
mainPanel.add(sp1);
Runnable updateImage = () -> {
if (!htmlCheckBox.isSelected()) {
String text = inputTextArea.getText();
BufferedImage image = createTextImage(text);
imagePanel.setImage(image);
} else {
String text = inputTextArea.getText();
BufferedImage image = createHtmlImage(text);
imagePanel.setImage(image);
}
};
inputTextArea.getDocument().addDocumentListener(new DocumentListener() {
public void changedUpdate(DocumentEvent e) {
updateImage();
}
public void insertUpdate(DocumentEvent e) {
updateImage();
}
public void removeUpdate(DocumentEvent e) {
updateImage();
}
private void updateImage() {
updateImage.run();
}
});
htmlCheckBox.addChangeListener(e -> {
updateImage.run();
});
inputTextArea.setText(initialText);
f.setSize(1200, 600);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
private static BufferedImage createTextImage(String text) {
return createTextImage(text, -1, new Font("TimesRoman", Font.BOLD, 15), Color.BLACK, Color.WHITE);
}
/**
* Creates an image with the given text, using the given font and foreground- and background color.<br>
* <br>
* If the given width is not positive, then the width of the image will be computed
* to show the longest line that appears in the text. If the given width is positive,
* then the lines of the given text will be wrapped (at word boundaries) if possible,
* so that the whole text can be displayed.
*
* @param text The text
* @param width The image width
* @param font The font
* @param foreground The foreground color
* @param background The background color
* @return The image
*/
private static BufferedImage createTextImage(String text, int width, Font font, Color foreground, Color background) {
JTextArea textArea = new JTextArea(text);
textArea.setFont(font);
textArea.setForeground(foreground);
textArea.setBackground(background);
if (width > 0)
{
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
textArea.setSize(new Dimension(width, Short.MAX_VALUE));
}
Dimension size = textArea.getPreferredSize();
int w = Math.max(1, size.width);
if (width > 0)
{
w = width;
}
int h = Math.max(1, size.height);
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = image.createGraphics();
SwingUtilities.paintComponent(g, textArea, new JPanel(), 0, 0, w, h);
g.dispose();
return image;
}
private static BufferedImage createHtmlImage(String text) {
return createHtmlImage(text, new Font("TimesRoman", Font.BOLD, 15), Color.BLACK, Color.WHITE);
}
/**
* Creates an image with the given HTML string, using the given font and foreground- and background color.<br>
*
* @param html The HTML string
* @param font The font
* @param foreground The foreground color
* @param background The background color
* @return The image
*/
private static BufferedImage createHtmlImage(String html, Font font, Color foreground, Color background) {
JLabel label = new JLabel(html);
label.setOpaque(true);
label.setFont(font);
label.setForeground(foreground);
label.setBackground(background);
Dimension size = label.getPreferredSize();
int w = Math.max(1, size.width);
int h = Math.max(1, size.height);
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = image.createGraphics();
SwingUtilities.paintComponent(g, label, new JPanel(), 0, 0, w, h);
g.dispose();
return image;
}
static class ImagePanel extends JPanel {
private static final long serialVersionUID = 1L;
private BufferedImage image;
public void setImage(BufferedImage image) {
this.image = image;
repaint();
}
@Override
public Dimension getPreferredSize() {
if (image == null || super.isPreferredSizeSet()) {
return super.getPreferredSize();
}
return new Dimension(image.getWidth(), image.getHeight());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (image != null) {
g.drawImage(image, 0, 0, null);
}
}
}
}
Edit: A small addendum for one of the comments. It centers the text horizontally, using the snippet from https://stackoverflow.com/a/3213361/3182664 . Note that this is not tested thoroughly. At some point, questions, comments and edits boil down to "Write some code for me". I'm a freelancer. You can hire me.
private static BufferedImage createTextImage(String text, int width, Font font, Color foreground, Color background) {
JTextPane textPane = new JTextPane();
textPane.setText(text);
// See https://stackoverflow.com/a/3213361/3182664
StyledDocument doc = textPane.getStyledDocument();
SimpleAttributeSet center = new SimpleAttributeSet();
StyleConstants.setAlignment(center, StyleConstants.ALIGN_CENTER);
doc.setParagraphAttributes(0, doc.getLength(), center, false);
textPane.setFont(font);
textPane.setForeground(foreground);
textPane.setBackground(background);
if (width > 0)
{
//textPane.setLineWrap(true);
//textPane.setWrapStyleWord(true);
textPane.setSize(new Dimension(width, Short.MAX_VALUE));
}
Dimension size = textPane.getPreferredSize();
int w = Math.max(1, size.width);
if (width > 0)
{
w = width;
}
int h = Math.max(1, size.height);
BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = image.createGraphics();
SwingUtilities.paintComponent(g, textPane, new JPanel(), 0, 0, w, h);
g.dispose();
return image;
}