首页 > 解决方案 > 带有设置边框和新行的 BufferedImage 字符串

问题描述

我是 StackOverflow 的新手,需要帮助解决以下问题。

背景:

我必须为学校做一个项目,在那里我们得到一个可以打印东西的乐高头脑风暴机器人(基于坐标)。我的想法是用Java实现程序,翻译(谷歌翻译API)给定的输入,使用该字符串创建一个BufferedImage,然后读出该图像的坐标,这样机器人就可以绘制/打印翻译后的输入。除了将文本写入 BufferedImage 之外,我得到了一切工作。

问题:

我正在寻找一种使用输入字符串创建 BufferedImage 的方法。图像应具有固定边框(160x200 像素,因为这是机器人坐标系的大小)。我设法创建了一个带有所述边框的 BufferedImage,但是当我在图像上插入字符串时,它只会离开图像,所以字符串的后面部分会丢失。到达边界时是否可以在 BufferedImage 中自动创建一个新行?

我现在只担心宽度,所以它不是问题,如果它在底部被切断(尽管如果你知道如何改变,你也可以告诉我)。字体应该是:

Font font = new Font("Arial", Font.PLAIN, 25);

因为它支持我使用的语言。

谢谢您的帮助!

TL;DR:具有固定大小和字符串作为内容的 BufferedImage。字符串不应该被截断:新行,如果字符串到达​​边界,单词不会被截断。

标签: javastringimageborderbufferedimage

解决方案


好吧,既然我被告知要发布我的答案(即使这会阻止未来的人自己完成作业),那就是这样。此类从给定的输入字符串创建一个 BufferedImage (160x200 px)(还将图像保存为源文件夹中的文件)。我确信它仍然可以改进,但我不知道如何改进,因为这就是我从这里得到的帮助中所做的一切。

图像的示例输出


import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

import javax.imageio.ImageIO;

public class TextToImage {
    
    public static BufferedImage createImage(String inputString) throws IOException{
        
        BufferedImage image = createGraphics(inputString);
        saveImage(image);
        
        return image;
    }
    
    public static BufferedImage createGraphics(String inputString) {
        
        BufferedImage bufferedImage = new BufferedImage(160, 195, BufferedImage.TYPE_INT_RGB);
        Font font = new Font("Arial", Font.PLAIN, 25);
        Graphics2D graphics2D = prepareGraphics(bufferedImage);
        double baseY = getY(getBounds(font, inputString, graphics2D));
        
        if(isLatin(inputString)) {
            drawLinesAsWords(graphics2D, inputString, font, baseY);
        } else {
            drawLinesAsCharacters(graphics2D, inputString, font, baseY);
        }
        
        graphics2D.dispose();

        return bufferedImage;
    }
    
    public static double getY(Rectangle2D bounds) {
        
        double ascent = - bounds.getY();
        double baseY = 0 + ascent;
        return baseY;
    }
    
    public static Rectangle2D getBounds(Font font, String content, Graphics2D graphics2D) {
        FontRenderContext context = graphics2D.getFontRenderContext();
        Rectangle2D bounds = font.getStringBounds(content, context);
        
        return bounds;
    }
    
    public static Graphics2D prepareGraphics(BufferedImage bufferedImage) {
        Graphics2D graphics2D = (Graphics2D)bufferedImage.getGraphics();
        graphics2D.setBackground(Color.GRAY);
        graphics2D.clearRect(0, 0, 160, 195);
        graphics2D.setPaint(Color.BLACK);
        
        return graphics2D;
    }
    
    public static boolean isLatin(String inputString) {
        String regex = "^.*\\p{IsLatin}.*";
        boolean result = inputString.matches(regex);
        if(result) {
            return true;
        } else {
            return false;
        }
    }
    
    public static void saveImage(BufferedImage bufferedImage) throws IOException {
        
        ImageIO.write(bufferedImage, "png", new File("./Image.jpeg"));
    }
    
    public static int getHeight(Font font, Graphics2D g) {
        
        int lineHeight = g.getFontMetrics(font).getHeight();
        return lineHeight;
    }

    public static void drawLinesAsWords(Graphics2D graphics2D, String content, Font font, double baseY) {
        
        int lineHeight = getHeight(font, graphics2D);
        int leftBorder = 5;
        String[] wordArray = content.split(" ");
        FontMetrics fontMetrics = graphics2D.getFontMetrics(font);
        String currentContent = "";
        double leftTopCornerLine = baseY;
        
        for(int i = 0; i < wordArray.length; i++) {
            
            if(leftTopCornerLine < 195) {

                if(fontMetrics.stringWidth(currentContent)>=240) {
                    if(fontMetrics.stringWidth(wordArray[i])<=240-fontMetrics.stringWidth(currentContent)) {
                        currentContent += " " + wordArray[i];
                        graphics2D.drawString(currentContent, leftBorder, (int)leftTopCornerLine);
                        currentContent ="";
                        leftTopCornerLine += lineHeight;
                    } else {
                        graphics2D.drawString(currentContent, leftBorder, (int)leftTopCornerLine);
                        currentContent ="";
                        leftTopCornerLine += lineHeight;
                    }
                } else {
                    int contentWidth = fontMetrics.stringWidth(currentContent);
                    if(contentWidth<=260) {
                        currentContent += " " + wordArray[i];
                    }
                }
            } else {
                System.out.println("Input was cut, because it was too long.");
                break;
            }
        }
    }
    
    public static void drawLinesAsCharacters(Graphics2D graphics2D, String content, Font font, double baseY) {
        int lineHeight = getHeight(font, graphics2D);
        int leftBorder = 5;
        String[] characterArray = content.split("");
        FontMetrics fontMetrics = graphics2D.getFontMetrics(font);
        String currentContent = "";
        double leftTopCornerLine = baseY;
        
        for(int i = 0; i < characterArray.length; i++) {
            
            if(leftTopCornerLine < 195) {

                if(fontMetrics.stringWidth(currentContent)>=210) {
                    if(fontMetrics.stringWidth(characterArray[i])<=210-fontMetrics.stringWidth(currentContent)) {
                        currentContent += characterArray[i];
                        graphics2D.drawString(currentContent, leftBorder, (int)leftTopCornerLine);
                        currentContent ="";
                        leftTopCornerLine += lineHeight;
                    } else {
                        graphics2D.drawString(currentContent, leftBorder, (int)leftTopCornerLine);
                        currentContent ="";
                        leftTopCornerLine += lineHeight;
                    }
                } else {
                    int contentWidth = fontMetrics.stringWidth(currentContent);
                    if(contentWidth<=230) {
                        currentContent += characterArray[i];
                    }
                }
            } else {
                System.out.println("Input was cut, because it was too long.");
                break;
            }
        }
    }
    
}


推荐阅读