Java - Draw text in the center of an image
Asked Answered
C

4

6

I need to write text in the center of an image. The text to write is not always the same.

The code I'm using is here:

// Here I first draw the image
g.drawImage(img, 22, 15, 280, 225, null);
// I get the text 
String text = photoText.getText();
// Set the text color to black
g.setColor(Color.black);
// I draw the string 
g.drawString(text, 79.5F, 220.0F);

The problem is that the text isn't at the center of the image, what can I do?

I only need to draw the text at the horizontal center.

Careycarfare answered 6/9, 2011 at 17:6 Comment(0)
S
8

Using a JLabel is less work, but FontMetrics, shown here, will let you manage the geometry directly.

Shuntwound answered 6/9, 2011 at 17:24 Comment(0)
C
6

The easy way is to use a JLabel with an Icon and Text. Then set the horizontal/vertical text position to CENTER and the text is painted in the center of the image.

From your code it looks like you are trying to paint the text near the bottom of the image. In this case you can use the JLabel with an Icon as a container. Then you can set the layout to something like a BoxLayout and add another label with the text.

No custom painting is required for either approach.

import java.awt.*;
import javax.swing.*;
import javax.swing.text.*;

public class LabelImageText extends JPanel
{
    public LabelImageText()
    {
        JLabel label1 = new JLabel( new ColorIcon(Color.ORANGE, 100, 100) );
        label1.setText( "Easy Way" );
        label1.setHorizontalTextPosition(JLabel.CENTER);
        label1.setVerticalTextPosition(JLabel.CENTER);
        add( label1 );

        //

        JLabel label2 = new JLabel( new ColorIcon(Color.YELLOW, 200, 150) );
        label2.setLayout( new BoxLayout(label2, BoxLayout.Y_AXIS) );
        add( label2 );

        JLabel text = new JLabel( "More Control" );
        text.setAlignmentX(JLabel.CENTER_ALIGNMENT);
        label2.add( Box.createVerticalGlue() );
        label2.add( text );
        label2.add( Box.createVerticalStrut(10) );

        //

        JLabel label3 = new JLabel( new ColorIcon(Color.GREEN, 200, 150) );
        add( label3 );

        JLabel text3 = new JLabel();
        text3.setText("<html><center>Text<br>over<br>Image<center></html>");
        text3.setLocation(20, 20);
        text3.setSize(text3.getPreferredSize());
        label3.add( text3 );

        //

        JLabel label4 = new JLabel( new ColorIcon(Color.CYAN, 200, 150) );
        add( label4 );

        JTextPane textPane = new JTextPane();
        textPane.setText("Add some text that will wrap at your preferred width");
        textPane.setEditable( false );
        textPane.setOpaque(false);
        SimpleAttributeSet center = new SimpleAttributeSet();
        StyleConstants.setAlignment(center, StyleConstants.ALIGN_CENTER);
        StyledDocument doc = textPane.getStyledDocument();
        doc.setParagraphAttributes(0, doc.getLength(), center, false);
        textPane.setBounds(20, 20, 75, 100);
        label4.add( textPane );
    }

    public static class ColorIcon implements Icon
    {
        private Color color;
        private int width;
        private int height;

        public ColorIcon(Color color, int width, int height)
        {
            this.color = color;
            this.width = width;
            this.height = height;
        }

        public int getIconWidth()
        {
            return width;
        }

        public int getIconHeight()
        {
            return height;
        }

        public void paintIcon(Component c, Graphics g, int x, int y)
        {
            g.setColor(color);
            g.fillRect(x, y, width, height);
        }
    }

    private static void createAndShowUI()
    {
        JFrame frame = new JFrame("LabelImageText");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add( new LabelImageText() );
        frame.pack();
        frame.setLocationRelativeTo( null );
        frame.setVisible( true );
    }

    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                createAndShowUI();
            }
        });
    }
}

I mean I have to write a text in the center of the image and then save the image

You can use Screen Image to create an image of any component. This assumes you are displaying the image and text on a GUI.

Or, if you are talking about just reading in an image adding text to the image and then saving the image, then you will need to create a BufferedImage and draw the image on it and then draw the text on it. You will need to use the FontMetrics class as mentioned by Trashgod. My suggestion won't help.

Cotillion answered 6/9, 2011 at 21:54 Comment(3)
I will use the FontMetrics class, because I need to save the image but I'm also using a GUI, Can I use your suggestion so?Careycarfare
+1 for ScreenImage; see also this ImageIO example..Shuntwound
@GhzNcl, I don't understand your question. I gave you working code. Only you can decide if it does what you want. I also gave a link to ScreenImage which shows how to use it on visible or non-visible components.Cotillion
W
5

One possible solution: draw the image in a JPanel, being sure to set the panel's preferredsize as the size of the image, have the JPanel use a GridBagLayout, and place the text in a JLabel that is added to the JPanel, without GridBagConstraints. This is one way to center the JLabel in the JPanel.

Weakness answered 6/9, 2011 at 17:12 Comment(2)
I will try in this way. Thanks.Careycarfare
But with this way I can't save the image, I mean if I save the image the text will not be saved. I'm searching for a way to save the text too. I mean I have to write a text in the center of the image and then save the image.Careycarfare
W
5

I used TextLayout to get the text properly centered:

example of generated image

Here's how to create the image and save it as a file:

int imgWidth = 250;
int imgHeight = 250;
var img = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB);

Graphics2D g = img.createGraphics();

var backgroundColor = new Color(0, 150, 100);
g.setPaint(backgroundColor);
g.fillRect(0, 0, imgWidth, imgHeight);

var font = new Font("Arial", Font.PLAIN, 80);
g.setFont(font);
g.setPaint(Color.WHITE);

String text = "0";

var textLayout = new TextLayout(text, g.getFont(), g.getFontRenderContext());
double textHeight = textLayout.getBounds().getHeight();
double textWidth = textLayout.getBounds().getWidth();

g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
        RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

// Draw the text in the center of the image
g.drawString(text, imgWidth / 2 - (int) textWidth / 2,
                   imgHeight / 2 + (int) textHeight / 2);

String imgFormat = "png";
ImageIO.write(img, imgFormat, new File("/home/me/new_image." + imgFormat));
Wayside answered 3/10, 2017 at 8:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.