Add and insert images into PDFs on Android

Nutrient Android SDK lets you add an image as a new page to a document using the Processor API or the Document Editor API. With this functionality, you can extend your existing PDF documents by adding photos, bitmap graphics, or even images of scanned documents.

If you’d instead like to add an image to an existing PDF page in the form of an annotation, see the custom stamps guide.

Using the Processor API

To add a new image-based page using the PdfProcessor API, load your document and add a new page from an image via a PdfProcessorTask instance. Processor is a great choice if you want to build an automated document processing operation:

val document: PdfDocument = ...

// Load an image from assets into a `Bitmap` object.
val bitmap = BitmapFactory.decodeStream(assets.open("image.png"))

// Create a task with which to add an image-based page to the document.
val task = PdfProcessorTask.fromDocument(document)

// Add an image-based page to the processor task and position the bitmap in the center of the page.
task.addNewPage(
    NewPage.emptyPage(NewPage.PAGE_SIZE_A0)
        .withPageItem(PageImage(bitmap, PagePosition.CENTER))
        .build(), document.pageCount
)

// Save it to a new document.
val outputFile = File(context.getFilesDir(), "outputDocument.pdf")
val disposable = PdfProcessor.processDocumentAsync(task, outputFile).subscribe()
PdfDocument document = ...

// Load an image from assets into a `Bitmap` object.
final Bitmap bitmap = BitmapFactory.decodeStream(getAssets().open("image.png"));

// Create a task with which to add an image-based page to the document.
final PdfProcessorTask task = PdfProcessorTask.fromDocument(document);

// Add an image-based page to the processor task and position the bitmap in the center of the page.
task.addNewPage(
    NewPage.emptyPage(NewPage.PAGE_SIZE_A0)
        .withPageItem(new PageImage(bitmap, PagePosition.CENTER))
        .build(), document.getPageCount());

// Save it to a new document.
final File outputFile = new File(context.getFilesDir(), "outputDocument.pdf");
final Disposable disposable = PdfProcessor.processDocumentAsync(task, outputFile).subscribe();
Information

Adding new pages with the Processor API is only available if you have the Document Editor component enabled in your license.

Using the Document Editor API

Image-based pages can also be added using the Document Editor API. The Document Editor is particularly useful if you want to build a general-purpose UI for manipulating pages, as it provides helpers that make building a document editing UI easy.

Similar to how it works with the Processor API, here’s how you can use the Document Editor to add a new page configured to show an image:

val document: PdfDocument = ...

// Use the `PdfDocumentEditorFactory` to create a `PdfDocumentEditor`.
val documentEditor = PdfDocumentEditorFactory.createForDocument(document)

// Set up the output file location.
val outputFile = File(filesDir, "outputDocument.pdf")

// Load an image from assets into a `Bitmap` object.
val bitmap = BitmapFactory.decodeStream(assets.open("image.png"))

// Create an image-based page and position the bitmap in the center of the page.
NewPage.emptyPage(NewPage.PAGE_SIZE_A0)
        .withPageItem(PageImage(bitmap, PagePosition.CENTER))
        .build()

// Add the page to the end of the document and save to the output document.
val disposable: Disposable = documentEditor.addPage(document.getPageCount(), page)
    .flatMapCompletable { documentEditor.saveDocument(context, outputFile.outputStream(), null) }
    // Use `subscribeOn` to put `saveDocument` on a background thread, as it can be slow.
    .subscribeOn(Schedulers.io())
    // Make sure the resulting document rendering goes back on the main thread.
    .observeOn(AndroidSchedulers.mainThread())
    // Display the saved document in a new activity with the following action on `subscribe`.
    .subscribe { PdfActivity.showDocument(context, Uri.fromFile(outputFile), null) }
PdfDocument document = ...

// Use the `PdfDocumentEditorFactory` to create a `PdfDocumentEditor`.
final PdfDocumentEditor documentEditor =
    PdfDocumentEditorFactory.createForDocument(document);

// Set up the output file location.
final File outputFile = new File(getFilesDir(), "outputDocument.pdf");

// Load an image from assets into a `Bitmap` object.
final Bitmap bitmap = BitmapFactory.decodeStream(getAssets().open("image.png"));

// Create an image-based page and position the bitmap in the center of the page.
final NewPage page = NewPage.emptyPage(NewPage.PAGE_SIZE_A0)
        .withPageItem(new PageImage(bitmap, PagePosition.CENTER))
        .build();

// Add the page to the end of the document and save to the output document.
final Disposable disposable = documentEditor.addPage(document.getPageCount(), page)
    .flatMapCompletable(saved -> documentEditor.saveDocument(context, new FileOutputStream(outputFile), null))
    // Use `subscribeOn` to put `saveDocument` on a background thread, as it can be slow.
    .subscribeOn(Schedulers.io())
    // Make sure the resulting document rendering goes back on the main thread.
    .observeOn(AndroidSchedulers.mainThread())
    // Display the saved document in a new activity with the following action on `subscribe`.
    .subscribe( () -> { PdfActivity.showDocument(context,
        Uri.fromFile(outputFile), null);
    });

Using the built-in UI

Nutrient Android SDK comes with a prebuilt user interface for document editing that includes an option for adding new image-based pages. To learn more, check out the document editing UI overview.