我想使用KitKat中引入的PdfDocument
android类从View生成PDF文件。我设法做到了,文件到目前为止生成正常,最终得到了正确的PDF。唯一的问题是文件很大,只有一页12Mb。有没有办法减少文件大小?
我用来生成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;
}
答案 0 :(得分:5)
有一些主要因素会增加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
尝试使用iText。以下链接为Android中的iText提供了一个基本的想法。
http://technotransit.wordpress.com/2011/06/17/using-itext-in-android/
http://www.mysamplecode.com/2013/05/android-itext-pdf-bluetooth-printer.html
答案 1 :(得分:3)
如果有人仍在寻找解决方案......我正在开发一个项目来从图像生成PDF,并且不满意Android的 PdfDocument 和第三方生成的文件大小 AndroidPdfWriter APW。
经过一些试验后,我最终使用了Apache的PdfBox,它给了我一个PDF文件(A4大小,单个1960x1080图像),大约80K,而它通常是2~3M, PdfDocument 或 AndroidPdfWriter 。
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();
=====
顺便说一句。我猜他们生成巨大文件大小的原因是因为他们在写入PDF文件时不压缩图像数据。如果你看一下AndroidPdfWriter的XObjectImage.deflateImageData()方法,你会看到它正在使用java.util.zip.Deflater.NO_COMPRESSION
选项来编写图像数据,如果你有一张尺寸为1960x1080的照片,那就太可怕了。如果您将选项更改为例如Deflater.BEST_COMPRESSION
你的文件大小要小得多,但是我需要3-4秒才能处理一页,这是不可接受的。
答案 2 :(得分:2)
这似乎只是PdfDocument中的一个错误。我用PdfDocument创建的PDF文件是5.6兆字节。通过iOS等效生成的同一文档是500K。如果我使用Android PDF并通过Adobe Acrobat的pdf优化运行它,而不压缩任何图像,5.6MB文件将变为350K。它们看起来完全相同,我在Adobe Acrobat中没有应用压缩。
在实际的PDF代码中,Android图像对象字典就是这个
<</Type /XObject
/Subtype /Image
/Width 1224
/Height 1584
/ColorSpace /DeviceRGB
/BitsPerComponent 8
/Length 5816448
>>
来自iOS的PDF有这个词典
<< /Length 8 0 R
/Type /XObject
/Subtype /Image
/Width 1224
/Height 1584
/ColorSpace /DeviceRGB
/SMask 9 0 R
/BitsPerComponent 8
/Filter /FlateDecode >>
我认为问题是Android版本中缺少FlateDecode过滤器。当我通过Adobe Acrobat PDF优化器运行它时,它将获得FlateDecode过滤器。
答案 3 :(得分:1)
使用PDFDocument 确保在将图像绘制到画布之前缩小图像尺寸。
绘制到屏幕时,这足以缩放位图:
canvas.drawBitmap(bmp, src, dst, paint);
但是,当使用PdfDocument.Page.getCanvas
中的画布时,此画布不会缩小位图,只会将其挤压到较小的区域。相反,你应该做这样的事情:
// 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();
这是嵌入在Android中,因此它比使用第三方库容易得多。 (以上是在Marshmallow平台上测试的)
答案 4 :(得分:0)
要在使用PdfDocument时减小PDF文件的大小,请使用Bitmap.Config.RGB_565
或Bitmap.Config.ARGB_8888
与Bitmap.Config.ARGB_4444
创建位图会增加文件大小
Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);