Hi McNeel,
I’m printing a drawing with a lot of transparent hatches on top of a raster image.
7 pages turn into a 120Mb file.
I asked an LLM why it was so heavy and the reply below reveals that theres an additional transparency options object added to each triangle of my hatches(!)
Found it, and it's gloriously stupid. Your 124 MB PDF contains 961,334 objects — 961,242 of which are graphics-state
dictionaries. There are exactly 4 unique ones.
The byte budget
┌──────────────────────────────────────────────────────────┬─────────┬───────┐
│ What │ Size │ Share │
├──────────────────────────────────────────────────────────┼─────────┼───────┤
│ /ExtGState objects (961,242 of them, 71 bytes each) │ 65.9 MB │ 53% │
├──────────────────────────────────────────────────────────┼─────────┼───────┤
│ /Page dicts — almost entirely the name→ref map for those │ 21.9 MB │ 18% │
├──────────────────────────────────────────────────────────┼─────────┼───────┤
│ xref table (961,335 rows × 20 bytes) │ 19.2 MB │ 15% │
├──────────────────────────────────────────────────────────┼─────────┼───────┤
│ Actual page content streams (compressed) │ 15.5 MB │ 12% │
├──────────────────────────────────────────────────────────┼─────────┼───────┤
│ The 16 JPEGs (1081×1599, legends/logos) │ 2.1 MB │ 2% │
└──────────────────────────────────────────────────────────┴─────────┴───────┘
960,772 of those objects are byte-for-byte identical:
<</Type /ExtGState/CA 0.90196078 /ca 0.90196078 >>
0.90196078 = 230/255, i.e. an alpha of 230 — a 10 %-transparent fill.
The mechanism
The details print the sunlight-hours mesh as vector, so Rhino explodes it into ~113,000 individually filled triangles
per page. Each one looks like this:
q /GSaZfsU56516 gs /DeviceRGB cs 0.784 0.313 0.274 sc
293.4 328.4 m ... l ... h f
Q
Because the fill is semi-transparent, Rhino's PDF writer (Xfinium — its fingerprints are all over the catalog) emits a
brand-new ExtGState object for every single triangle instead of reusing one. So each triangle costs an object + a
resource-map entry + an xref row on top of its actual geometry. ~86 MB of the file is one repeated "90 % opaque"
instruction, written out a million times.
The LLM also ‘merged’ those entries in my pdf cutting file size to 15Mb (-90%) with same print output. I’m suggesting that rhino does that automatically.



