Growing PDF File Size

In some cases, you might experience a large increase in PDF file size when saving documents. This happens especially when using image annotations with large images and triggering a save of a document often.

This increase in file size is due to incremental saving, which PSPDFKit uses by default if saving is not configured in another way. Incremental saving always appends changes to the end of a document and never deletes anything. Incremental saving is used by default since it’s faster than rewriting an entire document, and usually, the file size increase is almost unnoticeable. As a result, it could be that the data of an image annotation is written and stored in a PDF multiple times.

Rewrite a Document When Saving

To prevent the document file size from growing, you can trigger a non-incremental document save, which will rewrite the entire document instead of appending changes at the end.

This can be done by manually saving the document and setting the incrementalSave property of the DocumentSaveOptions to false as follows:

1
2
3
val incrementalSave = false
val options = DocumentSaveOptions(null, null, incrementalSave, null)
document.saveIfModified(options)
Copy
1
2
3
4
5
final boolean incrementalSave = false;
final DocumentSaveOptions options = DocumentSaveOptions(
    null, null, incrementalSave, null
);
document.saveIfModified(options);

Optimizing Size Even Further

In addition to disabling incremental saving, you can also set the rewriteAndOptimizeFileSize property of DocumentSaveOptions to true. This will cause PSPDFKit to first determine which objects in the PDF are no longer required and then remove them from the final output. While this leads to smaller file sizes, performing this operation is not free and will increase the time it takes to save documents. You can enable this as follows:

Copy
1
2
3
4
val incrementalSave = false
val options = DocumentSaveOptions(null, null, incrementalSave, null)
options.setRewriteAndOptimizeFileSize(true)
document.saveIfModified(options)
Copy
1
2
3
4
5
6
final boolean incrementalSave = false;
final DocumentSaveOptions options = DocumentSaveOptions(
    null, null, incrementalSave, null
);
options.setRewriteAndOptimizeFileSize(true);
document.saveIfModified(options);

Keep in mind that when rewriteAndOptimizeFileSize is enabled, incremental saving will automatically be disabled.

Disabling Incremental Save When Using Auto-Save

The method described above works only when you are saving manually. It is also possible to disable incremental saving when using auto-save with PdfActivity or PdfFragment.

The simplest method is to disable incremental saving via DocumentListener#onDocumentSave():

Copy
1
2
3
4
override fun onDocumentSave(document: PdfDocument, saveOptions: DocumentSaveOptions): Boolean {
    saveOptions.isIncremental = false
    return super.onDocumentSave(document, saveOptions)
}
Copy
1
2
3
4
5
@Override
public boolean onDocumentSave(@NonNull PdfDocument document, @NonNull DocumentSaveOptions saveOptions) {
    saveOptions.setIncremental(false);
    return super.onDocumentSave(document, saveOptions);
}

Incremental saving can be also prevented by using a custom WritableDataProvider with disabled appending:

Copy
1
2
3
4
5
6
7
8
9
10
11
12
// Return `false` from `supportsAppending()` to prevent incremental saving.
val dataProvider = object: ContentResolverDataProvider(uri) {
    override fun supportsAppending(): Boolean {
        return false
    }
}

// Start the activity.
val intent = PdfActivityIntentBuilder.fromDataProvider(context, dataProvider)
    .configuration(configuration)
    .build()
context.startActivity(intent)
Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
// Return `false` from `supportsAppending()` to prevent incremental saving.
DataProvider dataProvider = new ContentResolverDataProvider(uri) {
    @Override
    public boolean supportsAppending() {
        return false;
    }
};

// Start the activity.
Intent intent = PdfActivityIntentBuilder.fromDataProvider(context, dataProvider)
        .configuration(configuration)
        .build();
context.startActivity(intent);