Android 5中PrintedPdfDocument生成PDF图片体积过大问题求助
嘿,针对你遇到的Android 5上用PrintedPdfDocument生成PDF时图片体积过大的问题,我有几个不用切换到PdfRenderer的实用方案,完全兼容API 19+,一起来看看:
1. 手动压缩图片后再绘制到PDF页面
既然Android 5系统没有自动帮我们压缩图片,那我们可以提前对要插入的Bitmap做压缩处理,从源头减小体积。这里有两种常用方式:
按比例缩放图片:根据PDF页面的实际尺寸,把图片缩小到合适的分辨率,既不影响显示/打印效果,又能大幅降低体积。示例代码:
// 加载原始图片 Bitmap originalBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.your_test_image); // 获取PDF页面的宽度(从PrintAttributes或PdfDocument.PageInfo中获取) int pdfPageWidth = pageInfo.getPageWidth(); // 计算缩放比例,保持图片宽高比 float scaleRatio = (float) pdfPageWidth / originalBitmap.getWidth(); int targetWidth = (int) (originalBitmap.getWidth() * scaleRatio); int targetHeight = (int) (originalBitmap.getHeight() * scaleRatio); // 创建压缩后的Bitmap Bitmap compressedBitmap = Bitmap.createScaledBitmap(originalBitmap, targetWidth, targetHeight, true); // 绘制到PDF页面的Canvas canvas.drawBitmap(compressedBitmap, 0, 0, new Paint()); // 及时回收Bitmap,避免内存泄漏 compressedBitmap.recycle(); originalBitmap.recycle();调整图片质量:如果缩放后体积还是偏大,可以把图片按JPEG格式压缩到合适的质量(比如70%,这个数值可以根据实际效果调整),示例代码:
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); originalBitmap.compress(Bitmap.CompressFormat.JPEG, 70, outputStream); byte[] compressedBytes = outputStream.toByteArray(); // 解码回Bitmap用于绘制 Bitmap compressedBitmap = BitmapFactory.decodeByteArray(compressedBytes, 0, compressedBytes.length);
2. 手动设置PrintAttributes的分辨率(DPI)
PrintAttributes默认的DPI在Android 5上可能偏高,导致图片被渲染成高分辨率的版本,进而增大PDF体积。我们可以手动设置一个合理的DPI(比如300DPI,普通打印完全足够,甚至150DPI也能满足需求):
PrintAttributes printAttributes = new PrintAttributes.Builder() .setMediaSize(mediaSize) .setColorMode(PrintAttributes.COLOR_MODE_COLOR) .setMinMargins(PrintAttributes.Margins.NO_MARGINS) .setResolution(new PrintAttributes.Resolution("custom_dpi", "Custom DPI", 300, 300)) // 自定义DPI .build();
降低DPI会让PDF中图片的像素密度降低,从而有效减小文件体积,同时不会影响打印的清晰度。
3. 利用Canvas缩放绘制优化
如果不想额外创建压缩后的Bitmap,也可以直接在绘制时通过Canvas的缩放功能来缩小图片,让系统在绘制过程中自动处理像素:
canvas.save(); float scaleRatio = (float) pdfPageWidth / originalBitmap.getWidth(); // 缩放Canvas canvas.scale(scaleRatio, scaleRatio); // 绘制原图,此时Canvas会自动按比例缩小绘制 canvas.drawBitmap(originalBitmap, 0, 0, new Paint()); canvas.restore();
这种方式的压缩效果可能不如手动压缩明显,但胜在简单,不需要额外处理Bitmap对象。
你可以根据自己的需求组合这些方案,比如先设置合适的DPI,再手动按比例缩放图片,这样应该能把2000×700px的图片体积控制在和高版本系统相近的水平,而且全程不需要切换到PdfRenderer,完美兼容Kitkat及以上设备。
内容的提问来源于stack exchange,提问作者Tobias Reich

