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-ридером:

3 ответа

Решение

ARGB_8888` только для качества цвета, но качество печати / отображения связано с разрешением (сколько точек на дюйм у вас при отображении на экране).

Например, если у вас есть экран с разрешением 400 точек на дюйм (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. Пожалуйста, также проверьте этот пост?

Я немного опоздал. Отмеченный ответ не помог мне, потому что растровое изображение стало большим, и, таким образом, его нельзя было воспроизвести. Я нашел оригинальный пост, потому что у меня была точно такая же проблема, возможно, этот ответ поможет другим в моей ситуации.

Я искал вокруг, чтобы увидеть, есть ли у кого-нибудь аккуратное решение для масштабирования растрового изображения при сохранении соотношения. Я наткнулся на этот сайт:

https://guides.codepath.com/android/Working-with-the-ImageView

Это не сложная штука, правда. Мне понадобились только две дополнительные строки кода:

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

Я добавил аналогичные классы хелпера / утилит, как предлагает сайт (так что на практике это более двух строк;)). Высота исходит от

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

Масштабирование просто делит высоту устройства на исходную высоту растрового изображения, чтобы получить коэффициент, который, в свою очередь, умножается на исходную ширину растрового изображения, чтобы найти масштабированную ширину.

Это отлично работает на моем Nexus 5. Я не смог протестировать это на нескольких устройствах, но это похоже на твердое решение.

Как с PdfRenderer вы будете отображать страницы PDF в ImageView, проще всего просто создать растровое изображение максимального размера вашего ImageView с некоторыми математическими добавками, чтобы сохранить пропорции PDF. Поскольку PDF-файлы обычно предназначены для печати, они всегда будут иметь более высокое разрешение, чем ваш экран, поэтому вы не рискуете получить пиксельное изображение. Чтобы быть уверенным ImageView имеет это measuredWidth а также 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)
    }

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

Другие вопросы по тегам