【问题标题】:Android's PdfRenderer class produces low quality imagesAndroid 的 PdfRenderer 类生成低质量图像
【发布时间】:2015-11-23 06:53:29
【问题描述】:

我正在使用PdfRendererabove api 21 在我的应用程序中显示 pdf,我注意到页面的质量很差。 我还按照谷歌示例使用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 类和经典 Pdf 阅读器之间的巨大差异:

【问题讨论】:

  • 放大/缩小或切换焦点/焦点后,pdf的质量会改变吗?
  • @Sipty 不,它没有。
  • 课堂上的局限真可怕!我建议应用 AA 以及其他一些方法来提高位图的质量。如果这不起作用,那么下一个最佳步骤可能是让您选择外部库。我的猜测是 Android 人员没有使用亚像素渲染和/或特定字体的问题。那里有一些很棒的库,可以为您提供大量额外有用的选项。
  • @Sipty 我实际上在使用 api 21 以下的外部库。但是,关于 Android sdk 在 api 21 以上提供此类的事实,我已经尝试实现它
  • @Sipty github.com/JoanZapata/android-pdfview 但截图来自 Adob​​e Reader

标签: android pdf bitmap pdfrenderer


【解决方案1】:

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

例如,如果您有 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
);

地点:

  1. getResources().getDisplayMetrics().densityDpi 是目标 DPI 分辨率
  2. mCurrentPage.getWidth() 以 Postscript 点返回宽度,其中每个 pt 为 1/72 英寸。
  3. 72 (DPI) 是默认的 PDF 分辨率。

因此,将#2 乘以 72 得到英寸,乘以 DPI 得到像素。换句话说,为了匹配显示器打印设备的质量,您应该增加渲染图像的大小,因为默认 PDF 分辨率为 72 DPI。也请检查this post?

【讨论】:

  • 明白了,谢谢你的回答,帮了大忙!
  • 尤金 M - 很好的答案。我有个问题。现在我提高了应用程序的质量,速度变得非常慢。估计是内存不够了你知道一个解决方案吗?谢谢
  • @Joolah 你可以通过计算 bitmap.getWidth()*bitmap.getHeight() * 4 来计算 Bitmap 使用了多少字节(对于 ARGB,每个像素使用 32 个字节)
  • 当心使用这个 densityDpi / 72 - 在我这样做之后,它会在较新的高 DPI 设备上导致 OutOfMemory 错误。所以现在,我简单地将我的高度和宽度乘以 2 以获得更清晰的图像,它看起来相当不错。
  • 这将在与 PDF 页面大小相同的设备上呈现足够大的位图以实现全分辨率。由于大多数设备都小得多,这比所需的内存要多得多。对于我的 420 DPI Nexus 5x 上的 8.5"x11" PDF,这会生成 69 MB 位图。使用 getResources().getDisplayMetrics().widthPixels/heightPixels 代替(或根据下面 blae 的答案缩放)给我一个 6.5 MB 的位图,不到 10% 的内存使用量,这是我的设备无论如何都可以渲染的最佳位图。更高的唯一原因是放大特定部分。
【解决方案2】:

我来晚了。标记的答案对我没有帮助,因为位图变大了,因此无法渲染。我找到了原始帖子,因为我遇到了完全相同的问题,也许这个答案会帮助我遇到的其他人。

我四处搜寻,看看是否有人有一个巧妙的解决方案来缩放位图,同时保持比例。我偶然发现了这个网站:

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

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

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

我添加了网站建议的类似帮助程序/实用程序类(因此在实践中,它超过两行;))。高度来自

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

缩放只是将设备高度除以原始位图高度得到一个因子,然后再乘以原始位图宽度以找到缩放后的宽度。

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

【讨论】:

  • 不是灵丹妙药。但比接受的答案更好。
  • "DeviceDimensionsHelper.getDisplayHeight" 这是手机显示屏的高度。如果有人用它进行渲染,那么图像视图的高度呢?
【解决方案3】:

PdfRenderer 一样,您将在 ImageView 中显示 PDF 页面,最简单的方法是简单地创建一个最大尺寸的 ImageView 位图,并添加一些数学来保持 PDF 的比例。由于 PDF 通常用于打印,因此它们的分辨率总是比您的屏幕高,因此您不会冒险获得像素化图像。为确保ImageView 已分配measuredWidthmeasuredHeight,请在您的代码中使用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)
    }

【讨论】:

    猜你喜欢
    • 2021-10-27
    • 1970-01-01
    • 1970-01-01
    • 2012-05-13
    • 2012-12-12
    • 2016-02-09
    • 1970-01-01
    • 1970-01-01
    • 2014-08-10
    相关资源
    最近更新 更多