Класс Android PdfRenderer создает изображения низкого качества

Я использую PdfRenderer выше 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 и классическим читателем Pdf:

введите описание изображения здесь введите описание изображения здесь

Ответ 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
);

где:

  • getResources().getDisplayMetrics().densityDpi - целевое разрешение DPI
  • mCurrentPage.getWidth() возвращает ширину в точках Postscript, где каждый pt равен 1/72 дюйма.
  • 72 (DPI) - разрешение по умолчанию PDF.

Следовательно, дайвинг №2 на 72 мы получаем дюймы и умножаем на DPI, мы получаем пиксели. Другими словами, чтобы соответствовать качеству устройства печати на дисплее, вы должны увеличить размер изображения, созданного по умолчанию, разрешение по умолчанию - 72 DPI. Также проверьте этот пост?

Ответ 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. Я не смог протестировать это на нескольких устройствах, но это кажется надежным решением.

Ответ 3

Вы можете попробовать этот образец с помощью класса PDFViewer, не уверен в качестве, потому что я никогда не использовал его, но он по-прежнему попробуйте:)

Ответ 4

Как и в случае с PdfRenderer вы будете отображать страницы PDF в ImageView, проще всего просто создать растровое изображение максимального размера вашего ImageView, добавив некоторые математические выражения для сохранения пропорций PDF. Поскольку PDF обычно предназначены для печати, они всегда будут иметь более высокое разрешение, чем ваш экран, поэтому вы не рискуете получить пиксельное изображение. Чтобы быть уверенным, что для ImageView ему назначены measuredWidth ImageView и measuredHeight высота, используйте ImageView::post() в своем коде (извините, мой Котлин):

    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)
    }