This HTML page is not optimized for LLM or AI agent consumption. Fetch the Markdown version instead: /guides/android/features/rendering-pdf-pages.md — it contains the complete documentation content in clean, structured Markdown without any CSS, JavaScript, or navigation noise. Render PDF pages on Android | Nutrient SDK

Use Nutrient and PdfDocument to render PDF pages into Bitmap(opens in a new tab) objects for custom app views.

Initializing Nutrient

Initialize Nutrient before loading or rendering a document. By default, Nutrient initializes at app startup using the license key in AndroidManifest.xml. For details and manual initialization, refer to the initializing Nutrient guide.

Loading a document

PdfDocumentLoader loads documents from a Uri(opens in a new tab) or DataProvider. For supported sources, refer to the PdfActivity guide.

The following example loads a PDF from the app’s assets:

val document : PdfDocument
try {
// Use this `Uri` format to access files inside your app's assets.
val documentUri = Uri.parse("file:///android_asset/shopping-center-plan.pdf")
// This synchronously opens the document. To keep your app UI responsive, you should do this call
// on a background thread, or use the asynchronous version of this method instead.
document = PdfDocumentLoader.openDocument(context, documentUri)
} catch (e : IOException) {
handleDocumentLoadingError(e)
return
}

Use the loaded PdfDocument to render its pages.

Rendering pages

PdfDocument provides #renderPageToBitmap for synchronous rendering and #renderPageToBitmapAsync for asynchronous rendering.

Synchronous rendering

Use #renderPageToBitmap to render a page into a Bitmap(opens in a new tab) synchronously. These methods block until rendering completes, so call them only on a background thread.

Calculate bitmap dimensions from the original PageSize in PDF points to preserve the page’s aspect ratio:

val pageIndex = 0
// Page size is in PDF points (not pixels).
val pageSize : Size = document.getPageSize(pageIndex)
// We define a target width for the resulting bitmap and use it to calculate the final height.
val width = 2048
val height = (pageSize.height * (width / pageSize.width)).toInt()
// This will render the first page uniformly into a bitmap with a width of 2,048 pixels.
val pageBitmap : Bitmap = document.renderPageToBitmap(context, pageIndex, width, height)

Asynchronous rendering

Use #renderPageToBitmapAsync to render without blocking. It returns an RxJava Single<Bitmap>(opens in a new tab) that emits the bitmap when rendering completes.

Rendering runs on a background thread by default, so you can call this method from the main thread:

// Render the page on a background thread and return the resulting bitmap on the main thread.
document.renderPageToBitmapAsync(context, pageIndex, width, height)
.observeOn(AndroidSchedulers.mainThread())
.subscribe { bitmap ->
// Your code can now use the bitmap.
updateUserInterface(bitmap)
}

Providing a render configuration

Both rendering methods accept PageRenderConfiguration. Create it with Builder to configure these options:

  • Control memory and disk caching with cache, or only disk caching with diskCache.
  • Render a specific region, such as the upper half of a page.
  • Reuse a bitmap with reuseBitmap to reduce memory allocation.
  • Set background color, grayscale, sepia, or color inversion.
  • Add overlays, such as watermarks, with renderedDrawables.

For overlays, refer to the drawable API guide. The following example renders in grayscale:

val renderConfig = PageRenderConfiguration.Builder()
.toGrayscale(true)
.build()
val grayscaleBitmap : Bitmap = document.renderPageToBitmap(context, pageIndex, width, height, renderConfig)

Rendering a specific part of a page

Use PageRenderConfiguration.Builder#region() to render part of a page.

The following example renders the currently visible region:

// You can get all visible pages from `pdfFragment.visiblePages`.
val somePageIndex = ...
// In order to render just a part of the page, you first need the visible rect.
val currentVisibleRect = RectF()
// This saves the visible rect in PDF coordinates to `currentVisibleRect`.
pdfFragment.getVisiblePdfRect(currentVisibleRect, somePageIndex)
// Define a desired width for the bitmap in pixels.
val bitmapWidth = 2000
// Now calculate the height, keeping the aspect ratio of the bitmap as the visible area.
val ratio = bitmapWidth / currentVisibleRect.width()
// Invert the height so it's not negative (in PDF, the rect top has a higher value than the bottom).
val bitmapHeight = (-currentVisibleRect.height() * ratio).toInt()
// Calculate the size of the full page for the desired region bitmap size.
val pageSizeInPdfPoints = document.getPageSize(somePageIndex)
val fullPageWidth = (pageSizeInPdfPoints.width * ratio).toInt()
val fullPageHeight = (pageSizeInPdfPoints.height * ratio).toInt()
// Now we need to get region coordinates in relation to the full page.
val x = (currentVisibleRect.left * ratio).toInt()
val y = ((pageSizeInPdfPoints.height - currentVisibleRect.top) * ratio).toInt()
// Offsets define the movement of the full page, so we move the page region in the top/left direction
// by x and y and then capture it.
val renderConfiguration = PageRenderConfiguration.Builder()
.region(-x, -y, fullPageWidth, fullPageHeight)
.build()
// Captures the region and renders it to the bitmap.
val regionBitmap = document.renderPageToBitmap(context, somePageIndex, bitmapWidth, bitmapHeight, renderConfiguration)