如何生成带有文字和图像的PDF

问题描述 投票:0回答:1

以下代码片段生成带有文本的 pdf,但图像扭曲像这样

似乎所需的图像应该是

.jpg
。当我使用
.png
时,pdf 中甚至没有显示扭曲的图像。

public static void createPdf() {
    try {
        //Image image = Image.createImage("/icon.png");
        Image image = Image.createImage("/Logo.jpg");
        EncodedImage encodedImage = EncodedImage.createFromImage(image, true);
        byte[] imageData = encodedImage.getImageData();

        StringBuilder content = new StringBuilder();
        content.append("%PDF-1.4\n");
        content.append("1 0 obj<</Type/Catalog/Pages 2 0 R>>endobj\n");
        content.append("2 0 obj<</Type/Pages/Kids [3 0 R]/Count 1>>endobj\n");
        content.append("3 0 obj<</Type/Page/Parent 2 0 R/Resources 4 0 R/MediaBox [0 0 520 800]/Contents 6 0 R>>endobj\n");
        content.append("4 0 obj<</Font<</F1 5 0 R>>/XObject<</Im0 7 0 R>>>>endobj\n");
        content.append("5 0 obj<</Type/Font/Subtype/Type1/BaseFont/Helvetica>>endobj\n");
        content.append("6 0 obj<</Length 219>>stream\n");
        content.append("BT /F1 24 Tf 175 720 Td (Codename One)Tj ET\n");
        content.append("BT /F1 20 Tf 100 700 Td (Using one codebase, build)Tj ET\n");
        content.append("BT /F1 20 Tf 0 660 Td (Android apps)Tj ET\n");
        content.append("BT /F1 20 Tf 0 640 Td (iOS apps)Tj ET\n");
        content.append("BT /F1 20 Tf 0 600 Td (UWP apps)Tj ET\n");
        content.append("512 0 0 512 4 50 cm\n");
        content.append("/Im0 Do\n");
        content.append("endstream\n");
        content.append("endobj\n");
        content.append("7 0 obj<</Type/XObject/Subtype/Image/Width 512/Height 512/ColorSpace/DeviceRGB/BitsPerComponent 8/Filter/DCTDecode/Length 132959>>stream\n");
        
        content.append(new String(imageData));

        content.append("endstream\n");
        content.append("endobj\n");
        content.append("\n");
        content.append("xref\n");
        content.append("0 8\n");
        content.append("0000000000 65535 f \n");
        content.append("0000000009 00000 n \n");
        content.append("0000000052 00000 n \n");
        content.append("0000000102 00000 n \n");
        content.append("0000000197 00000 n \n");
        content.append("0000000255 00000 n \n");
        content.append("0000000316 00000 n \n");
        content.append("0000000609 00000 n \n");
        content.append("trailer\n");
        content.append("<</Size 8/Root 1 0 R>>\n");
        content.append("startxref\n");
        content.append("133724\n");
        content.append("%%EOF\n");
        
        FileSystemStorage fss = FileSystemStorage.getInstance();
        String pdfPath = fss.getAppHomePath() + "Test2.pdf";
        try (Writer w = new OutputStreamWriter(fss.openOutputStream(pdfPath))) {
            w.write(content.toString());
        } catch (Exception e) {
            Log.p("Error " + e);
        }
    } catch (Exception e) {
        Log.p("Error " + e);
    }
}

生成的pdf保存在应用程序存储目录中

home/.cn1

如何从图像中提取出所需的原始图像数据,使图像能够不失真地显示?

编辑:这个问题与this有点不同,因为我需要生成/创建图像二进制数据并以编程方式而不是手动插入到pdf中

编辑: 下面现在直接写入

InputStream
中的字符。图像流现在更加原始,如this。但图像仍然扭曲,如 this Test6.pdf.

private void createPdf6() {
    try {
        FileSystemStorage fss = FileSystemStorage.getInstance();
        String pdfPath = fss.getAppHomePath() + "Test6.pdf";
        try (Writer w = new OutputStreamWriter(fss.openOutputStream(pdfPath))) {

            StringBuilder start = new StringBuilder();
            start.append("%PDF-1.4\n");
            start.append("1 0 obj<</Type/Catalog/Pages 2 0 R>>endobj\n");
            start.append("2 0 obj<</Type/Pages/Kids [3 0 R]/Count 1>>endobj\n");
            start.append("3 0 obj<</Type/Page/Parent 2 0 R/Resources 4 0 R/MediaBox [0 0 520 800]/Contents 6 0 R>>endobj\n");
            start.append("4 0 obj<</Font<</F1 5 0 R>>/XObject<</Im0 7 0 R>>>>endobj\n");
            start.append("5 0 obj<</Type/Font/Subtype/Type1/BaseFont/Helvetica>>endobj\n");
            start.append("6 0 obj<</Length 219>>stream\n");
            start.append("BT /F1 24 Tf 175 720 Td (Codename One)Tj ET\n");
            start.append("BT /F1 20 Tf 100 700 Td (Using one codebase, build)Tj ET\n");
            start.append("BT /F1 20 Tf 0 660 Td (Android apps)Tj ET\n");
            start.append("BT /F1 20 Tf 0 640 Td (iOS apps)Tj ET\n");
            start.append("BT /F1 20 Tf 0 600 Td (UWP apps)Tj ET\n");
            start.append("512 0 0 512 4 50 cm\n");
            start.append("/Im0 Do\n");
            start.append("endstream\n");
            start.append("endobj\n");
            //content.append("7 0 obj<</Type/XObject/Subtype/Image/Width 512/Height 512/ColorSpace/DeviceRGB/BitsPerComponent 8/Filter/DCTDecode/Length 132959>>stream\n");
            start.append("7 0 obj<</Type/XObject/Subtype/Image/Width 50/Height 50/ColorSpace/DeviceRGB/BitsPerComponent 8/Length 132959>>stream\n");
            w.write(start.toString());

            InputStream is = Display.getInstance().getResourceAsStream(this.getClass(), "/Logo.jpg");
            //InputStream is = Display.getInstance().getResourceAsStream(this.getClass(), "/icon.jpeg");
            //InputStream is = Display.getInstance().getResourceAsStream(this.getClass(), "/icon.png");

            int nextChar = is.read();
            if (nextChar == -1) {
                //return null;
            }

            while (nextChar > -1) {
                //Log.p("Char " + (char) nextChar);
                char[] charArray = {(char) nextChar};
                w.write(charArray);
                nextChar = is.read();
            }

            StringBuilder end = new StringBuilder();
            end.append("\nendstream\n");
            end.append("endobj\n");
            end.append("\n");
            end.append("xref\n");
            end.append("0 8\n");
            end.append("0000000000 65535 f \n");
            end.append("0000000009 00000 n \n");
            end.append("0000000052 00000 n \n");
            end.append("0000000102 00000 n \n");
            end.append("0000000197 00000 n \n");
            end.append("0000000255 00000 n \n");
            end.append("0000000316 00000 n \n");
            end.append("0000000609 00000 n \n");
            end.append("trailer\n");
            end.append("<</Size 8/Root 1 0 R>>\n");
            end.append("startxref\n");
            end.append("133724\n");
            end.append("%%EOF\n");
            w.write(end.toString());

        } catch (Exception e) {
            Log.p("Error " + e);
        }
    } catch (Exception e) {
        Log.p("Error " + e);
    }
}

我必须从对象中删除

Filter/DCTDecode
才能显示图像。为了显示更大的图像,我必须将高度和宽度减小到
Width 50/Height 50

直接写入 pdf 内容,而不将

StringBuilder
结果附加到 此 Test7.pdf。那就是

private void createPdf7() {
    try {
        FileSystemStorage fss = FileSystemStorage.getInstance();
        String pdfPath = fss.getAppHomePath() + "Test7.pdf";
        try (Writer w = new OutputStreamWriter(fss.openOutputStream(pdfPath))) {

            w.write("%PDF-1.4\n");
            w.write("1 0 obj<</Type/Catalog/Pages 2 0 R>>endobj\n");
            w.write("2 0 obj<</Type/Pages/Kids [3 0 R]/Count 1>>endobj\n");
            w.write("3 0 obj<</Type/Page/Parent 2 0 R/Resources 4 0 R/MediaBox [0 0 520 800]/Contents 6 0 R>>endobj\n");
            w.write("4 0 obj<</Font<</F1 5 0 R>>/XObject<</Im0 7 0 R>>>>endobj\n");
            w.write("5 0 obj<</Type/Font/Subtype/Type1/BaseFont/Helvetica>>endobj\n");
            w.write("6 0 obj<</Length 219>>stream\n");
            w.write("BT /F1 24 Tf 175 720 Td (Codename One)Tj ET\n");
            w.write("BT /F1 20 Tf 100 700 Td (Using one codebase, build)Tj ET\n");
            w.write("BT /F1 20 Tf 0 660 Td (Android apps)Tj ET\n");
            w.write("BT /F1 20 Tf 0 640 Td (iOS apps)Tj ET\n");
            w.write("BT /F1 20 Tf 0 600 Td (UWP apps)Tj ET\n");
            w.write("512 0 0 512 4 50 cm\n");
            w.write("/Im0 Do\n");
            w.write("endstream\n");
            w.write("endobj\n");
            w.write("7 0 obj<</Type/XObject/Subtype/Image/Width 50/Height 50/ColorSpace/DeviceRGB/BitsPerComponent 8/Length 132959>>stream\n");

            InputStream is = Display.getInstance().getResourceAsStream(this.getClass(), "/Logo.jpg");
            //InputStream is = Display.getInstance().getResourceAsStream(this.getClass(), "/icon.jpeg");
            //InputStream is = Display.getInstance().getResourceAsStream(this.getClass(), "/icon.png");

            int nextChar = is.read();
            if (nextChar == -1) {
                //return null;
            }

            while (nextChar > -1) {
                //Log.p("Char " + (char) nextChar);
                char[] charArray = {(char) nextChar};
                w.write(charArray);
                nextChar = is.read();
            }
            w.write("\nendstream\n");
            w.write("endobj\n");
            w.write("\n");
            w.write("xref\n");
            w.write("0 8\n");
            w.write("0000000000 65535 f \n");
            w.write("0000000009 00000 n \n");
            w.write("0000000052 00000 n \n");
            w.write("0000000102 00000 n \n");
            w.write("0000000197 00000 n \n");
            w.write("0000000255 00000 n \n");
            w.write("0000000316 00000 n \n");
            w.write("0000000609 00000 n \n");
            w.write("trailer\n");
            w.write("<</Size 8/Root 1 0 R>>\n");
            w.write("startxref\n");
            w.write("133724\n");
            w.write("%%EOF\n");

        } catch (Exception e) {
            Log.p("Error " + e);
        }
    } catch (Exception e) {
        Log.p("Error " + e);
    }
}

为了使图像正确显示,我还缺少什么?

编辑 使用 Linux 文本编辑器打开 this JSjpegSample-with image.pdf 显示以下图像数据流编码。注意一些可读的文字,例如

JFIF
Photoshop 7.0
Pdf with image

在 Codename One 模拟器中,这种编码方式与 SQLite 数据库文件的编码方式接近。使用 Linux 文本编辑器打开 SQLite 数据库显示以下内容。注意一些可读的文字,例如

SQLite format 3
CREATE TABLE
SQLite DB

如何将要添加到 pdf 的

.jpeg
以与 SQLite 数据库文件相同的方式编码?

codenameone
1个回答
0
投票

以下成功将图像添加到pdf文档中。要求包括:

  1. 使用以下命令创建

    jpeg
    图像
    EncodedImage.createFromImage(image, true);
    这很有用,因为
    png
    图像可以转换为
    jpeg

  2. 从图像字节创建

    ByteArrayInputStream
    。使用
    ByteArrayInputStream
    ,图像字节直接作为字符写入 pdf。

  3. ISO-8859-1
    中设置
    OutputStreamWriter
    编码。这种编码确保图像字节中的所有字符都按预期读取
    Filter/DCTDecode

    Windows-1252
    编码也尝试,但一些十六进制被读取为
    ?


    private void createPdf11() {
        try {
            Image image = Image.createImage("/Logo.jpg");
            //Image image = Image.createImage("/icon.jpeg");
            //Image image = Image.createImage("/icon.png");
            
            //create a jpeg encoded image
            EncodedImage encodedImage = EncodedImage.createFromImage(image, true);
            byte[] imageData = encodedImage.getImageData();
            
            //create ByteArrayInputStream from image byte array
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(imageData);

            FileSystemStorage fss = FileSystemStorage.getInstance();
            String pdfPath = fss.getAppHomePath() + "Test11.pdf";
            try (Writer w = new OutputStreamWriter(fss.openOutputStream(pdfPath), "ISO-8859-1")) {
                w.write("%PDF-1.7\n");
                w.write("1 0 obj<</Type/Catalog/Pages 2 0 R>>endobj\n");
                w.write("2 0 obj<</Type/Pages/Kids [3 0 R]/Count 1>>endobj\n");
                w.write("3 0 obj<</Type/Page/Parent 2 0 R/Resources 4 0 R/MediaBox [0 0 520 800]/Contents 6 0 R>>endobj\n");
                w.write("4 0 obj<</Font<</F1 5 0 R>>/XObject<</Im0 7 0 R>>>>endobj\n");
                w.write("5 0 obj<</Type/Font/Subtype/Type1/BaseFont/Helvetica>>endobj\n");
                w.write("6 0 obj<</Length 219>>stream\n");
                w.write("BT /F1 24 Tf 175 720 Td (Codename One)Tj ET\n");
                w.write("BT /F1 20 Tf 100 700 Td (Using one codebase, build)Tj ET\n");
                w.write("BT /F1 20 Tf 0 660 Td (Android apps)Tj ET\n");
                w.write("BT /F1 20 Tf 0 640 Td (iOS apps)Tj ET\n");
                w.write("BT /F1 20 Tf 0 600 Td (UWP apps)Tj ET\n");
                w.write("512 0 0 512 4 50 cm\n");
                w.write("/Im0 Do\n");
                w.write("endstream\n");
                w.write("endobj\n");
                w.write("7 0 obj<</Type/XObject/Subtype/Image/Width 512/Height 512/ColorSpace/DeviceRGB/BitsPerComponent 8/Filter/DCTDecode/Length 132959>>stream\n");
     
                //read the next byte of data from ByteArrayInputStream in int range 0 - 255
                int nextChar = byteArrayInputStream.read();
                while (nextChar > -1) {
                    //convert int to char and add it to char array
                    char[] charArray = {(char) nextChar};
                    //write char array
                    w.write(charArray);
                    nextChar = byteArrayInputStream.read();
                }

                w.write("\nendstream\n");
                w.write("endobj\n");
                w.write("\n");
                w.write("xref\n");
                w.write("0 8\n");
                w.write("0000000000 65535 f \n");
                w.write("0000000009 00000 n \n");
                w.write("0000000052 00000 n \n");
                w.write("0000000102 00000 n \n");
                w.write("0000000197 00000 n \n");
                w.write("0000000255 00000 n \n");
                w.write("0000000316 00000 n \n");
                w.write("0000000609 00000 n \n");
                w.write("trailer\n");
                w.write("<</Size 8/Root 1 0 R>>\n");
                w.write("startxref\n");
                w.write("133724\n");
                w.write("%%EOF\n");

            } catch (Exception e) {
                Log.p("Error " + e);
            }
        } catch (Exception e) {
            Log.p("Error " + e);
        }
    }


这将在应用程序主路径目录中创建带有文本和图像的 Test11.pdf

home/.cn1

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.