Remove Image Watermark
PdfPage.RemoveWatermarkImage deletes a watermark image from a page: it drops the
entry from the page’s XObject resources, cuts the operators that drew it out of the
content stream, and strips any watermark annotations. There is no document-level
call, so you iterate the pages yourself.
Which name to pass
| Argument | What gets removed |
|---|---|
"" | Any XObject marked as an Adobe watermark, plus all watermark annotations. |
"Img1" | The XObject with that exact name, plus all watermark annotations. |
The empty-string form works on watermarks applied by Adobe products, which tag the
XObject with an ADBE_CompoundType piece-info entry whose Private value is
Watermark. Nothing else sets that tag, so a watermark added by UniPDF or by another
library will not be found this way.
For everything else you need the XObject’s name. Get it by listing the page’s images; the list images guide covers that, and the name it prints for each XObject image is exactly what goes here.
Doing it
for i := 0; i < numPages; i++ {
page, err := pdfReader.GetPage(i + 1)
if err != nil {
return err
}
// "" for Adobe-applied watermarks, otherwise the XObject name.
if err := page.RemoveWatermarkImage("Img1"); err != nil {
return err
}
}
pdfWriter, err := pdfReader.ToWriter(nil)
if err != nil {
return err
}
return pdfWriter.WriteToFile(outputPath)Names are scoped to a page’s resource dictionary, so the same watermark can be /Img1
on one page and /Im3 on another. Do not assume one name covers the document; list
the images per page if the input is not something you produced yourself.
Annotation removal is unconditional. Every call strips all Watermark subtype
annotations from the page regardless of the name argument, so a watermark that exists
only as an annotation is removed by any call, including one with a name that matches
nothing.
Limitations
The method returns nil whether or not it removed anything. A misspelled name, a
name from the wrong page, or a document with no watermark at all all look like
success. Verify by listing the page’s images afterwards.
Cutting the drawing operators out is done by string editing, not by parsing: for the
content stream containing the name, everything between the nearest preceding q and
the following Q is deleted. That is exactly right for a watermark added by
AddWatermarkImage, which emits its own q ... Q block. Where the XObject is invoked
inside a larger q ... Q group, other operators in that group go with it.
Only the first content stream containing the name is edited per stream object, so an
XObject drawn more than once inside a single stream may leave a Do behind that now
refers to a removed resource. Viewers generally ignore it, but a strict validator may
not.
Removing the resource entry does not shrink the file on its own. The image stream becomes unreferenced; run the optimizer if size matters.
Run the example
The example walks every page of the input, removes the XObject named Img1, and
writes the result through a PdfWriter. It is all in main. Change the name argument
to match the document you’re working on.
git clone https://github.com/unidoc/unipdf-examples.git
cd unipdf-examples/watermarks
go run pdf_remove_watermark_image.go input.pdf output.pdfIf this is your first time using UniPDF, follow the getting started guide to create an API key and set up your development environment.