使用Java在图像上写多行文本

时间:2015-08-20 05:33:49

标签: java image text

我查看了java.awt.Graphics文档,stackoverflow,找不到解决方案。我输入了两个东西,一个图像文件和多行文本(段落)。我需要在图像文件上写入多行文本,然后将其另存为新图像。想知道我是否遗漏了一些非常简单的东西。 我也愿意使用任何好的第三方库。

final BufferedImage image = ImageIO.read(new File("c:/anil/Lenna.png"));

    Graphics g = image.getGraphics();
    g.setFont(g.getFont().deriveFont(30f));
    g.drawString("Hello world", 100, 100);
    g.dispose();

上面的代码只在图像上写了一行。

4 个答案:

答案 0 :(得分:1)

如果你想绘制几行,你必须明确地做...

所以第一步是检测'线

String str = ... //some text with line breaks;
String [] lines = str.spilt("\n"); //breaking the lines into an array

第二步是绘制所有行

Graphics g = image.getGraphics();
g.setFont(g.getFont().deriveFont(30f));
int lineHeight = g.getFontMetrics().getHeight();
//here comes the iteration over all lines
for(int lineCount = 0; lineCount < lines.length; lineCount ++){ //lines from above
    int xPos = 100;
    int yPos = 100 + lineCount * lineHeight;
    String line = lines[lineCount];
    g.drawString(line, xpos, yPos);
}
g.dispose();

答案 1 :(得分:1)

JLabel接受简单的html来格式化文本。然后你可以在你的图像上画它:

JLabel l=new JLabel("<html>line1<br>line2");
l.setSize(l.getPrefferedSize());
g.translate(10,10); // fixed location
l.paint(g);

编辑:完整示例

public class OP_32110247 extends JPanel {
    private final JLabel l = new JLabel();
    private final BufferedImage image;
    public OP_32110247(String imgfile, String txt) throws IOException {
        image = ImageIO.read(new URL(imgfile));
        l.setText(txt);
        l.setFont(getFont().deriveFont(Font.BOLD,30f));
        l.setSize(l.getPreferredSize());
        l.setForeground(Color.GREEN);
        Dimension d = new Dimension(image.getWidth(), image.getHeight());
        setPreferredSize(d);
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Dimension d = getSize();
        g.drawImage(image, 0, 0, null);
        //place text in center of image
        g.translate((d.width-l.getWidth())/2, (d.height-l.getHeight())/2);
        l.paint(g);
    }

    public static void main(String[] args) throws IOException {
        String txt = "<html>line1<br>line2";
        String image = "http://kysoft.pl/proj/java/j+c.png";
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        f.setContentPane(new OP_32110247(image,txt));
        f.pack();
        f.setVisible(true);
    }
}

答案 2 :(得分:0)

最佳解决方案是扩展JLabel并覆盖paintComponent。使用所需图像创建Label。在调用super.paintComponent之后绘制文本,每行使用字体指标定位在另一行之下。如下所示:

class ImageWithTextLabel extends JLabel {
    List<String> lines = new ArrayList<>();
    Point textPosition = new Point(0,0);
    private Font textFont;

    private ImageWithTextLabel(Icon image) {
        super(image);
    }

    public void addText(String text) {
        lines.add(text);
    }

    public void setTextPosition(Point textPosition) {
        this.textPosition = textPosition;
    }

    @Override protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        int from = textPosition.y ;
        g.setFont(textFont);
        for (String line : lines) {
            g.drawString(line, textPosition.x, from);
            from += g.getFontMetrics().getHeight();
        }
    }

    public void setTextFont(Font font) {
        textFont = font;
    }
}

答案 3 :(得分:0)

请参见Drawing Multiple Lines of Text(Oracle Java Tutorials)complete code 使用LineBreakMeasurer

int width = 400;
int height = 500;
BufferedImage bufferedImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
Graphics2D g2d =  bufferedImage.createGraphics();

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

g2d.setColor(Color.MAGENTA);

Hashtable<TextAttribute,Object> map = new Hashtable<TextAttribute,Object>();
map.put(TextAttribute.FAMILY, "微软雅黑");
map.put(TextAttribute.SIZE,new Float(18.0));
AttributedString vanGogh = new AttributedString(
"Many people 中国 believe that Vincent van Gogh painted his best works " +
"during the two-year period he spent in Provence. Here is where he " +
"painted The Starry Night--which some consider to be his greatest " +
"work of all. However, as his artistic brilliance reached new " +
"heights in Provence, his physical and mental health plummeted. ",
map);

AttributedCharacterIterator paragraph = vanGogh.getIterator();
int paragraphStart   = paragraph.getBeginIndex();
int paragraphEnd = paragraph.getEndIndex();
FontRenderContext frc = g2d.getFontRenderContext();
LineBreakMeasurer lineMeasurer = new LineBreakMeasurer(paragraph, frc);
float breakWidth = 250f;
float drawPosY = 20;
float drawPosx = 0f;
lineMeasurer.setPosition(paragraphStart);
while(lineMeasurer.getPosition()< paragraphEnd ){
    TextLayout layout = lineMeasurer.nextLayout(breakWidth);
    drawPosx = layout.isLeftToRight()?0:breakWidth-layout.getAdvance();
    drawPosY += layout.getAscent();
    layout.draw(g2d,drawPosx,drawPosY);
    drawPosY += layout.getDescent() + layout.getLeading();
}


g2d.dispose();

File file = new File("myimage.png");
ImageIO.write(bufferedImage,"png",file);

file = new File("myimage.jpg");
ImageIO.write(bufferedImage,"jpg",file);