title: PIL's Image.save('image.pdf') creates excessivly large PDF
body: <p>I have an low-resolution black &amp; white image <code>screenBWsmall.png</code>:</p>
  <p><a href="https://i.stack.imgur.com/QUvio.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/QUvio.png" alt="enter image description here" /></a></p>
  <p>I use the Python Imaging Library to convert it to PDF:</p>
  <pre><code>#!python
  from PIL import Image 
  im = Image.open('screenBWsmall.png')
  im.save('screenBWsmall.pdf')
  </code></pre>
  <p>The PDF file is huge compared to one generated from ImageMagick's <code>convert</code>, issued from the Bash command line:</p>
  <pre><code>convert screenBWsmall.png screenBWsmall_IM.pdf
  </code></pre>
  <p>The file sizes are:</p>
  <pre><code>  11093 screenBWsmall.png
  1050994 screenBWsmall.pdf
    16999 screenBWsmall_IM.pdf
  </code></pre>
  <p>While I'm puzzled by this, it is even more puzzling considering that the larger file <code>screenBWsmall.pdf</code> uses 1 bit per pixel (bits per component, or <code>bpc</code>) compared to 8 bpc for the smaller file <code>screenBWsmall_IM.pdf</code>:</p>
  <pre><code>$ pdfimages.exe -list screenBWsmall.pdf
  page   num  type   width height color comp bpc  enc interp  object ID x-ppi y-ppi size ratio
  --------------------------------------------------------------------------------------------
     1     0 image     960   540  gray    1   1  image  no         1  0    72    72 1025K 1621%
  
  $ pdfimages.exe -list screenBWsmall_IM.pdf
  page   num  type   width height color comp bpc  enc interp  object ID x-ppi y-ppi size ratio
  -------------------------------------------------------------------------------------------- 
     1     0 image     960   540  gray    1   8  image  no         8  0    72    72 14.9K 2.9%
  </code></pre>
  <p>The <a href="https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.save" rel="nofollow noreferrer">Image.save documentation</a> doesn't give much information with which I can speculate on the reason for the large file size.</p>
  <p><strong>Why does PIL create such a large PDF file size?</strong></p>
  <p><strong>Is there any way to have it create the smaller size of ImageMagick's <code>convert</code>?</strong>  I want to do it in Python because I will be performinng more complex steps with many files.</p>
  <p>My Python version is:</p>
  <pre><code>Python 3.8.8 (default, Mar  4 2021, 21:24:42) 
  [GCC 10.2.0] on cygwin
  </code></pre>
  <hr />
  <p><strong>Investigations with ImageMagick's <code>convert</code></strong></p>
  <p>Thanks to <em>fmw42</em>'s suggestions, I systematically experimented with 3 ways to shrink and combine 2 JPG images to into 1 PDF file.  In order of decreasing file size, the 3 methods are as follows.</p>
  <p><strong>Method #1:</strong> Use Python's PIL to generate <em>IMG_077x_PIL.pdf</em> (see <code>jpg2pdf.py</code> below).  In the process of doing so, save shrunken versions of both images to separate PNG files for <em>Method #3</em>.</p>
  <p><strong>Method #2:</strong> Use ImageMagick's <code>convert</code> to generate <em>IMG_077x_IMcvt.pdf:</em></p>
  <pre><code>convert -sample 50% -type Bilevel +dither IMG_077[45].JPG IMG_077x_IMcvt.pdf
  </code></pre>
  <p><strong>Method #3:</strong> Apply <code>convert</code> to shrunken PNG files from PIL to generate <em>IMG_077x_PIL+IMcvt.pdf</em>:</p>
  <pre><code>convert IMG_077[45]small.png IMG_077x_PIL+IMcvt.pdf
  </code></pre>
  <p><strong>Output PDF file sizes</strong> (in the same order as the methods above):</p>
  <pre><code>12350481 IMG_077x_PIL.pdf
   1234076 IMG_077x_IMcvt.pdf
    149782 IMG_077x_PIL+IMcvt.pdf
  </code></pre>
  <p>The 2 <strong>input JPG files sizes</strong> are a few MBs:</p>
  <pre><code> 2526685 IMG_0774.JPG
   2699515 IMG_0775.JPG
  </code></pre>
  <p>The 2 <strong>intermediate PNG file sizes</strong> used in Methods #1 and #3 are few dozen KBs:</p>
  <pre><code>   67283 IMG_0775small.png
     61968 IMG_0774small.png
  </code></pre>
  <p><strong>Observations:</strong></p>
  <ul>
  <li><p>Method #1: Great for shrinking the images down, but really bad in generating an enormous PDF file that is two orders of magnitude larger than it has to be.</p>
  </li>
  <li><p>Method #2: Middle of the road, most convenient, but PDF file size is an order of magnitude larger than it has to be.</p>
  </li>
  <li><p>Method #3: Requires both Python, PIL, and <code>convert</code>.  It is the least convenient, but most byte efficient.  The resulting PDF is only slightly larger than the sum of the two PNG images.</p>
  </li>
  </ul>
  <p><em>I wish there was a way to make Methods #1 and/or #2 as good as Method #3.</em></p>
  <p><strong>Characteristics of the output PDF files</strong></p>
  <pre><code>page   num  type   width height color comp bpc  enc interp  object ID x-ppi y-ppi size ratio
  --------------------------------------------------------------------------------------------
  $pdfimages -list IMG_077x_PIL.pdf
     1     0 image    1512  2016  gray    1   1  image  no         1  0    72    72 6030K 1621%
     2     1 image    1512  2016  gray    1   1  image  no         4  0    72    72 6030K 1621%
  
  $pdfimages -list IMG_077x_IMcvt.pdf
     1     0 image    2016  1512  gray    1   8  jpeg   no         8  0    72    72  576K  19% 
     2     1 image    2016  1512  gray    1   8  jpeg   no        22  0    72    72  626K  21% 
  
  $pdfimages -list IMG_077x_PIL+IMcvt.pdf
     1     0 image    1512  2016  gray    1   8  image  no         8  0    72    72 68.9K 2.3% 
     2     1 image    1512  2016  gray    1   8  image  no        22  0    72    72 74.6K 2.5% 
  </code></pre>
  <p><strong>jpg2pdf.py</strong></p>
  <pre><code>#!python
  
  # jpg2pdf.py
  #-----------
  # Use PIL to subsample, rotate, and convert 2 JPGs to B&amp;W.
  # Save each to small PNGs.
  # Combine both into a PDF.
  
  import os
  from PIL import Image
  
  ims = [] # Stores the 2 images
  fns=('IMG_0774.JPG','IMG_0775.JPG') # Filenames of the 2 images
  
  for fn in fns:
     
     # Read, resize, rotate, convert to B&amp;W, add to list `fns`
     im = Image.open(fn)
     im = im.resize((im.width//2, im.height//2))
     im = im.rotate(-90,expand=True)
     im = im.convert(mode=&quot;1&quot;, dither=Image.NONE)
     ims.append(im)
  
     # Write IMG_077[45]small.png
     fnBase = os.path.splitext(fn)[0]
     im.save( fnBase+'small.png' )
  
  # Write both to a single PDF
  ims[0].save( 'IMG_077x_PIL.pdf' , save_all=True , append_images=ims[1:] )
  </code></pre>
  <p><strong>A test input file</strong></p>
  <p><a href="https://drive.google.com/file/d/1vFKJzN4fn0qKfNRQg6R4cRLgKnPJvy2l/view?usp=sharing" rel="nofollow noreferrer">This dummy JPEG image file</a> should be save-able as both
  <code>IMG_0774.JPG</code>and <code>IMG_0775.JPG</code>.  Methods #1 through #3 should then
  work exactly as described with the code posted above. Using this JPG
  image, I confirmed that the 3 output file sizes are almost the same as
  reported in my question. Being just over 2MB, unfortunately, it can't
  be uploaded to this posted question.</p>