---
title: "Rendering annotations on Android | Nutrient SDK"
canonical_url: "https://www.nutrient.io/guides/android/annotations/rendering-annotations/"
md_url: "https://www.nutrient.io/guides/android/annotations/rendering-annotations.md"
last_updated: "2026-05-21T20:35:00.929Z"
description: "Render annotations from single objects into Bitmap instances using Nutrient SDK. Load documents efficiently with PdfDocumentLoader, enhancing your Android app’s functionality."
---

# Rendering annotations on Android

If you need to render single [`annotation`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.annotations/-annotation/index.html) objects into [`Bitmap`](http://developer.android.com/reference/android/graphics/Bitmap.html) instances, Nutrient offers several options for doing this. This article serves as a step-by-step guide to get you started quickly.

Before loading a document and rendering its annotations, you have to initialize Nutrient by providing your license. Make sure to follow the steps in our [integrating Nutrient](https://www.nutrient.io/sdk/android/getting-started.md) guide before continuing with this guide, in order to have Nutrient fully initialized.

---

## Loading a document

The first step in rendering annotations of a document is to load the document into memory. The [`PdfDocumentLoader`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.document/-pdf-document-loader/index.html) class offers a variety of static methods for doing this. The following example loads a PDF document from the app’s assets using [`PdfDocumentLoader.openDocument()`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.document/-pdf-document-loader/open-document.html) and a `file:///android_asset` URI. The complete list of available document sources and ways to load them is outlined in our guide about [using an activity](https://www.nutrient.io/guides/android/basics/using-activity.md):

### KOTLIN

```kotlin

// 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, either
// don't run this on the main thread, or use `openDocumentAsync()` instead.
val document: PdfDocument = PdfDocumentLoader.openDocument(context, documentUri)

```

### JAVA

```java

// Use this `Uri` format to access files inside your app's assets.
final Uri documentUri = Uri.parse("file:///android_asset/shopping-center-plan.pdf");

// This synchronously opens the document. To keep your app UI responsive, either
// don't run this on the main thread, or use `openDocumentAsync()` instead.
final PdfDocument document = PdfDocumentLoader.openDocument(context, documentUri);

```

The synchronous [`PdfDocumentLoader.openDocument()`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.document/-pdf-document-loader/open-document.html) method used in this example will throw an exception if there is an error while loading the document. You should wrap the call into `try/catch` to handle any errors properly.

## Retrieving annotations

To retrieve the annotations of your loaded [`PdfDocument`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.document/-pdf-document/index.html) instance, get a reference of your document’s [`AnnotationProvider`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.annotations/-annotation-provider/index.html) by calling [`document.getAnnotationProvider()`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.document/-pdf-document/get-annotation-provider.html). You can then query annotations by page number or annotation type:

### KOTLIN

```kotlin

// Retrieves all ink annotations of the document.
val inkAnnotations = document.getAnnotationProvider().getAllAnnotationsOfType(EnumSet.of(AnnotationType.INK))

```

### JAVA

```java

// Retrieves all ink annotations of the document.
final List<Annotation> inkAnnotations = document.getAnnotationProvider().getAllAnnotationsOfType(EnumSet.of(AnnotationType.INK));

```

If you want to retrieve all annotations of your document at once, you can call [`getAllAnnotationsOfType()`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.annotations/-annotation-provider/get-all-annotations-of-type.html) using [`AnnotationProvider#ALL_ANNOTATION_TYPES`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.annotations/-annotation-provider/-a-l-l_-a-n-n-o-t-a-t-i-o-n_-t-y-p-e-s.html).

## Rendering annotations

The rendering of annotations can be performed synchronously or asynchronously using the [`renderToBitmap()`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.annotations/-annotation/render-to-bitmap.html) and [`renderToBitmapAsync()`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.annotations/-annotation/render-to-bitmap-async.html) methods of [`Annotation`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.annotations/-annotation/index.html), respectively.

### Preparing a Bitmap

You first need to create a target [`Bitmap`](http://developer.android.com/reference/android/graphics/Bitmap.html) instance, which is usually done using [`Bitmap.createBitmap()`](https://developer.android.com/reference/android/graphics/Bitmap.html#createBitmap(int,%20int,%20android.graphics.Bitmap.Config)). Since annotations can have transparent regions as well, it makes sense to use a bitmap format that supports this — [`Bitmap.Config.ARGB_8888`](https://developer.android.com/reference/android/graphics/Bitmap.Config.html#ARGB_8888) is a good choice:

### KOTLIN

```kotlin

// Create a bitmap with an alpha channel so that transparent parts
// of the annotation are properly displayed.
val bitmap = Bitmap.createBitmap(
    bitmapWidth,
    bitmapHeight,
    Bitmap.Config.ARGB_8888)

```

### JAVA

```java

// Create a bitmap with an alpha channel so that transparent parts
// of the annotation are properly displayed.
final Bitmap bitmap = Bitmap.createBitmap(
    bitmapWidth,
    bitmapHeight,
    Bitmap.Config.ARGB_8888);

```

While rendering, the annotation will be stretched to fill the entire bitmap area. If you want to maintain the aspect ratio of the annotation, you need to create a bitmap with the same aspect ratio as the annotation.

### Calculating the Bitmap size

You can calculate the [`Bitmap`](http://developer.android.com/reference/android/graphics/Bitmap.html) size from the annotation size stored within the bounding box of your annotation. To retrieve the bounding box, use [`annotation.getBoundingBox()`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.annotations/-annotation/get-bounding-box.html):

### KOTLIN

```kotlin

// The annotation has a size, which can be calculated from its bounding box.
val annotationWidth = annotation.boundingBox.width()
val annotationHeight = -annotation.boundingBox.height()

// Create a bitmap with a width of 300 pixels. The height of the bitmap is derived
// by proportionally fitting the annotation into the width of the bitmap.
val bitmapWidth = 300
val heightFactor = bitmapWidth / annotationWidth
val bitmapHeight = (annotationHeight * heightFactor).toInt()

```

### JAVA

```java

// The annotation has a size, which can be calculated from its bounding box.
final float annotationWidth = annotation.getBoundingBox().width();
final float annotationHeight = -annotation.getBoundingBox().height();

// Create a bitmap with a width of 300 pixels. The height of the bitmap is derived
// by proportionally fitting the annotation into the width of the bitmap.
final int bitmapWidth = 300;
final float heightFactor = bitmapWidth / annotationWidth;
final int bitmapHeight = (int) (annotationHeight * heightFactor);

```

The bounding box holds [PDF coordinates](https://www.nutrient.io/guides/android/faq/coordinate-spaces.md), which, unlike Android’s coordinates, are vertically flipped. As such, the returned [`height()`](https://developer.android.com/reference/android/graphics/RectF.html#height()) is negative and has to be inverted.

### Synchronous rendering

To synchronously render an annotation into a [`Bitmap`](http://developer.android.com/reference/android/graphics/Bitmap.html) instance, call [`renderToBitmap()`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.annotations/-annotation/render-to-bitmap.html) on your annotation, passing in the already prepared [`Bitmap`](http://developer.android.com/reference/android/graphics/Bitmap.html) instance:

### KOTLIN

```kotlin

// This is the bitmap you already prepared (see explanation above).
annotation.renderToBitmap(bitmap)

```

### JAVA

```java

// This is the bitmap you already prepared (see explanation above).
annotation.renderToBitmap(bitmap);

```

> **⚠️ Warning:** When calling [`annotation.renderToBitmap()`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.annotations/-annotation/render-to-bitmap.html), the method will block until rendering has finished, so don’t use it on your main thread! Instead, use asynchronous rendering.

### Asynchronous rendering

In most instances, it’s better to render an annotation asynchronously to ensure you do not block the current thread. This can be done by using [`renderToBitmapAsync()`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.annotations/-annotation/render-to-bitmap-async.html), which can also be used on the main thread. The method returns [`Single<Bitmap>`](http://reactivex.io/RxJava/2.x/javadoc/io/reactivex/Single.html), which will emit the [`Bitmap`](http://developer.android.com/reference/android/graphics/Bitmap.html) once rendering is done:

### KOTLIN

```kotlin

val annotationRendering = annotation.renderToBitmapAsync(bitmap).subscribe { bitmap, throwable ->
        // This will be called with either your bitmap
        // or a throwable (if there was an error while rendering).
    }

// If you ever need to cancel the async render operation, use this.
annotationRendering.dispose()

```

### JAVA

```java

Disposable annotationRendering = annotation.renderToBitmapAsync(bitmap).subscribe((bitmap, throwable) -> {
        // This will be called with either your bitmap
        // or a throwable (if there was an error while rendering).
    });

// If you ever need to cancel the async render operation, use this.
annotationRendering.dispose();

```

Rendering will only start once you call [`subscribe()`](http://reactivex.io/RxJava/2.x/javadoc/io/reactivex/Single.html#subscribe--) on [`Single<Bitmap>`](http://reactivex.io/RxJava/2.x/javadoc/io/reactivex/Single.html). Since rendering is asynchronous, you can cancel it at any time — for example, by calling [`dispose()`](http://reactivex.io/RxJava/2.x/javadoc/io/reactivex/disposables/Disposable.html#dispose--) on the [`Disposable`](http://reactivex.io/RxJava/2.x/javadoc/io/reactivex/disposables/Disposable.html) that is returned by [`subscribe()`](http://reactivex.io/RxJava/2.x/javadoc/io/reactivex/Single.html#subscribe--).

### Providing an annotation render configuration

Both synchronous and asynchronous render methods allow you to specify an [`AnnotationRenderConfiguration`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.configuration.rendering/-annotation-render-configuration/index.html) object for defining render options. You can create the configuration using its [`Builder`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.configuration.rendering/-annotation-render-configuration/-builder/index.html) class:

### KOTLIN

```kotlin

val config = AnnotationRenderConfiguration.Builder().toGrayscale(true).build()

// Renders the annotation to the bitmap in grayscale.
annotation.renderToBitmap(bitmap, config)

```

### JAVA

```java

final AnnotationRenderConfiguration config = new AnnotationRenderConfiguration.Builder().toGrayscale(true).build();

// Renders the annotation to the bitmap in grayscale.
annotation.renderToBitmap(bitmap, config);

```

#### Available render options

It is possible to specify several different render configuration options via the [`Builder`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.configuration.rendering/-annotation-render-configuration/-builder/index.html), including:

- Inversion of the annotation colors using [`invertColors()`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.configuration.rendering/-annotation-render-configuration/-builder/invert-colors.html).

- Grayscale rendering using [`toGrayscale()`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.configuration.rendering/-annotation-render-configuration/-builder/to-grayscale.html).

- Form field highlight color, color of selected form items, and the border color for required form fields using [`formHighlightColor()`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.configuration.rendering/-annotation-render-configuration/-builder/form-highlight-color.html), [`formItemHighlightColor()`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.configuration.rendering/-annotation-render-configuration/-builder/form-item-highlight-color.html), and [`formRequiredFieldBorderColor()`](https://www.nutrient.io/api/android/nutrient/com.pspdfkit.configuration.rendering/-annotation-render-configuration/-builder/form-required-field-border-color.html), respectively.
---

## Related pages

- [Customize the rendering resolution in our Android viewer](/guides/android/features/low-res-render-api.md)
- [Render PDF forms on Android](/guides/android/viewer/rendering/pdf-forms.md)
- [Coordinate space conversion](/guides/android/faq/coordinate-spaces.md)
- [Drawing content above displayed documents](/guides/android/features/drawable-api.md)
- [PDF renderer library for Android](/guides/android/features/rendering-pdf-pages.md)
- [Customize PDF fonts for Android applications](/guides/android/features/custom-fonts.md)

