I'm not sure what you mean exactly with "compression optimizer":
You may want to leave every single PDF object that may be relevant to the rendered pages "as is", and just impose the highest possible lossless compression to object streams which are yet un-compressed, or which are compressed/encoded with a not-so-efficient compression method.
You may be willing to accept, on top of the options listed in "1.", some other changes to the PDF file:
- Downsampling of image resolution.
- Subsetting fonts which are fully embedded.
- Unembedding fully embedded fonts if they belong to the Base 14 PDF fonts.
- Convert CMYK colors to RGB colors.
- Convert color images to grayscale images.
- Remove most of the PDF's metadata.
- Throw out un-used objects.
- If the final version of the PDF document is a result of incremental updates, reduce it to this final version (throwing out all "preserved-inside" previous versions).
- Throw out any potentially embedded ICC profiles.
A sophisticated enough, long Ghostscript command line can help with that. It will do a PDF-to-PDF conversion:
gs \
-o smaller-downsampled+gray.pdf \
-sDEVICE=pdfwrite \
-dCompressPages=true \
-dCompressFonts=true \
-dDownsampleColorImages=true \
-dDownsampleGrayImages=true \
-dDownsampleMonoImages=true \
-dColorImageResolution=72 \
-dGrayImageResolution=72 \
-dMonoImageResolution=72 \
-dColorImageDownsampleThreshold=1.0 \
-dGrayImageDownsampleThreshold=1.0 \
-dMonoImageDownsampleThreshold=1.0 \
-dProcessColorModel=/DeviceGray \
-dColorConversionStrategy=/Gray \
-dColorConversionStrategyForImages=/Gray \
-dCompatibilityLevel=1.4 \
-dEmbedAllFonts=false \
-c ".setpdfwrite <</AlwaysEmbed [ ] /NeverEmbed [/Courier /Courier-Bold /Courier-Oblique /Courier-BoldOblique /Helvetica /Helvetica-Bold /Helvetica-Oblique /Helvetica-BoldOblique /Times-Roman /Times-Bold /Times-Italic /Times-BoldItalic /Symbol /ZapfDingbats] /ColorImageFilter /DCTEncode /GrayImageFilter /DCTEncode /MonoImageFilter /CCITTFaxEncode /OutputICCProfile (None)>> setdistillerparams" \
-f big.pdf
(For Windows, change gs
to gswin32c.exe
or gswin64c.exe
, and change all line-continuation markers \
to ^
...) Above command will change the following:
- Convert all images to grayscale color space.
- Un-embed all Helvetica, Courier, Times, Symbol and ZapfDingbats fonts (the "Base 14" for PDF).
- Downsample all images to 72 PPI if the current resolution of the respective image is above 72 PPI.
- Change all image compression to JPEG compression (
/DCTEncode
) if possible.
- Throw out embedded ICC output profiles, if possible.
Update/Correction
My original example command had a typo. It had contained these lines, which are wrong:
-sProcessColorModel=/DeviceGray \
-sColorConversionStrategy=/Gray \
-sColorConversionStrategyForImages=/Gray \
There are two different ways to express these options correctly:
Using -d
for these parameters. In that case there must be forward slashes /
for the parameter values:
-dProcessColorModel=/DeviceGray \
-dColorConversionStrategy=/Gray \
-dColorConversionStrategyForImages=/Gray \
Using -s
for these parameters. In that case the forward slashes /
for the parameter values must be skipped:
-sProcessColorModel=DeviceGray \
-sColorConversionStrategy=Gray \
-sColorConversionStrategyForImages=Gray \
(However, there is no general rule that may be derived for all Ghostscript options from this example, it only applies to a certain subset of parameters where -s...
or -d...
may be used alternatively in this way.)
So I got it exactly the wrong way round. Sorry for the confusion this caused!
In any case, the modified command works for the OP's linked big.pdf
now. It brings down
- the original size of 2.5 MByte for a 1-page PDF containing a color image to
- the new size of 53 kByte for a PDF containing a gray-scale image.
Data for original image inside big.pdf
:
$ pdfimages -list big.pdf
page num type width height color comp bpc enc interp objID x-ppi y-ppi size ratio
-----------------------------------------------------------------------------------
1 0 image 1600 1071 rgb 3 8 image no 7 0 142 142 2502K 50%
Data for new image inside smaller-downsampled+gray.pdf
:
$ pdfimages -list smaller-downsampled+gray.pdf
page num type width height color comp bpc enc interp objID x-ppi y-ppi size ratio
-----------------------------------------------------------------------------------
1 0 image 800 535 gray 1 8 jpeg no 12 0 71 71 48.5K 12%