web-dev-qa-db-ja.com

AndroidのPdfRendererクラスは低品質の画像を生成します

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リーダーの大きな違いです。

enter image description hereenter image description here

17

ARGB_8888`は色品質専用ですが、印刷/表示品質は解像度(画面に表示するときの1インチあたりのドット数)に関連しています。

たとえば、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解像度は72DPIです。 この投稿

42
Eugene

私は少し遅れています。ビットマップが大きくなり、レンダリングできなかったため、マークされた回答は役に立ちませんでした。私はまったく同じ問題を抱えていたので元の投稿を見つけました、多分この答えは私の状況で他の人を助けるでしょう。

比率を維持しながら、ビットマップをスケーリングするための適切な解決策があるかどうかを調べました。私はこのサイトに出くわしました:

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

本当に複雑なことではありません。追加のコード行は2行だけ必要でした。

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

サイトが示唆しているのと同様のhelper/utilクラスを追加しました(したがって、実際には2行以上です;))。高さはから来ます

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

スケーリングは、デバイスの高さを元のビットマップの高さで除算して係数を取得し、それを元のビットマップの幅と乗算してスケーリングされた幅を求めます。

これは私のNexus5で完全に機能します。複数のデバイスでこれをテストすることはできませんでしたが、固溶体のようです。

6
stianak

PdfRendererと同様に、ImageViewにPDFページを表示します。保存するためにいくつかの計算を追加して、ImageViewの最大サイズのビットマップを作成するのが最も簡単です。 PDFの比率。PDFは通常印刷用に作成されているため、常に画面よりも高解像度であるため、ピクセル化された画像を取得するリスクはありません。ImageViewmeasuredWidthmeasuredHeightが割り当てられている場合は、コードで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)
    }
1
javaxian

次のことを試すことができます このサンプルPDFViewerクラスを使用します。使用したことがないため、品質についてはわかりませんが、それでも試してみてください:)

0