Guide
Existing PDF Overlay
Open existing PDFs and add text, images, stamps, and page numbers on top
Overview
gpdf can open existing PDFs and overlay new content on top of them without modifying the original data. This uses the Incremental Update technique — new objects are appended after the original PDF bytes.
Common use cases:
- Adding watermarks ("DRAFT", "CONFIDENTIAL")
- Inserting page numbers
- Stamping approval marks with dates
- Adding headers/footers to existing documents
Opening an Existing PDF
import gpdf "github.com/gpdf-dev/gpdf"
// Read existing PDF bytes (from file, HTTP response, database, etc.)
pdfBytes, _ := os.ReadFile("input.pdf")
doc, err := gpdf.Open(pdfBytes)
if err != nil {
log.Fatal(err)
}
You can pass the same options as NewDocument — fonts, default font, etc.:
doc, err := gpdf.Open(pdfBytes,
gpdf.WithFont("NotoSans", fontData),
gpdf.WithDefaultFont("NotoSans", 12),
)
Overlay on a Single Page
Use Overlay(pageIndex, fn) to add content on a specific page (0-based index):
doc.Overlay(0, func(p *template.PageBuilder) {
p.Absolute(document.Mm(40), document.Mm(120), func(c *template.ColBuilder) {
c.Text("DRAFT",
template.FontSize(72),
template.TextColor(pdf.Gray(0.85)),
)
})
})
The PageBuilder supports the same API as when creating new pages — AutoRow, Absolute, Row, etc.
Overlay on Every Page
Use EachPage(fn) to iterate over all pages:
count, _ := doc.PageCount()
doc.EachPage(func(pageIndex int, p *template.PageBuilder) {
p.Absolute(document.Mm(170), document.Mm(285), func(c *template.ColBuilder) {
c.Text(fmt.Sprintf("%d / %d", pageIndex+1, count),
template.FontSize(10),
template.AlignRight(),
)
}, template.AbsoluteWidth(document.Mm(20)))
})
Saving the Result
result, err := doc.Save()
if err != nil {
log.Fatal(err)
}
os.WriteFile("output.pdf", result, 0644)
The original PDF content is preserved — Save() appends overlay data after the original bytes.
Complete Example: Watermark + Page Numbers
pdfBytes, _ := os.ReadFile("report.pdf")
doc, err := gpdf.Open(pdfBytes)
if err != nil {
log.Fatal(err)
}
count, _ := doc.PageCount()
doc.EachPage(func(i int, p *template.PageBuilder) {
// Watermark
p.Absolute(document.Mm(40), document.Mm(140), func(c *template.ColBuilder) {
c.Text("CONFIDENTIAL",
template.FontSize(60),
template.TextColor(pdf.Color{R: 0.9, G: 0.9, B: 0.9, A: 1, Space: pdf.ColorSpaceRGB}),
)
})
// Page number (bottom-right)
p.Absolute(document.Mm(170), document.Mm(285), func(c *template.ColBuilder) {
c.Text(fmt.Sprintf("%d / %d", i+1, count),
template.FontSize(10),
template.AlignRight(),
)
}, template.AbsoluteWidth(document.Mm(20)))
})
result, _ := doc.Save()
os.WriteFile("report_stamped.pdf", result, 0644)
API Reference
| Method | Description |
|---|---|
gpdf.Open(data, opts...) | Open an existing PDF for modification |
doc.PageCount() | Get the number of pages |
doc.Overlay(pageIndex, fn) | Add content on a specific page (0-based) |
doc.EachPage(fn) | Add content on every page |
doc.Save() | Return the modified PDF bytes |
Next Steps
- Fonts — Embedding fonts, CJK support, and text shaping limitations
- Basic Usage — Creating PDFs from scratch
- Styling — Colors, text decoration, and typography
- API Reference — Full
gpdfpackage reference