Android's PdfRenderer class produces low quality images

ARGB_8888` is for color quality only but the printing/displaying quality is related to the resolution (how much dots per inch you have when displaying on screen).

For example, if you have 400 DPI screen (400 Dots Per Inch) and want to display PDF with this quality then you should render the bitmap via Bitmap.createBitmap() that takes pixels as its sizes:

Bitmap bitmap = Bitmap.createBitmap(
    getResources().getDisplayMetrics().densityDpi * mCurrentPage.getWidth() / 72,                        
    getResources().getDisplayMetrics().densityDpi * mCurrentPage.getHeight() / 72,
    Bitmap.Config.ARGB_8888
);

where:

  1. getResources().getDisplayMetrics().densityDpi is the target DPI resolution
  2. mCurrentPage.getWidth() returns width in Postscript points, where each pt is 1/72 inch.
  3. 72 (DPI) is the default PDF resolution.

Hence, diving #2 by 72 we get inches and multiplying by DPI we get pixels. In other words to match the quality of the printing device of the display you should increase the size of the image rendered as default PDF resolution is 72 DPI. Please also check this post?


I am a bit late. The answer marked did not help me, because the bitmap got to big, and thus could not be rendered. I found the original post because I had the exact same problem, maybe this answer will help others in my situation.

I searched around to see if anyone had a neat solution to scaling the bitmap, while keeping the ratio. I came across this site:

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

It is not complicated stuff, really. I only needed two additional lines of code:

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

I added similar helper/util classes as the site suggests(so in practice, it is more than two lines ;) ). The height comes from

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

The scaling simply divides the device height with the original bitmap height to get a factor, which is in turn multiplied with the original bitmap width to find the scaled width.

This works perfectly on my Nexus 5. I have not been able to test this on multiple devices, but it seems like a solid solution.