Skip to content
Add Image to Page

Add Image to Page

Stamping an image onto pages of a document that already exists means reading the pages with model.PdfReader, handing each one to the creator with AddPage, and drawing the image on the pages you want it on. The creator writes the result out, so the pages you do not touch pass through unchanged.

Doing it

c := creator.New()

img, err := c.NewImageFromFile(imagePath)
if err != nil {
    return err
}
img.ScaleToWidth(iwidth)
img.SetPos(xPos, yPos)

// Add every page, draw the image on the one we want.
for i := 0; i < numPages; i++ {
    page, err := pdfReader.GetPage(i + 1)
    if err != nil {
        return err
    }
    if err := c.AddPage(page); err != nil {
        return err
    }
    if i+1 == pageNum {
        if err := c.Draw(img); err != nil {
            return err
        }
    }
}

c.Draw applies to the page most recently added, so the AddPage call has to come first. Both calls are needed even for pages that get no image: skipping AddPage drops the page from the output.

SetPos(x, y) places the image’s upper left corner, measured from the upper left corner of the page, with y growing downward. It also switches the image out of relative positioning, which is what lets the same Image be drawn onto several pages at the same spot.

One creator.Image can be drawn any number of times. The embedded XObject is built on the first draw and reused, so a repeated stamp costs one copy of the image data in the output file rather than one per page.

Choosing an encoder

Leave the encoder alone and UniPDF picks one from the source. A JPEG whose pixel data it can embed as-is gets a DCT encoder and is copied byte for byte; anything else gets an encoder derived from the pixel data, falling back to raw if that inspection fails.

SetEncoder overrides that:

encoder := core.NewDCTEncoder()
encoder.Quality = 80 // 75 by default
img.SetEncoder(encoder)

A DCT encoder is lossy and produces much smaller streams, which is the reason to reach for it on a PNG or GIF source. core.NewFlateEncoder() is lossless and usually much larger.

Setting a DCT encoder on a JPEG source changes nothing, including Quality, because the original JPEG bytes are passed through untouched. To genuinely re-encode a JPEG you have to install a non-DCT encoder. See add images to a PDF for the details of that pass-through and of ICC profile handling.

Limitations

Sources are decoded by Go’s image package with JPEG, PNG and GIF registered. Anything else, TIFF and WebP included, fails at NewImageFromFile.

Scaling is not optional in practice. An image starts out as many points wide as it has pixels, so an unscaled photo is usually many times the size of the page. There is no error for this; the image is drawn off the page edge and clipped by the viewer.

Coordinates are not validated either. A position outside the page box draws normally and is clipped on display.

Run the example

The example takes a page number, a position and a width, and stamps a single image onto that page. addImageToPdf is the whole of it. Passing -1 as the page number applies the image to every page.

git clone https://github.com/unidoc/unipdf-examples.git
cd unipdf-examples/image
go run pdf_add_image_to_page.go input.pdf <page> image.jpg <xpos> <ypos> <width> output.pdf

If this is your first time using UniPDF, follow the getting started guide to create an API key and set up your development environment.

View the full source
Last updated on