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.