From 463eeabc5f7a141b38cbfb2daf4c67b977a8305d Mon Sep 17 00:00:00 2001 From: shipeasy-ai Date: Sat, 20 Jun 2026 21:53:36 -0400 Subject: [PATCH] perf(templates): raise PDF preview render quality Page/preview images rasterized at 1400px (~165 DPI) and palette-quantized to as few as 4-256 colours read as a blurry, banded scan in the builder and preview. Raise the default render width to 2200px (~260 DPI, override via PAGE_MAX_WIDTH) and write PDF pages as truecolour PNG instead of a quantized palette. Larger cached blobs, but crisp text and logos. Co-Authored-By: Claude Opus 4.8 (1M context) --- lib/templates/process_document.rb | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/lib/templates/process_document.rb b/lib/templates/process_document.rb index af4e1697..eb3588dd 100644 --- a/lib/templates/process_document.rb +++ b/lib/templates/process_document.rb @@ -12,7 +12,11 @@ module Templates CONCURRENCY = 2 Q = 95 JPEG_Q = ENV.fetch('PAGE_QUALITY', '35').to_i - MAX_WIDTH = 1400 + # Width (px) every page/preview image is rasterized to. US-Letter at 1400px + # is only ~165 DPI, which reads as a blurry scan in the builder/preview; + # 2200px is ~260 DPI. Env-overridable (`PAGE_MAX_WIDTH`) so storage/CPU can + # be dialed back per environment. + MAX_WIDTH = ENV.fetch('PAGE_MAX_WIDTH', '2200').to_i MAX_NUMBER_OF_PAGES_PROCESSED = 15 MAX_FLATTEN_FILE_SIZE = 20.megabytes GENERATE_PREVIEW_SIZE_LIMIT = 50.megabytes @@ -140,10 +144,12 @@ module Templates data = if format == FORMAT - bitdepth = 2**page.stats.to_a[1..3].pluck(2).uniq.size - - page.write_to_buffer(format, compression: 6, filter: 0, bitdepth:, - palette: true, Q: Q, dither: 0) + # Full-colour PNG. The old palette path quantized each page to as few + # as 4–256 colours, which bands anti-aliased text and any colour logo + # — the second cause (with the low render width) of the "low quality + # image" look. Truecolour keeps edges crisp at the cost of larger + # blobs, acceptable for the handful of pages a template has. + page.write_to_buffer(format, compression: 6, filter: 0) else page.write_to_buffer(format, interlace: true, Q: JPEG_Q) end