Android 的 PdfRenderer class 生成低质量图像
Android's PdfRenderer class produces low quality images
我正在使用 PdfRenderer
above api 21 在我的应用程序中显示 pdf,我发现页面质量很差。
我还按照 google 示例使用 PdfRenderer
,这就是我为页面创建 Bitmap
的方式:
//mCurrentPage is a PdfRenderer.Page and mImageView is an ImageView
Bitmap bitmap = Bitmap.createBitmap(mCurrentPage.getWidth(),
mCurrentPage.getHeight(),
Bitmap.Config.ARGB_8888);
mCurrentPage.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
mImageView.setImageBitmap(bitmap);
我使用 ARGB_8888
因为据我所知,它是显示位图的最佳质量。
我做错了什么吗?
编辑
这就是 PdfRenderer class 和 classic Pdf 的巨大区别 reader:
ARGB_8888` 仅针对颜色质量,但 printing/displaying 质量与分辨率有关(在屏幕上显示时每英寸有多少点)。
例如,如果您有 400 DPI 屏幕(每英寸 400 点)并希望以这种质量显示 PDF,那么您应该通过 Bitmap.createBitmap() 渲染位图,将像素作为其大小:
Bitmap bitmap = Bitmap.createBitmap(
getResources().getDisplayMetrics().densityDpi * mCurrentPage.getWidth() / 72,
getResources().getDisplayMetrics().densityDpi * mCurrentPage.getHeight() / 72,
Bitmap.Config.ARGB_8888
);
其中:
getResources().getDisplayMetrics().densityDpi
是目标DPI分辨率
mCurrentPage.getWidth()
returns 以 Postscript 点为单位的宽度,其中每个 pt
为 1/72 英寸。
- 72 (DPI) 是默认的 PDF 分辨率。
因此,将 #2 乘以 72 得到英寸,乘以 DPI 得到像素。换句话说,为了匹配显示器打印设备的质量,您应该增加渲染图像的大小,因为默认 PDF 分辨率为 72 DPI。请同时检查 this post?
我来晚了。标记的答案对我没有帮助,因为位图变大了,因此无法渲染。我找到了原来的 post,因为我遇到了完全相同的问题,也许这个答案会对遇到我情况的其他人有所帮助。
我四处搜索,看看是否有人有一个巧妙的解决方案来缩放位图,同时保持比例。我发现了这个网站:
https://guides.codepath.com/android/Working-with-the-ImageView#scaling-a-bitmap
真的,这并不复杂。我只需要另外两行代码:
int height = DeviceDimensionsHelper.getDisplayHeight(this);
Bitmap scaledBitmap = BitmapUtil.scaleToFitHeight(bitmap, height);
我按照网站的建议添加了类似的 helper/util 类(所以在实践中,它不止两行 ;))。身高来自
context.getResources().getDisplayMetrics().widthPixels;
缩放只是简单地将设备高度除以原始位图高度得到一个因子,再乘以原始位图宽度得到缩放后的宽度。
这在我的 Nexus 5 上完美运行。我无法在多个设备上测试它,但它似乎是一个可靠的解决方案。
与 PdfRenderer
一样,您将在 ImageView 中显示 PDF 页面,最简单的方法是简单地创建 ImageView 最大尺寸的位图,并添加一些数学运算以保持 PDF 的比例。由于 PDF 通常用于打印,因此它们的分辨率始终高于您的屏幕,因此您不会冒像素化图像的风险。为确保 ImageView
已分配 measuredWidth
和 measuredHeight
,请在您的代码中使用 ImageView::post()
(请原谅我的 Kotlin):
pdfPageImageView.post {
val viewWidth = pdfPageImageView.measuredWidth
val viewHeight = pdfPageImageView.measuredHeight
val pageWidth = page.width
val pageHeight = page.height
val pageRatio = 1.0 * pageWidth / pageHeight
val viewRatio = 1.0 * viewWidth / viewHeight
val bitmapWidth: Int
val bitmapHeight: Int
if (pageRatio > viewRatio) {
bitmapWidth = viewWidth
bitmapHeight = (viewWidth / pageRatio).toInt()
} else {
bitmapHeight = viewHeight
bitmapWidth = (viewHeight * pageRatio).toInt()
}
val bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888)
page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)
pdfPageImageView.setImageBitmap(bitmap)
}
我正在使用 PdfRenderer
above api 21 在我的应用程序中显示 pdf,我发现页面质量很差。
我还按照 google 示例使用 PdfRenderer
,这就是我为页面创建 Bitmap
的方式:
//mCurrentPage is a PdfRenderer.Page and mImageView is an ImageView
Bitmap bitmap = Bitmap.createBitmap(mCurrentPage.getWidth(),
mCurrentPage.getHeight(),
Bitmap.Config.ARGB_8888);
mCurrentPage.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
mImageView.setImageBitmap(bitmap);
我使用 ARGB_8888
因为据我所知,它是显示位图的最佳质量。
我做错了什么吗?
编辑
这就是 PdfRenderer class 和 classic Pdf 的巨大区别 reader:
ARGB_8888` 仅针对颜色质量,但 printing/displaying 质量与分辨率有关(在屏幕上显示时每英寸有多少点)。
例如,如果您有 400 DPI 屏幕(每英寸 400 点)并希望以这种质量显示 PDF,那么您应该通过 Bitmap.createBitmap() 渲染位图,将像素作为其大小:
Bitmap bitmap = Bitmap.createBitmap(
getResources().getDisplayMetrics().densityDpi * mCurrentPage.getWidth() / 72,
getResources().getDisplayMetrics().densityDpi * mCurrentPage.getHeight() / 72,
Bitmap.Config.ARGB_8888
);
其中:
getResources().getDisplayMetrics().densityDpi
是目标DPI分辨率mCurrentPage.getWidth()
returns 以 Postscript 点为单位的宽度,其中每个pt
为 1/72 英寸。- 72 (DPI) 是默认的 PDF 分辨率。
因此,将 #2 乘以 72 得到英寸,乘以 DPI 得到像素。换句话说,为了匹配显示器打印设备的质量,您应该增加渲染图像的大小,因为默认 PDF 分辨率为 72 DPI。请同时检查 this post?
我来晚了。标记的答案对我没有帮助,因为位图变大了,因此无法渲染。我找到了原来的 post,因为我遇到了完全相同的问题,也许这个答案会对遇到我情况的其他人有所帮助。
我四处搜索,看看是否有人有一个巧妙的解决方案来缩放位图,同时保持比例。我发现了这个网站:
https://guides.codepath.com/android/Working-with-the-ImageView#scaling-a-bitmap
真的,这并不复杂。我只需要另外两行代码:
int height = DeviceDimensionsHelper.getDisplayHeight(this);
Bitmap scaledBitmap = BitmapUtil.scaleToFitHeight(bitmap, height);
我按照网站的建议添加了类似的 helper/util 类(所以在实践中,它不止两行 ;))。身高来自
context.getResources().getDisplayMetrics().widthPixels;
缩放只是简单地将设备高度除以原始位图高度得到一个因子,再乘以原始位图宽度得到缩放后的宽度。
这在我的 Nexus 5 上完美运行。我无法在多个设备上测试它,但它似乎是一个可靠的解决方案。
与 PdfRenderer
一样,您将在 ImageView 中显示 PDF 页面,最简单的方法是简单地创建 ImageView 最大尺寸的位图,并添加一些数学运算以保持 PDF 的比例。由于 PDF 通常用于打印,因此它们的分辨率始终高于您的屏幕,因此您不会冒像素化图像的风险。为确保 ImageView
已分配 measuredWidth
和 measuredHeight
,请在您的代码中使用 ImageView::post()
(请原谅我的 Kotlin):
pdfPageImageView.post {
val viewWidth = pdfPageImageView.measuredWidth
val viewHeight = pdfPageImageView.measuredHeight
val pageWidth = page.width
val pageHeight = page.height
val pageRatio = 1.0 * pageWidth / pageHeight
val viewRatio = 1.0 * viewWidth / viewHeight
val bitmapWidth: Int
val bitmapHeight: Int
if (pageRatio > viewRatio) {
bitmapWidth = viewWidth
bitmapHeight = (viewWidth / pageRatio).toInt()
} else {
bitmapHeight = viewHeight
bitmapWidth = (viewHeight * pageRatio).toInt()
}
val bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888)
page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)
pdfPageImageView.setImageBitmap(bitmap)
}