Superposicion sobre PDF existente

Descripcion general

gpdf puede abrir PDFs existentes y superponer nuevo contenido sobre ellos sin modificar los datos originales. Esto utiliza la tecnica de Actualizacion Incremental — los nuevos objetos se agregan despues de los bytes originales del PDF.

Casos de uso comunes:

  • Agregar marcas de agua ("DRAFT", "CONFIDENTIAL")
  • Insertar numeros de pagina
  • Estampar marcas de aprobacion con fechas
  • Agregar encabezados/pies de pagina a documentos existentes

Abrir un PDF existente

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)
}

Puede pasar las mismas opciones que NewDocument — fuentes, fuente predeterminada, etc.:

doc, err := gpdf.Open(pdfBytes,
    gpdf.WithFont("NotoSans", fontData),
    gpdf.WithDefaultFont("NotoSans", 12),
)

Superposicion en una pagina especifica

Use Overlay(pageIndex, fn) para agregar contenido en una pagina especifica (indice basado en 0):

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)),
        )
    })
})

El PageBuilder soporta la misma API que al crear nuevas paginas — AutoRow, Absolute, Row, etc.

Superposicion en cada pagina

Use EachPage(fn) para iterar sobre todas las paginas:

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)))
})

Guardar el resultado

result, err := doc.Save()
if err != nil {
    log.Fatal(err)
}
os.WriteFile("output.pdf", result, 0644)

El contenido original del PDF se conserva — Save() agrega los datos de superposicion despues de los bytes originales.

Ejemplo completo: Marca de agua + Numeros de pagina

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)

Referencia de API

MetodoDescripcion
gpdf.Open(data, opts...)Abrir un PDF existente para modificacion
doc.PageCount()Obtener el numero de paginas
doc.Overlay(pageIndex, fn)Agregar contenido en una pagina especifica (basado en 0)
doc.EachPage(fn)Agregar contenido en cada pagina
doc.Save()Devolver los bytes del PDF modificado

Siguientes pasos