1<!DOCTYPE html> 2 3 4<html lang="en"> 5 6 <head> 7 <title>Ghostscript : Optimizing PDFs</title> 8 <link rel="canonical" href="https://ghostscript.com/blog/optimizing-pdfs.html" /> 9 10 <meta name="description" content="Details for optimizing PDFs with Ghostscript"> 11 <meta charset="UTF-8"> 12 <meta name="format-detection" content="telephone=no"> 13 <meta name="msapplication-tap-highlight" content="no"> 14 <meta name="viewport" content="user-scalable=yes, initial-scale=1, width=device-width"> 15 16 <link rel="stylesheet" type="text/css" href="../css/default.css"> 17 <link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:200,200i,300,300i,400,400i,600,600i,700,700i,900,900i" rel="stylesheet"> 18 19 <link rel="preconnect" href="https://fonts.googleapis.com"> 20 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> 21 <link href="https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap" rel="stylesheet"> 22 23 24 <link rel="shortcut icon" href="../images/favicon.svg"> 25 26 <style> 27 28 pre { 29 padding: 10px; 30 background: #ddd; 31 max-width:100%; 32 overflow-x: auto; 33 white-space: pre-wrap; 34 white-space: -moz-pre-wrap; 35 white-space: -pre-wrap; 36 white-space: -o-pre-wrap; 37 word-wrap: break-word; 38 } 39 40 .wrap { 41 width: 100%; 42 display:flex; 43 margin: 0 auto; 44 justify-content:space-between; 45 } 46 47 .wrap .container { 48 width: 45%; 49 margin: 0 auto; 50 } 51 52 :root { 53 --bg: #1e1f24; 54 --panel: #26282f; 55 --code-bg: #15161a; 56 --text: #e7e7ea; 57 --muted: #9a9ca6; 58 --accent: #5ec9a6; 59 --accent-dim: #3a7d68; 60 --border: #34363f; 61 } 62 63 64 .sub { 65 color: var(--muted); 66 font-size: 0.9rem; 67 margin: 0 0 28px; 68 } 69 70 .card { 71 background: var(--panel); 72 border: 1px solid var(--border); 73 color: var(--text); 74 border-radius: 10px; 75 margin-bottom: 22px; 76 overflow: hidden; 77 } 78 79 .card-header { 80 display: flex; 81 justify-content: space-between; 82 align-items: center; 83 padding: 12px 16px; 84 border-bottom: 1px solid var(--border); 85 } 86 87 .card-title { 88 font-size: 0.9rem; 89 font-weight: 600; 90 color: var(--text); 91 } 92 93 .card-desc { 94 font-size: 0.8rem; 95 color: var(--muted); 96 margin: 2px 0 0; 97 } 98 99 .card ul { 100 margin: 0px 0 0 0px; 101 padding: 0; 102 } 103 104 .copy-btn { 105 background: transparent; 106 border: 1px solid var(--border); 107 color: var(--text); 108 font-size: 0.78rem; 109 padding: 6px 12px; 110 border-radius: 6px; 111 cursor: pointer; 112 flex-shrink: 0; 113 transition: border-color 0.15s, color 0.15s; 114 } 115 116 .copy-btn:hover { 117 border-color: var(--accent); 118 color: var(--accent); 119 } 120 121 .copy-btn:focus-visible { 122 outline: 2px solid var(--accent); 123 outline-offset: 2px; 124 } 125 126 .copy-btn.copied { 127 border-color: var(--accent); 128 color: var(--accent); 129 } 130 131 .card pre { 132 margin: 0; 133 padding: 16px; 134 background: var(--code-bg); 135 overflow-x: auto; 136 } 137 138 .card code { 139 font-family: monospace; 140 font-size: 0.83rem; 141 line-height: 1.6; 142 color: var(--text); 143 white-space: pre; 144 } 145 146 @media (prefers-reduced-motion: reduce) { 147 .copy-btn { transition: none; } 148 } 149 150 @media (max-width: 1024px) { 151 .wrap { 152 flex-direction: column; 153 } 154 .wrap .container { 155 width: 100%; 156 margin-bottom: 20px; 157 } 158 } 159 </style> 160 161 162 </head> 163 164 <body data-value="../"> 165 166 <header> 167 <nav id="headerAssets" class="assets"></nav> 168 169 <noscript><code class="standout nojs"></code></noscript> 170 </header> 171 172 <main tabindex="0"> 173 174 <div class="banner" role="heading" aria-level="1"><h1>Optimizing PDFs with Ghostscript</h1></div> 175 176 <div class="outer"> 177 178 <div class="inner"> 179 180 <!--- start page content here --> 181 <article> 182 <div class='body'> 183 <p style="width:100%;text-align: left;">Compressing files inside a Python script or a RAG pipeline? <a href="https://pymupdf.io/compress">Use PyMuPDF</a>.</p> 184 185 186<div class="wrap"> 187 <div class="container"> 188 <h2>Ghostscript PDF Compression</h2> 189 <p class="sub">Click "Copy" then run it in your terminal.</p> 190 191 <div class="card"> 192 <div class="card-header"> 193 <div> 194 <div class="card-title">Standard compression (presets)</div> 195 <p class="card-desc">Good default â swap /ebook for /screen or /printer as needed</p> 196 </div> 197 <button class="copy-btn" data-target="snippet-1">Copy</button> 198 </div> 199 <pre><code id="snippet-1">gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 \ 200 -dPDFSETTINGS=/ebook \ 201 -dNOPAUSE -dQUIET -dBATCH \ 202 -sOutputFile=output.pdf input.pdf</code></pre> 203 </div> 204 </div> 205 <div class="container"> 206 <div class="card"> 207 <div class="card-desc">
208 <span><b style="padding-left:20px;color:#fff;">What each flag does</b></span> 209 <div class="card-header"> 210 <ul> 211 <li><code>-sDEVICE=pdfwrite</code> â tells Ghostscript to render the output as a new PDF (rather than printing, rasterizing, etc.)</li> 212 <li><code>-dCompatibilityLevel=1.4</code> â sets the PDF version for compatibility (1.4 is a safe, widely-supported default)</li> 213 <li><code>-dPDFSETTINGS=/ebook</code> â this is the main lever for compression. It's a preset bundle that controls image downsampling/compression quality. Options, from least to most compression:</li> 214 <ul style="margin-left: 20px;"> 215 <li><code>/screen</code> â low-resolution output, smallest file size</li> 216 <li><code>/ebook</code> â medium-resolution output, good balance</li> 217 <li><code>/printer</code> â high-resolution output, larger file size</li> 218 <li><code>/prepress</code> â high-quality output for printing, largest file size</li> 219 </ul> 220 <li><code>-dNOPAUSE -dQUIET -dBATCH</code> â run non-interactively without prompts and exit when done</li> 221 <li><code>-sOutputFile=</code> â output path (must differ from the input file)</li> 222 </ul> 223 </div> 224 </div> 225 </div> 226 227 228 </div> 229 230</div> 231 232 233
234<script> 235 document.querySelectorAll('.copy-btn').forEach(function (btn) { 236 btn.addEventListener('click', function () { 237 var targetId = btn.getAttribute('data-target'); 238 var codeEl = document.getElementById(targetId); 239 var text = codeEl.textContent; 240 241 navigator.clipboard.writeText(text).then(function () { 242 var original = btn.textContent; 243 btn.textContent = 'Copied'; 244 btn.classList.add('copied'); 245 setTimeout(function () { 246 btn.textContent = original; 247 btn.classList.remove('copied'); 248 }, 1500); 249 }).catch(function () { 250 // Fallback for browsers without clipboard API support 251 var textarea = document.createElement('textarea'); 252 textarea.value = text; 253 document.body.appendChild(textarea); 254 textarea.select(); 255 document.execCommand('copy'); 256 document.body.removeChild(textarea); 257 btn.textContent = 'Copied'; 258 setTimeout(function () { btn.textContent = 'Copy'; }, 1500); 259 }); 260 }); 261 }); 262</script>
262 263 264 <h2 class='author'>By Ken Sharp - Thursday, September 29, 2022</h2><p>There are quite a few âguidesâ or suggestions on the Internet for âoptimizingâ PDF files, and many of them suggest using Ghostscript to perform the task. Confusingly, they often differ in their advice and sometimes are even contradictory, making it hard to find helpful information. This post attempts to document what pdfwrite (and the Ghostscript family of interpreters) can and canât do and why.</p><p>The first problem is that when people say âoptimizeâ they can mean many different things; perhaps to one person, optimize means âmake my file smallerâ while to another, it means âmake it more likely to open in a browserâ. The two different goals mean that the two files might be constructed differently, but both could be described as optimized for the task they are meant to fulfill.</p><p>Letâs start by listing some of the things people can mean when they say âoptimizedâ:</p><ul><li>Fast web view</li><li>Minimise file size</li><li>Conforming to a subset of the PDF specification (e.g., PDF/A)</li><li>Produce a PDF file without errors</li></ul><p>There may be others, but these are the most common, so weâll look at these. Before we begin, though, we need to understand how the pdfwrite device, and the interpreter(s), actually work.</p><p>Because of the way PDF files are constructed, it is possible, up to a point, to treat them as if they are a set of âbuilding blocksâ. Pages, images, and forms can be thought of as a component of the PDF and can be rearranged or reordered. In addition, it is possible to take a content stream (the operations marking a page or making up a Form) and call it from another stream. So, you could create a new content stream for a page; in that stream, you could call the original stream, then perform some other operations. This allows an application to effectively add to a page without changing the original page content. Several PDF applications work like this.</p><p>This isnât how <a href="https://ghostscript.readthedocs.io/en/latest/VectorDevices.html">pdfwrite</a> and Ghostscript work, though many users seem to think it is. With the Ghostscript family, the input interpreter reads the input (which could be a PDF file, a PostScript program, a PCL or XPS page description, or even some kinds of image formats). The interpreter then sends a sequence of marking operations to the graphics library; when rendering, e.g., to the display, that turns the operations into pixels. When the output device is one of the high-level devices, the graphics library sends those operations to the device, turning them back into high-level operations in a potentially different output language. Currently, that can be PDF, PostScript, PCL or XPS.</p><p>The important point to remember is that the output only contains those parts of the input which draw on the page; other metadata is generally lost. The PDF interpreter does make a lot of effort to copy metadata from an input PDF file to the pdfwrite device, so things like hyperlinks, bookmarks and so on will often be preserved, but it is vital to realise that not everything is preserved, and even where the content appears to be the same (because metadata is preserved or the operation draws on the page) the actual commands may not be the same. For example, in PDF syntax, this: 265 266 267 </p> 268 269 <pre><code> 270 <p>0 1 0 rg</p><p>0 0 72 72 re</p><p>f</p> 271 </pre></code> 272 273 <p>fills a rectangle from 0,0 (bottom left corner) width 72, height 72 (1 inch square) with pure green.</p><p>This:</p> 274 275 <pre><code> 276 <p>0 1 0 rg</p><p>0 0 m</p><p>0 72 l</p><p>72 72 l</p><p>72 0 l</p><p>h</p><p>f</p> 277 </pre></code> 278 279 <p>starts from 0,0, creates a line segment to 0,72, then to 72, 72, then to 72,0 and finally closes the path, then fills it with green.</p><p>The two will render identically, but the actual content is quite different. Although this is (obviously) a highly simplified example, it should be clear that there are several ways to achieve a particular appearance in PDF. Most of the time, this doesnât matter, but if your workflow relies in any way on the actual content of a PDF file, then you may find it does not work after being processed through the pdfwrite device, even though it looks exactly the same.</p><p>This will be important in a couple of the sections below.</p><h3>Fast web view</h3><p>Ordinarily, the entire PDF file must be downloaded before it can be opened because the cross-reference table can only be found by looking at the document trailer, which is located at the end of the file.</p><p>Fast Web View (described as Linearized PDF in the specification) is a way to produce a PDF file that allows for the first page (and only the first page) to be drawn before the whole PDF file is available on systems that support it. This isnât well-supported and is of limited value since it only affects the first page. However, if you find the feature useful, you can have the pdfwrite device produce a PDF file that conforms to this part of the specification by using -dFastWebView.</p><p>The caveats above about the file content apply, of course, and you should be aware that this feature requires random access to the <strong>output</strong> file. You cannot use this feature and stream the output to stdout.</p><h3>Produce a PDF file without errors</h3><p>Ghostscriptâs PDF interpreter is very tolerant of errors, and unlike Adobe Acrobat, it will tell you when it finds them rather than silently ignoring them. It seems that several other PDF consumers, including printers, are rather less tolerant of errors in PDF files and will fail to print or otherwise process these files. This is not a criticism of those consumers, the files <strong>are </strong>broken or invalid, but sometimes Ghostscript can produce the expected output, or at least match Acrobat, which many users consider to be the same thing, even when other consumers cannot.</p><p>One solution is to process such files through Ghostscript and the pdfwrite device to produce a âcleanâ or âoptimizedâ PDF file, which is much more likely to work, or at least work the same on all consumers. Indeed, we have been told of some organisations which process <strong>all</strong> their PDF files through Ghostscript and pdfwrite before sending them into their workflow, just to avoid such problems.</p><p>Thereâs no special configuration required for this though users might find the -dPDFSTOPONERROR and -dPDFSTOPONWARNING controls useful, to filter out potentially bad files for further verification.</p><p>For the especially curious, the -dPDFDEBUG control will dump to stdout the PDF content being processed as it goes, which can provide still more details for those skilled in reading raw PDF content. Beware; this has a large performance hit and will scribble lots of more or less incomprehe
279nsible messages to the output!</p><h3>Conforming to a subset of the specification</h3><p>There is already documentation on producing PDF/X-3 and PDF/A files available here:</p><p><a href="https://ghostscript.readthedocs.io/en/gs10.0.0/VectorDevices.html#creating-a-pdf-x-3-document" target="_blank" rel="noopener noreferrer"><span>https://ghostscript.readthedocs.io/en/gs10.0.0/VectorDevices.html#creating-a-pdf-x-3-document</span></a></p><p><a href="https://ghostscript.readthedocs.io/en/gs10.0.0/VectorDevices.html#creating-a-pdf-x-3-document" target="_blank" rel="noopener noreferrer"><span>https://ghostscript.readthedocs.io/en/gs10.0.0/VectorDevices.html#creating-a-pdf-a-document</span></a></p><p>and information on producing ZUGFeRD (Factur-X, EN16931) files here:</p><p><a href="https://ghostscript.com/blog/zugferd.html" target="_blank" rel="noopener noreferrer"><span>https://ghostscript.com/blog/zugferd.html</span></a></p><p>I donât propose to cover these further. We may support other subsets of PDF in the future, and these will be covered in the Ghostscript documentation as well.</p><h3>Minimise file size</h3><p>This is probably the most confusing area of all, and where the various information posted by users can be contradictory.</p><p>The first thing to understand is that there is <strong>no</strong> guarantee that processing a PDF file with Ghostscript and the pdfwrite output device will produce a smaller file. In fact, it may even produce a larger file! As youâll recall from the introduction, the actual operations written to the PDF file may not be the same as the original ones and, in fact, as the example showed, may be more verbose and, therefore larger.</p><p>In addition, at the time of writing, the pdfwrite device does not support either XrefStm (compressed xref tables) or ObjStm (a means of compressing other kinds of objects) in the PDF files it creates. If the original file did use those and used them effectively, it may well be smaller than the pdfwrite output.</p><p>However, in general, these donât save a huge amount of space, and many PDF files donât take advantage of them anyway.</p><p>The other aspect of how pdfwrite works is where we can gain an advantage, sometimes quite significant gains. Recall that we do not write metadata (or at least some kinds of metadata) into the output PDF file, and we rewrite the file completely.</p><p>Quite a few PDF files contain extraneous white space or leading/trailing zeros, and many of them contain genuine metadata which may not be useful to the user.</p><p>The extraneous bytes can be written for several reasons, but one of the most common is the value associated with the /Length key of a stream. Fairly often, the PDF producer doesnât know the length of a compressed stream until after it has been written, so it doesnât know how many bytes to reserve in the PDF file to hold that length.</p><p>Because of the cross-reference table which holds offsets of each object in the PDF file, naive producers often cannot easily change the recorded position in the file of an object after it has been written either. So instead, it writes the Length as a large number of space characters, which it will later partially overwrite with the actual digits defining the length. Of course, this leaves the remaining white space unused. The pdfwrite device doesnât do that, so it can save space there.</p><p>Some applications embed data in the PDF file, which is meaningful to that application but not to anything else. For example, Adobe Illustrator can embed the original Illustrator document in the PDF file. If you then open that PDF file with Illustrator, it will use the saved document rather than trying to interpret the PDF file. Because the pdfwrite device doesnât understand the embedded data, it doesnât copy it, which in the case of Illustrator can lead to quite large savings.</p><p>This is also where problems can arise; letâs take a real file weâve been sent and look inside it. The file has this Page dictionary describing the page:</p><div class="raw-html-embed"> 280<pre><code> 2819 0 obj 282<< 283/ArtBox[0 0.000122 819.212585 1176.378052] 284/BleedBox[0 0.000122 819.212585 1176.378052] 285/Contents 10 0 R 286/CropBox[0 0 819.213013 1176.378052] 287/MediaBox[0 0 819.213013 1176.378052] 288/OneVisionPageColorsInfo<< 289/CreationDate(D:20140328215859+01'00') 290/PageCustomColors<< 291/C=0#20M=0#20Y=0#20K=100[0 0 0 1]>> 292/PageProcessColors[ 293/Cyan 294/Magenta 295/Yellow 296/Black]>> 297/Parent 5 0 R 298/Resources<< 299/ExtGState<< 300/GS0 14 0 R>> 301/ProcSet[ 302/PDF 303/Text 304/ImageC 305/ImageI] 306/XObject<< 307/Im0 12 0 R>>>> 308/Rotate 0 309/TrimBox[0 0.000122 819.212585 1176.378052] 310/Type 311/Page>> 312endobj 313 314</code></pre> 315 316 317</div><p>In there, amongst the standard keys, we can see â/OneVisionPageColorsInfoâ, which is a non-standard key, obviously added by a OneVision product. It is a dictionary with CreationDate, PageProcessColors and PageCustomColors keys. Once this file has been processed and a new file created by pdfwrite, that information will not be present. It saves space, but at the cost of dropping the metadata. If the file were then sent back through a workflow that expected to find the PageCustomColors in a OneVisionPageColorsInfo dictionary, it would fail.</p><p>That pretty much covers the âincidentalâ space savings that might occur by using the pdfwrite device. Depending on the content of the original file, these might or might not be significant. Now letâs look at actions we can take which might save even more space, but potentially at the cost of some quality.</p><p>The pdfwrite device understands many of the âdistiller parameterâ controls that are specified by Adobe for use with the Adobe Acrobat Distiller product. Distiller takes PostScript programs as input and produces PDF files as output. As we noted right at the start, the Ghostscript family can take a variety of different inputs and produce PDF files as output, and we can apply these distiller parameters to affect how that output is produced.</p><h3>Images</h3><p>The biggest win is often to reduce the size of image data in the PDF file as, if images are present, they will generally use the most bytes. We can do this in several ways:</p><ul><li>Alter the colour space</li><li>Change the compression</li><li>Remove duplicates</li><li>Reduce the âeffectiveâ resolution of the image</li></ul><h4>Altering the colour space</h4><p>We can convert the content to grayscale instead of colour; for RGB input, this is a saving of 66.6%, and for CMYK input, itâs a saving of 75%. Of course, the entire document will then be in gray, which may not be desirable. Use -sColorConversionStrategy=Gray to do this.</p><p>
317If the image data is known to be in CMYK, then the ConvertCMYKImagesToRGB switch can turn them into RGB instead for a 25% saving while retaining the colour.</p><h4>Change the compression</h4><p>If the image data is not compressed or is losslessly compressed, then using a lossy compression filter can save some more space. There are three controls for this: one each for gray, colour, and monochrome (1 bit per pixel) images. Thereâs little point in trying to alter the Monochrome image compression as there is no lossy filter available. Just leave that one alone. The GrayImageFilter and ColorImageFilter, however, can both be set to /DCTEncode, which will apply JPEG compression to the images. Be aware this is a lossy compression; the quality <strong>will</strong> be reduced, and if the original image was JPEG compressed, the additional compression would result in substantial quality degradation.</p><p>Note that you will also have to disable the automatic filter using the AutoFilterGrayImages and AutoFilterColorImages controls (set them to false). There is no AutoFilter control for monochrome images.</p><p>You should also disable PassThroughJPEGImages and PassThroughJPXImages.</p><h4>Removing duplicates</h4><p>Some PDF creation tools, when using the same image (e.g., a company logo) multiple times, will insert a copy of the image each time. With PDF, this isnât necessary; we can use a reference to the image instead and only embed one copy of the image data. If the -dDetectDuplicateImages control is true, then the pdfwrite device will take an MD5 hash of every image and, if it detects two images with the same hash, will replace the second usage with reference to the first image.<strong> NOTE</strong> this control defaults to true, so you do not need to turn it on, but you might want to turn it off.</p><h4>Reduce image resolution</h4><p>This is another area where there is a considerable amount of confusion, not helped by the fact that many image formats include a resolution in the image information. In fact, there is not really a resolution for any image format; merely a number of image samples (or pixels) horizontally and vertically. Until that image is drawn on a medium, we canât say what the resolution actually is.</p><p>To take a concrete example, letâs say I have an image that is 360 pixels by 360 pixels. I then draw that on 1 inch square on a PDF page. The âeffectiveâ resolution of the image is, clearly, 360 dpi. Now I take the same image and draw it into a two-inch square on my PDF page. I havenât changed the image in any way, but now the effective resolution of the image is 180 dpi, half what it was. Yet the image is unchanged, so clearly, the resolution isnât an inherent property of the image itself.</p><p>The controls for reducing image resolution are, unfortunately, complicated because thatâs the way that Adobe defined them, and for compatibility, we chose to implement the same controls. Basically, there is a set of controls for each image âtypeâ: Monochrome, Gray or Colour. We first need to turn on downsampling for the image type(s) we want to change. So set -dDownsampleColorImages, -dDownsampleGrayImages and -dDownsampleMonoImages to true to reduce the resolution of each type of image.</p><p>Next, thereâs a resolution for each image type, and we need to bear in mind the point above about the effective resolution of the image. You should also note that if the image is used in multiple locations at different sizes, then it will be downsampled only once to the lowest effective resolution. So, we need to set -dColorImageResolution, -dGrayImageResolution and -dColorImageResolution.</p><p>Confusingly there is also a âthresholdâ for each of these resolutions. Thatâs there so that we donât spend much time processing image data for very little reward. If the image resolution is already âcloseâ to what we want, then we wonât try and reduce the resolution. Again, there are three controls: -dColorImageDownsampleThreshold, -dGrayImageDownsampleThreshold and -dMonoImageDownsampleThresholdâ.</p> 318 319 320<p>Letâs take an example here, using our image above, which has 360 pixels in each direction and is drawn in a one-inch square. Assume weâve set the desired ImageResolution to 300. If the ImageDownsampleThreshold is the default of 1.5, then we will only downsample images that have an effective resolution of 300 x 1.5 = 450 dpi. Our image drawn in a one-inch square has a resolution of 360 and therefore doesnât qualify, so we wonât reduce its resolution. Using a Threshold of 1.1, however, we would downsample images with a resolution of 300 x 1.1 = 330, and so we would downsample our example image. If we altered the ImageDownsampleThreshold to 1.0, then we would reduce the resolution of all images greater than 300 x 1.0 = 300 to be 300.</p><p>Moving on, the final parameter is the type of downsampling to apply, and there are three possibilities: Subsample, Average and Bicubic. For Monochrome images, we can only use Subsample because the other types involve coming up with some kind of average value of the pixels we are considering. Since monochrome images can only have black or white pixels, thereâs no way to come up with an average. For the other image types, we can use Average or Bicubic; without going into technical detail, bicubic will produce more âpleasingâ results but will take longer.</p><p>There is one control that encapsulates stored values for all the controls above, the -dPDFSETTINGS control. The default for this control is not to apply any kind of space savings; there are four other possible values; /screen, /ebook, /printer and /prepress, which are covered in detail in the Ghostscript documentation at: <a href="https://ghostscript.readthedocs.io/en/gs10.0.0/VectorDevices.html#the-family-of-pdf-and-postscript-output-devices" target="_blank" rel="noopener noreferrer"><span style="color:windowtext;">https://ghostscript.readthedocs.io/en/gs10.0.0/VectorDevices.html#the-family-of-pdf-and-postscript-output-devices</span></a></p><h4>Non-image options</h4><p>There are a few other ways that the file size can be reduced, but with potential downsides.</p><p> The embedding of fonts can be controlled using the /NeverEmbed distiller parameter. Of course, if you donât embed the fonts, then the final PDF consumer will have to use a substitute font, which means the PDF file may not display as intended.</p><p>By default, pdfwrite embeds any halftone screens (used to âditherâ the output on a monochrome device). These can be discarded reasonably safely since any monochrome device (e.g., printer) will always be able to use its own defaults. You can drop this information by setting -dPreserveHalftoneInfo to fal
320se.</p><p>Similarly with overprint, though this might give surprising results on a real CMYK printer or press. The -dPreserveOverprintSettings controls this.</p><p>Transfer functions (dot gain compensation, gamma correction) can be applied to the PDF file, altering the colour values, but allowing the information to be dropped, if it is present in the input file. Set -dTransferFunctionInfo to /Apply instead of /Preserve.</p><p>Undercolour removal and black generation functions are used when converting RGB to CMYK, and PDF files can carry around rules on how to do this. Since printers will always have their own defaults, it is safe to drop this too by setting UCRandBGInfo to /Remove.</p><p>PDF files can contain certain metadata describing the content; this is known as Marked Content and Structure Information. Currently, pdfwrite doesnât preserve Structure Information (it is planned to do so when time allows), but the new PDF interpreter can preserve Marked Content (the old interpreter cannot). If you know you donât need this, then you can set -dPreserveMarkedContent to false.</p><h3>Summary</h3><p>It isnât really possible to give a âone size fits allâ recommendation on how to use these parameters; it depends on how badly you want to reduce the file size, what compromises on quality you are prepared to make, and how much time you want to spend processing the PDF file to get there.</p><p>Iâve tried to describe all the reasonable ways to âoptimizeâ a PDF file and the controls you can use to help do so, as well as warning of what possible pitfalls there might be. Hopefully, this is clear enough to be of some assistance in navigating the admittedly complicated settings for the PDF interpreter and the pdfwrite device.</p></div> 321 322 323 324<hr /> 325 <p>Doing this inside a Python script or a RAG pipeline? <a href="https://artifex.com/blog/optimizing-pdf-file-size-with-pymupdf-three-essential-techniques">Use PyMuPDF</a>.</p> 326 327 </div> 328 329 </article> 330<!--- stop page content here --> 331 332 </div><!-- close inner --> 333 334 </div><!-- close outer --> 335 336 337 338 </main> 339 340 <footer></footer> 341 342
342<script type="text/javascript" src="../js/app.js"></script>
342 343 344 345 346 </body> 347 348 349 350</html>
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.