简体   繁体   English

Android PdfDocument 文件大小

[英]Android PdfDocument file size

I want to generate a PDF File from a View using the PdfDocument android class introduced in KitKat.我想使用 KitKat 中引入的PdfDocument android 类从视图生成 PDF 文件。 I managed to do it, and the file is so far generated ok, ending up having a correct PDF.我设法做到了,到目前为止文件生成正常,最终得到了正确的 PDF。 The only problem is the file is huge, 12Mb for just one page.唯一的问题是文件很大,一页就有 12Mb。 Is there a way to reduce the File size?有没有办法减小文件大小?

The code I am using to generate the PDF is:我用来生成 PDF 的代码是:

public static File generateDocument(Activity activity, String fileName, ViewGroup container) throws IOException{
    File f = new File(activity.getExternalFilesDir(null), fileName);
    PdfDocument document = new PdfDocument();
    try{
        for(int i=0;i<container.getChildCount();i++){
            View v = container.getChildAt(i);
            PdfDocument.PageInfo.Builder pageBuilder = new PdfDocument.PageInfo.Builder(v.getWidth(), v.getHeight(), i);
            Page page = document.startPage(pageBuilder.create());
            v.draw(page.getCanvas());
            document.finishPage(page);
        }

        document.writeTo(new FileOutputStream(f));
    } finally{
        if(document!=null){
            document.close();
        }
    }
    return f;
}

In case anyone is still looking for a solution... I was working on a project to generate PDF from images and not satisfied with the file size generated by both Android's PdfDocument and 3rd party AndroidPdfWriter APW .如果有人仍在寻找解决方案......我正在从事一个从图像生成 PDF 的项目,并且对 Android 的PdfDocument和第 3 方AndroidPdfWriter APW生成的文件大小不满意。

After some trials I ended up using Apache's PdfBox , which gave me a PDF file (A4 size with a single 1960x1080 image) for around 80K, while it's usually 2~3M with PdfDocument or AndroidPdfWriter .经过一些试验后,我最终使用了 Apache 的PdfBox ,它给了我一个大约 80K 的 PDF 文件(A4 大小和一张 1960x1080 图像),而PdfDocumentAndroidPdfWriter通常是 2~3M。

PDDocument document = new PDDocument();
PDPage page = new PDPage(PDRectangle.A4);
document.addPage(page);

// Define a content stream for adding to the PDF
contentStream = new PDPageContentStream(document, page);

Bitmap bimap = _get_your_bitmap_();
// Here you have great control of the compression rate and DPI on your image.
// Update 2017/11/22: The DPI param actually is useless as of current version v1.8.9.1 if you take a look into the source code. Compression rate is enough to achieve a much smaller file size.
PDImageXObject ximage = JPEGFactory.createFromImage(document, bitmap, 0.75, 72);
// You may want to call PDPage.getCropBox() in order to place your image
// somewhere inside this page rect with (x, y) and (width, height).
contentStream.drawImage(ximage, 0, 0);

// Make sure that the content stream is closed:
contentStream.close();

document.save(_your_file_path_);
document.close();

===== =====

btw.顺便提一句。 I guess the reason why they generate a huge file size is because they don't compress the image data while writing to PDF file.我猜他们生成巨大文件的原因是因为他们在写入 PDF 文件时不压缩图像数据。 If you take a look into AndroidPdfWriter's XObjectImage.deflateImageData() method you will see it's using java.util.zip.Deflater.NO_COMPRESSION option to write the image data which is kind of horrible if you've got a picture with size 1960x1080.如果您查看 AndroidPdfWriter 的 XObjectImage.deflateImageData() 方法,您会看到它使用java.util.zip.Deflater.NO_COMPRESSION选项来写入图像数据,如果您有一张尺寸为 1960x1080 的图片,这会很糟糕。 If you change the options to eg Deflater.BEST_COMPRESSION you get much smaller file size however it takes up to 3-4 seconds for me to handle one single page which is not acceptable.如果您将选项更改为例如Deflater.BEST_COMPRESSION ,您将获得更小的文件大小,但是我处理一个页面最多需要 3-4 秒,这是不可接受的。

There are a few main things that increases the size of a PDF file:有几个主要因素会增加 PDF 文件的大小:

hi-resolution pictures (where lo-res would suffice)
embedded fonts (where content would still be readable "good enough" without them)
PDF content not required any more for the current version/view (older version of certain objects)
embedded ICC profiles
embedded third-party files (using the PDF as a container)
embedded job tickets (for printing)
embedded Javascript
and a few more

Try using iText.尝试使用 iText。 Following links give a basice idea for iText in android.以下链接给出了 android 中 iText 的基本概念。

http://technotransit.wordpress.com/2011/06/17/using-itext-in-android/ http://technotransit.wordpress.com/2011/06/17/using-itext-in-android/

http://www.mysamplecode.com/2013/05/android-itext-pdf-bluetooth-printer.html http://www.mysamplecode.com/2013/05/android-itext-pdf-bluetooth-printer.html

https://stackoverflow.com/a/21025162/3110609 https://stackoverflow.com/a/21025162/3110609

Using PDFDocument, be sure to downscale your images prior to drawing them in the canvas.使用 PDFDocument,确保在画布中绘制图像之前缩小图像。

When drawing to the screen, this is enough to scale the bitmap:绘制到屏幕时,这足以缩放位图:

canvas.drawBitmap(bmp, src, dst, paint);

However, when using the canvas from PdfDocument.Page.getCanvas , this canvas will not downscale the bitmap, it will just squeeze it into a smaller zone.但是,当使用来自PdfDocument.Page.getCanvas的画布时,此画布不会缩小位图,只会将其压缩到较小的区域。 Instead you should do something like this:相反,你应该这样做:

// Scale bitmap : filter = false since we are always downSampling
Bitmap scaledBitmap = Bitmap.createScaledBitmap(bmp, dstWidth, dstHeight,
    false); // filter=false if downscaling, true if upscaling

canvas.drawBitmap(scaledBitmap, null, dst, paint);

scaledBitmap.recycle();

This is embedded in Android so it is much easier than using a third-party library.这是嵌入在 Android 中的,因此它比使用第三方库要容易得多。 (The above was tested on a Marshmallow platform) (以上是在Marshmallow平台上测试的)

This seems to just be a bug in PdfDocument.这似乎只是 PdfDocument 中的一个错误。 The PDF file I created with PdfDocument was 5.6 megabytes.我用 PdfDocument 创建的 PDF 文件是 5.6 兆字节。 The same document generated through the iOS equivalent was 500K.通过 iOS 等效生成的相同文档是 500K。 If I take the Android PDF and run it through Adobe Acrobat's pdf optimization, without compressing any images, the 5.6MB file becomes 350K.如果我使用 Android PDF 并通过 Adobe Acrobat 的 pdf 优化运行它,而不压缩任何图像,则 5.6MB 文件变为 350K。 They look identical, and I applied no compression in Adobe Acrobat.它们看起来完全相同,而且我在 Adobe Acrobat 中没有应用任何压缩。

In the actual PDF code, the Android image object dictionary is this在实际的PDF代码中,Android图像对象字典是这样的

<</Type /XObject
/Subtype /Image
/Width 1224
/Height 1584
/ColorSpace /DeviceRGB
/BitsPerComponent 8
/Length 5816448
>>

The PDF from iOS has this dict来自 iOS 的 PDF 有这个命令

<< /Length 8 0 R
/Type /XObject
/Subtype /Image
/Width 1224
/Height 1584
/ColorSpace /DeviceRGB
/SMask 9 0 R
/BitsPerComponent 8
/Filter /FlateDecode >>

I think the problem is the lack of the FlateDecode filter in the Android version.我认为问题在于 Android 版本中缺少 FlateDecode 过滤器。 When I run it through the Adobe Acrobat PDF optimizer, it gets the FlateDecode filter.当我通过 Adobe Acrobat PDF 优化器运行它时,它获得了 FlateDecode 过滤器。

I want to generate a PDF File from a View using the PdfDocument android class introduced in KitKat.我想使用 KitKat 中引入的PdfDocument android 类从视图生成 PDF 文件。 I managed to do it, and the file is so far generated ok, ending up having a correct PDF.我设法做到了,到目前为止文件生成正常,最终得到了正确的 PDF。 The only problem is the file is huge, 12Mb for just one page.唯一的问题是文件很大,只有一页就有 12Mb。 Is there a way to reduce the File size?有没有办法减少文件大小?

The code I am using to generate the PDF is:我用来生成PDF的代码是:

public static File generateDocument(Activity activity, String fileName, ViewGroup container) throws IOException{
    File f = new File(activity.getExternalFilesDir(null), fileName);
    PdfDocument document = new PdfDocument();
    try{
        for(int i=0;i<container.getChildCount();i++){
            View v = container.getChildAt(i);
            PdfDocument.PageInfo.Builder pageBuilder = new PdfDocument.PageInfo.Builder(v.getWidth(), v.getHeight(), i);
            Page page = document.startPage(pageBuilder.create());
            v.draw(page.getCanvas());
            document.finishPage(page);
        }

        document.writeTo(new FileOutputStream(f));
    } finally{
        if(document!=null){
            document.close();
        }
    }
    return f;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM