将多行多页格式的文本呈现到BufferedImage(不适用于Android) [英] Rendering multi-line multi-page formatted text to a BufferedImage (not in Android)

查看:97
本文介绍了将多行多页格式的文本呈现到BufferedImage(不适用于Android)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我只需要实现PNG图片的创建,就可以渲染出文本文件的内容。在线搜索时,我发现有一些使用Android的实现,但没有使用标准Java的多行文本的完整示例,因此认为值得在这里发布我的解决方案。

I've just had to implement the creation of a PNG Image, rendering out the contents of a text file. Searching online I found a few implementations using Android but no complete example for multi-line text using standard Java only so thought it would be worth posting my solution here.

分别是:

取一个可能为任意大小的字符串,并使用适当格式的段落将其呈现出来以适合PNG图像,然后将String正确地分成行和段落。如果渲染的文档不适合一页,则生成多个 BufferedImage s,每页一个。

Take a String of potentially any size and render it out with properly formatted paragraphs to fit into PNG images, splitting the String into lines and paragraphs properly. If the rendered document does not fit into one page then generate multiple BufferedImages, one for each page.

推荐答案

我在Java文档中找到了一些用于渲染段落的示例代码,并在此基础上进行了以下修改:

I found some sample code in the Java documentation for rendering out a paragraph, building on that I made the following:

private static final Font FONT = new Font("Serif", Font.PLAIN, 14);
private static final float PARAGRAPH_BREAK = 10;
private static final float MARGIN = 20;

private Graphics2D setupGraphics(BufferedImage img) {
    Graphics2D g2d = img.createGraphics();
    g2d.setFont(FONT);
    g2d.fillRect(0, 0, img.getWidth(), img.getHeight());
    g2d.setColor(Color.BLACK);
    return g2d;
}

private List<BufferedImage> renderText(String str, int width, int height) {
    String[] paragraphs = str.split("\n");

    List<BufferedImage> images = new ArrayList<>();

    BufferedImage img = new BufferedImage(width, 
            height, 
            BufferedImage.TYPE_3BYTE_BGR);
    images.add(img);
    Graphics2D g2d = setupGraphics(img);

    float drawPosY = 0;

    for (int paragraph=0;paragraph<paragraphs.length;paragraph++) {

        drawPosY += PARAGRAPH_BREAK;

        AttributedString attStr = new AttributedString(paragraphs[paragraph]);
        AttributedCharacterIterator it = attStr.getIterator();
        LineBreakMeasurer measurer = new LineBreakMeasurer(it, g2d.getFontRenderContext());
        measurer.setPosition(it.getBeginIndex());

        while (measurer.getPosition() < it.getEndIndex()) {
            TextLayout layout = measurer.nextLayout(img.getWidth()-MARGIN*2);

            if (drawPosY > img.getHeight() - layout.getAscent() - layout.getDescent() - layout.getLeading()) {
                drawPosY = 0;
                img = new BufferedImage((int)(
                        width, 
                        height, 
                        BufferedImage.TYPE_3BYTE_BGR);
                images.add(img);
                g2d.dispose();
                g2d = setupGraphics(img);
            }

            drawPosY += layout.getAscent();

            layout.draw(g2d, MARGIN, drawPosY);

            drawPosY += layout.getDescent()+layout.getLeading();
        }
    }
    g2d.dispose();

    return images;
}

生成的PNG在内存中,所以我按以下方式创建它:

In my case I needed the generated PNG in memory so I created it as follows:

    try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
        ImageIO.write(output, "png", baos);
        ret.setImageData(baos.toByteArray());
    } catch (IOException ex) {
        Logger.getLogger(ImageGenerationService.class.getName()).log(Level.SEVERE, null, ex);
        return null;
    }

本节中几乎相同的代码将导致ImageIO以不同格式写出文件(例如,用 jpg代替 png)或将图像写入文件(使用 FileOutputStream 代替 ByteArrayOutputStream )。

Almost identical code in this section would cause ImageIO to write out the file different formats (for example "jpg" instead of "png") or write the image to a file (using FileOutputStream instead of ByteArrayOutputStream).

我希望这对其他遇到相同问题的人有所帮助。

I hope this helps anyone else with the same problem.

这篇关于将多行多页格式的文本呈现到BufferedImage(不适用于Android)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆