关于pdf:Android的PdfRenderer类产生低质量的图像

Android's PdfRenderer class produces low quality images

我在API 21上使用PdfRenderer在我的应用程序中显示pdf,我注意到页面质量很差。
我也跟随google示例使用PdfRenderer,这就是我为页面创建Bitmap的方式:

1
2
3
4
5
6
//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类和经典Pdf阅读器之间的巨大区别:

enter image description here enter image description here


ARGB_8888`仅用于颜色质量,但是打印/显示质量与分辨率(在屏幕上显示时,每英寸有多少点)有关。

例如,如果您具有400 DPI屏幕(每英寸400点),并希望以这种质量显示PDF,则应通过Bitmap.createBitmap()渲染位图,该像素为像素大小:

1
2
3
4
5
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()返回以Postscript点为单位的宽度,其中每个pt为1/72英寸。
  • 默认PDF分辨率为72(DPI)。
  • 因此,将#2潜水72,我们得到英寸,再乘以DPI,我们得到像素。换句话说,要匹配显示器的打印设备的质量,您应该增加渲染图像的大小,因为默认的PDF分辨率为72 DPI。还请检查此帖子?


    我来晚了。标有答案的答案对我没有帮助,因为位图过大,因此无法呈现。我找到了原始帖子,因为我遇到了完全相同的问题,也许这个答案对我的情况有帮助。

    我四处搜寻,看看是否有人在保持比例的同时有一种巧妙的方法来缩放位图。我遇到了这个网站:

    https://guides.codepath.com/android/Working-with-the-ImageView#scaling-a-bitmap

    这不是复杂的东西。我只需要另外两行代码:

    1
    2
    int height = DeviceDimensionsHelper.getDisplayHeight(this);
    Bitmap scaledBitmap = BitmapUtil.scaleToFitHeight(bitmap, height);

    我按照网站的建议添加了类似的helper / util类(因此在实践中,它多于两行;))。高度来自

    1
    context.getResources().getDisplayMetrics().widthPixels;

    缩放仅将设备高度除以原始位图高度即可得到一个因子,然后将其乘以原始位图宽度即可找到缩放后的宽度。

    这在我的Nexus 5上完美运行。我无法在多个设备上对此进行测试,但这似乎是一个可靠的解决方案。


    PdfRenderer一样,您将在ImageView中显示PDF页面,最简单的方法是简单地创建ImageView的最大大小的位图,并添加一些数学运算来保留PDF的比例。由于PDF通常是供打印的,因此它们的分辨率始终比屏幕高,因此您不必冒像素化图像的风险。为确保为ImageView分配了measuredWidthmeasuredHeight,请在代码中使用ImageView::post()(对不起,我的Kotlin):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
        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)
        }