3

It doesn't necessarily have to be CMD but I'd prefer it. It has to be free though.

I have tried lots of different ones but all of them seem to optimize some bit data within the PDFs and don't even touch the image compression which is what I am after as this is the main size culprit in my PDFs generated from Google Docs.

2

1 Answer 1

5

I'm not sure what you mean exactly with "compression optimizer":

  1. 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.

  2. 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:

  1. Convert all images to grayscale color space.
  2. Un-embed all Helvetica, Courier, Times, Symbol and ZapfDingbats fonts (the "Base 14" for PDF).
  3. Downsample all images to 72 PPI if the current resolution of the respective image is above 72 PPI.
  4. Change all image compression to JPEG compression (/DCTEncode) if possible.
  5. 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:

  1. Using -d for these parameters. In that case there must be forward slashes / for the parameter values:

    -dProcessColorModel=/DeviceGray          \
    -dColorConversionStrategy=/Gray          \
    -dColorConversionStrategyForImages=/Gray \
    
  2. 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%
10
  • 1
    Sorry for ignorance but I need just a bit of explanation as I've never used ghostscript before. I have downloaded and put it in one folder on the disk, I've also put pdf named gray.pdf in the same dir and made batch where I copied all the above but, changed gs to gswin64.exe and it shows some errors so I removed all the "\" but still nothing. Commented Apr 3, 2015 at 22:02
  • 2
    @FateTrader: In a Windows *.bat file you need to also change the line endings to ^. And possibly remove the spaces from the start of lines. (I thought someone asking explicitly for a command line tool know that.) Commented Apr 4, 2015 at 3:11
  • 1
    @FateTrader: I did NOT talk about replacing / -- I talked about replacing \ as line continuation markers! I also did NOT advertise to remove spaces at the end of lines before the (new) ^ signs (there must remain at least 1 space!). Commented Apr 4, 2015 at 17:40
  • 1
    Sigh... @FateTrader: Also, I didn't recommend to use gswin64.exe for Windows, but I recommended gswin64c.exe (notice the c before the .exe ?!?) Commented Apr 4, 2015 at 17:45
  • 1
    @FateTrader: you should provide a (link to a) sample 'big.pdf' to test with... Commented Apr 4, 2015 at 17:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.