Java使用颜色写入.pdf [英] Java write to .pdf with color

查看:151
本文介绍了Java使用颜色写入.pdf的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个.pdf文件,然后以彩色写入。通过控制台,我已经能够做到这一点与ansi转义序列。例如,如果我想要红色,我把\\\ [31m在我的字符串和\\\ [0m删除所有格式。您可以更改背景和前景。我设计了我自己的有用的类,以帮助显示信息,甚至是一个基于文本的象棋项目我仍然工作。

I would like to create a .pdf file and then write to it in color. Through consoles, I have been able to do that with ansi escape sequences. For example if I want red I put "\u001b[31m" in front of my string and "\u001b[0m" to remove all the formatting. You can change the background and the foreground. I designed my own useful class around this to help with displaying information and even for a text-based chess project I am still working on.

但是,现在我想用颜色写入文件。我想做一个类似的事情,我用ansi转义,但可能没有转义。

However, now I would like to write to files with colors. I would like to do a similar thing that I did with the ansi escapes but probably not with escapes.

如果我想在.pdf中创建颜色, (不使用外部来源)?

If I want to create color in a .pdf, how would I do that (without utilizing an external source)? Can someone point me in the right direction?

推荐答案

这里有一个非常简单的PDF创建者类,多于在彩色背景上用彩色书写Courier文本:

Here a quick hack of a very very simple PDF creator class which can do nothing more than writing Courier text in color on colored background:

public class SimplePdfCreator
{
    /**
     * Creates a {@link SimplePdfCreator} instance writing to the
     * given {@link OutputStream}.
     */
    public SimplePdfCreator(OutputStream os) throws IOException
    {
        pdfOs = os instanceof BufferedOutputStream ? (BufferedOutputStream) os : new BufferedOutputStream(os);

        writeHeader();
        fontObjectNr = writeFont();
        initPage();
    }

    /**
     * Sets the (fill) color for the upcoming operations on the current page.
     */
    public void color(float r, float g, float b)
    {
        pageBuilder.append(r)
                   .append(' ')
                   .append(g)
                   .append(' ')
                   .append(b)
                   .append(" rg\n");
    }

    /**
     * Sets the background (fill) color for the upcoming operations on the current page.
     */
    public void backColor(float r, float g, float b)
    {
        backBuilder.append(r)
                   .append(' ')
                   .append(g)
                   .append(' ')
                   .append(b)
                   .append(" rg\n");
    }

    /**
     * Prints the given text on a baseline starting at the given coordinates
     * on the current page.
     */
    public void print(int x, int y, String string)
    {
        pageBuilder.append(x - xNow)
                   .append(' ')
                   .append(y - yNow)
                   .append(" Td (")
                   .append(string)
                   .append(") Tj\n");
        xNow = x;
        yNow = y;
        fillBack(string);
    }

    /**
     * Prints the given text on the next line on the current page.
     */
    public void print(String string)
    {
        pageBuilder.append("(")
                   .append(string)
                   .append(") '\n");
        yNow -= leading;
        fillBack(string);
    }

    /**
     * Stores the current page with the printed content in the output
     * and creates a new one.
     */
    public void storePage() throws IOException
    {
        writePageContent();
        initPage();
    }

    /**
     * Returns the width of the given String.
     */
    public double getStringWidth(String string)
    {
        return string.length() * fontSize * .6;
    }

    /**
     * Returns the font size
     */
    public int getFontSize()
    {
        return fontSize;
    }

    /**
     * Returns the leading
     */
    public int getLeading()
    {
        return leading;
    }

    /**
     * Finishes the output writing required data to it and closing the
     * target {@link OutputStream}.
     */
    public void close() throws IOException
    {
        int pagesObjectNr = writePages();
        int catalogObjectNr = writeCatalog(pagesObjectNr);
        long xrefPosition = writeXref();
        writeTrailer(catalogObjectNr);
        writeFooter(xrefPosition);
        pdfOs.close();;
    }

    //
    // helper methods
    //
    void writeHeader() throws IOException
    {
        write("%PDF-1.4\n".getBytes(charSet));
        write(new byte[]{'%', (byte)128, (byte)129, (byte)130, '\n'});
    }

    int writeFont() throws IOException
    {
        return writeObject("<</Type/Font/Subtype/Type1/BaseFont/Courier/Encoding/WinAnsiEncoding>>\n".getBytes(charSet));
    }

    void initPage()
    {
        pageBuilder.setLength(0);
        backBuilder.setLength(0);
        pageBuilder.append("BT/F0 ")
                   .append(fontSize)
                   .append(" Tf ")
                   .append(leading)
                   .append(" TL 0 g\n");
        backBuilder.append("1 g\n");
        xNow = 0;
        yNow = 0;
    }

    void fillBack(String string)
    {
        backBuilder.append(xNow)
                   .append(' ')
                   .append(yNow - leading*.2)
                   .append(' ')
                   .append(getStringWidth(string))
                   .append(' ')
                   .append(leading)
                   .append(" re f\n");
    }

    void writePageContent() throws IOException
    {
        pageBuilder.append("ET\n");
        StringBuilder contents = new StringBuilder();
        contents.append("<</Length ")
                .append(pageBuilder.length() + backBuilder.length())
                .append(">>\nstream\n")
                .append(backBuilder)
                .append(pageBuilder)
                .append("\nendstream\n");
        int contentsObjectNr = writeObject(contents.toString().getBytes(charSet));
        pageContentsObjects.add(contentsObjectNr);
    }

    int writePages() throws IOException
    {
        int pagesObjectNrToBe = xref.size() + pageContentsObjects.size() + 1;
        StringBuilder pages = new StringBuilder();
        pages.append("<</Type /Pages /Count ")
             .append(pageContentsObjects.size())
             .append("/Kids[");
        for (int pageContentObject : pageContentsObjects)
        {
            int pageObjectNr = writeObject(String.format("<</Type/Page/Parent %s 0 R/Contents %s 0 R>>\n", pagesObjectNrToBe, pageContentObject).getBytes(charSet));
            pages.append(pageObjectNr).append(" 0 R ");
        }
        pages.append("]/Resources<</ProcSet[/PDF/Text]/Font<</F0 ")
             .append(fontObjectNr)
             .append(" 0 R>>>>/MediaBox[0 0 612 792]>>\n");
        return writeObject(pages.toString().getBytes(charSet));
    }

    int writeCatalog(int pagesObjectNr) throws IOException
    {
        return writeObject(String.format("<</Type/Catalog/Pages %s 0 R>>\n", pagesObjectNr).getBytes(charSet));
    }

    long writeXref() throws IOException
    {
        long xrefPos = position;
        byte[] eol = new byte[]{'\n'};
        write("xref\n".getBytes(charSet));
        write(String.format("0 %s\n", xref.size() + 1).getBytes(charSet));
        write("0000000000 65535 f ".getBytes(charSet));
        write(eol);
        for(long position: xref)
        {
            write(String.format("%010d 00000 n ", position).getBytes(charSet));
            write(eol);
        }
        return xrefPos;
    }

    void writeTrailer(int catalogObjectNr) throws IOException
    {
        write(String.format("trailer\n<</Size %s/Root %s 0 R>>\n", xref.size() + 1, catalogObjectNr).getBytes(charSet));
    }

    void writeFooter(long xrefPosition) throws IOException
    {
        write(String.format("startxref\n%s\n%%%%EOF\n", xrefPosition).getBytes(charSet));
    }

    int writeObject(byte[] bytes) throws IOException
    {
        int objectNr = startObject();
        write(bytes);
        endObj();
        return objectNr;
    }

    int startObject() throws IOException
    {
        xref.add(position);
        int objectNr = xref.size();
        write(String.format("%s 0 obj\n", objectNr).getBytes(charSet));
        return objectNr;
    }

    void endObj() throws IOException
    {
        write("endobj\n".getBytes(charSet));
    }

    long write(byte[] bytes) throws IOException
    {
        if (bytes != null)
        {
            pdfOs.write(bytes);
            position += bytes.length;
        }
        return position;
    }

    final BufferedOutputStream pdfOs;
    final Charset charSet = Charset.forName("ISO-8859-1");
    final List<Long> xref = new ArrayList<Long>();
    final List<Integer> pageContentsObjects = new ArrayList<Integer>();
    final StringBuilder pageBuilder = new StringBuilder();
    final StringBuilder backBuilder = new StringBuilder();
    final int fontObjectNr;
    long position = 0;

    int xNow = 0;
    int yNow = 0;

    int fontSize = 11;
    int leading = 11;
}

您可以这样使用:

public void test() throws IOException
{
    SimplePdfCreator creator = new SimplePdfCreator(new FileOutputStream("target/test-outputs/SimpleGenerated.pdf"));

    creator.print(100, 500, "Test line 1");
    creator.print("Test line 2");

    creator.color(1, 0, 0);
    creator.backColor(0, 1, 1);
    creator.print(100, 450, "Test line red");
    creator.color(0, 1, 0);
    creator.backColor(1, 0, 1);
    creator.print("Test line green");
    creator.color(0, 0, 1);
    creator.backColor(1, 1, 0);
    creator.print("Test line blue");

    creator.color(1, 1, 1);
    creator.backColor(0, 0, 0);

    creator.print(100, 400, "step");
    creator.print(100 + (int)creator.getStringWidth("step"), 400 - creator.getLeading(), "by");
    creator.print(100 + (int)creator.getStringWidth("stepby"), 400 - 2 * creator.getLeading(), "step");

    creator.storePage();

    creator.print(100, 400, "Page 2");

    creator.storePage();

    creator.close();
}

这会创建:

>

,如上所述,这是一个快速的黑客,也许是一个概念的证明,有很多需要改进,例如坐标可能应该是double而不是int,字符串应该在添加到内容之前转义(特别是括号,...

And remember, as mentioned above, this is a quick hack, maybe a prove of concept, and there is much to improve, e.g. coordinates probably should be double instead of int, strings shall be escaped before adding to the content (especially concerning brackets, ...

这篇关于Java使用颜色写入.pdf的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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