From eacdb3d843f67d96e285600f3085224a7859ddd1 Mon Sep 17 00:00:00 2001 From: Zheng Jie Tan Date: Wed, 3 Apr 2019 01:11:42 -0400 Subject: [PATCH] Added PDF 2d-resolution export --- Tests/test_file_pdf.py | 4 ++++ docs/handbook/image-file-formats.rst | 6 +++--- src/PIL/PdfImagePlugin.py | 15 +++++++++++---- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/Tests/test_file_pdf.py b/Tests/test_file_pdf.py index 7b024426b..2b5c12ea3 100644 --- a/Tests/test_file_pdf.py +++ b/Tests/test_file_pdf.py @@ -64,6 +64,10 @@ class TestFilePdf(PillowTestCase): # Act / Assert self.helper_save_as_pdf(mode) + def test_resolution(self): + self.helper_save_as_pdf("RGB", resolution=300.5) + self.helper_save_as_pdf("RGB", resolution=(300, 150)) + def test_unsupported_mode(self): im = hopper("LA") outfile = self.tempfile("temp_LA.pdf") diff --git a/docs/handbook/image-file-formats.rst b/docs/handbook/image-file-formats.rst index 3ea8dd533..990851aa3 100644 --- a/docs/handbook/image-file-formats.rst +++ b/docs/handbook/image-file-formats.rst @@ -1054,9 +1054,9 @@ The :py:meth:`~PIL.Image.Image.save` method can take the following keyword argum .. versionadded:: 5.1.0 **resolution** - Image resolution in DPI. This, together with the number of pixels in the - image, will determine the physical dimensions of the page that will be - saved in the PDF. + Image resolution in DPI either as a numeric value or ``(xdpi, ydpi)`` tuple. + This, together with the number of pixels in the image, will determine the + physical dimensions of the page that will be saved in the PDF. **title** The document’s title. If not appending to an existing PDF file, this will diff --git a/src/PIL/PdfImagePlugin.py b/src/PIL/PdfImagePlugin.py index 702aaa392..9e01ea692 100644 --- a/src/PIL/PdfImagePlugin.py +++ b/src/PIL/PdfImagePlugin.py @@ -56,6 +56,13 @@ def _save(im, fp, filename, save_all=False): existing_pdf = PdfParser.PdfParser(f=fp, filename=filename, mode="w+b") resolution = im.encoderinfo.get("resolution", 72.0) + # Allows the user to specify either a 1D resolution or 2D resolution. + if not isinstance(resolution, (list, tuple)): + pdf_width_res = resolution + pdf_height_res = resolution + else: + pdf_width_res = resolution[0] + pdf_height_res = resolution[1] info = { "title": None if is_appending else os.path.splitext( @@ -211,8 +218,8 @@ def _save(im, fp, filename, save_all=False): MediaBox=[ 0, 0, - int(width * 72.0 / resolution), - int(height * 72.0 / resolution) + int(width * 72.0 / pdf_width_res), + int(height * 72.0 / pdf_height_res) ], Contents=contents_refs[pageNumber]) @@ -221,8 +228,8 @@ def _save(im, fp, filename, save_all=False): page_contents = PdfParser.make_bytes( "q %d 0 0 %d 0 0 cm /image Do Q\n" % ( - int(width * 72.0 / resolution), - int(height * 72.0 / resolution))) + int(width * 72.0 / pdf_width_res), + int(height * 72.0 / pdf_height_res))) existing_pdf.write_obj(contents_refs[pageNumber], stream=page_contents)