[英]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 图像),而PdfDocument或AndroidPdfWriter通常是 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.