views:

537

answers:

1

I have checked similarly named questions, but they don't answer this use case.

Basically, I was to overlay some text (text) at a given coordinate (x,y) I have the below function in a package;

protected BufferedImage Process2(BufferedImage image){
    Graphics2D gO = image.createGraphics();
    gO.setColor(Color.red);
    gO.setFont(new Font( "SansSerif", Font.BOLD, 12 ));
    gO.drawString(this.text, this.x, this.y);
    System.err.println(this.text+this.x+this.y);
    return image;
}

I feel like im missing something patently obvious; every reference to Graphics2D I can find is dealing with either games or writing directly to a file but I just want a BufferedImage returned. with the overlay 'rendered'

In the current code, the image appears out the end unchanged.

Thanks!

+3  A: 

The method drawString() uses x and y for the leftmost character's baseline. Numbers typically have no descenders; if the same is true of text, a string drawn at position (0,0) will be rendered entirely outside the image. See this example.

Addendum: You may be having trouble with an incompatible color model in your image. One simple expedient is to render the image and then modify it in situ.

example

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class TextOverlay extends JPanel {

    private BufferedImage image;

    public TextOverlay() {
        try {
            image = ImageIO.read(new URL(
                "http://sstatic.net/so/img/logo.png"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        this.setPreferredSize(new Dimension(
            image.getWidth(), image.getHeight()));
        image = process(image);
    }

    private BufferedImage process(BufferedImage old) {
        int w = old.getWidth();
        int h = old.getHeight();
        BufferedImage img = new BufferedImage(
            w, h, BufferedImage.TYPE_INT_ARGB);
        Graphics2D g2d = img.createGraphics();
        g2d.drawImage(old, 0, 0, null);
        g2d.setPaint(Color.red);
        g2d.setFont(new Font("Serif", Font.BOLD, 20));
        String s = "Hello, world!";
        FontMetrics fm = g2d.getFontMetrics();
        int x = img.getWidth() - fm.stringWidth(s) - 5;
        int y = fm.getHeight();
        g2d.drawString(s, x, y);
        g2d.dispose();
        return img;
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawImage(image, 0, 0, null);
    }

    private static void create() {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(new TextOverlay());
        f.pack();
        f.setVisible(true);
    }

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

            @Override
            public void run() {
                create();
            }
        });
    }
}
trashgod
Well for my tests I'm using x = image.getHeight()/2 and likewise for y, so I dont think that that is the issue, but thanks!
Andrew Bolster
Any chance you're calling `paintComponent()` with the old image instead of the new?
trashgod
I'm not using any JComponents so no, no paintComponents; but if im missing something fundamental, please slap me with it, I am not a GUI coder and have very little knowledge of dealing with graphics in Java so this could be completely the wrong approach
Andrew Bolster
Pulled out the relevent bit of code, thank you very much for your help!
Andrew Bolster