gpt4 book ai didi

Java 用颜色写入 .pdf

转载 作者:行者123 更新时间:2023-11-30 03:47:56 29 4
gpt4 key购买 nike

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

但是,现在我想用颜色写入文件。我想做与 ansi 转义类似的事情,但可能不会使用转义。

如果我想在 .pdf 中创建颜色,我该怎么做(不使用外部来源)?有人能指出我正确的方向吗?

最佳答案

这里是一个非常非常简单的 PDF 创建类的快速破解,它除了在彩色背景上以彩色编写 Courier 文本之外什么也做不了:

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();
}

这创造了这个:

enter image description here

请记住,如上所述,这是一个快速破解,也许是概念验证,并且还有很多需要改进的地方,例如坐标可能应该是 double 而不是 int,在添加到内容之前应对字符串进行转义(特别是关于括号,...

关于Java 用颜色写入 .pdf,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25166533/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com