Skip to content
How to reduce the size of generated PDF reports

How to reduce the size of generated PDF reports

Attach an optimizer to the creator before writing. The chain runs during Write, over the assembled object list.

c.SetOptimizer(optimize.New(optimize.Options{
    CombineDuplicateDirectObjects:   true,
    CombineIdenticalIndirectObjects: true,
    CombineDuplicateStreams:         true,
    CompressStreams:                 true,
    UseObjectStreams:                true,
    SubsetFonts:                     true,
    CleanUnusedResources:            true,
}))

return c.WriteToFile(outputPath)

Every option is off by default and each one you turn on appends a pass. The seven above are lossless. ImageQuality and ImageUpperPPI are the two that change pixels, and CleanContentstream leaves rendering alone but strips marked-content operators, which breaks tagged output and with it PDF/UA and PDF/A.

Creator.SetPdfWriterAccessFunc gets you the same result through the writer, and is what you need when you are also encrypting or setting something else on it. Note that the hook runs after the creator has installed its own optimizer, so calling SetOptimizer on the writer inside the hook replaces anything set with c.SetOptimizer rather than adding to it.

In a report the weight is usually fonts. SubsetFonts rewrites embedded TrueType programs to only the glyphs the document uses, which matters most with a composite font: a CJK face embedded whole is well over a megabyte. c.EnableFontSubsetting(font) does the same job for a specific font you loaded yourself, and is the more direct call when you know which one is large.

A pass that fails does not fail the write. Chain.Optimize logs at debug level and carries on with the objects it had, so a document that optimizes badly still comes out correct and simply larger, with nothing returned to say so.

Every option, what each pass skips, and the cost of running it are in the PDF optimization guides.

Last updated on