Merge branch 'master' into reduce-in-resize

# Conflicts:
#	docs/releasenotes/7.0.0.rst
This commit is contained in:
Alexander 2019-12-30 03:24:38 +03:00
commit c74c20eb9f
7 changed files with 83 additions and 56 deletions

View File

@ -5,6 +5,12 @@ Changelog (Pillow)
7.0.0 (unreleased)
------------------
- Allow loading of WMF images at a given DPI #4311
[radarhere]
- Added reduce operation #4251
[homm]
- Raise ValueError for io.StringIO in Image.open #4302
[radarhere, hugovk]

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -53,6 +53,17 @@ class TestFileWmf(PillowTestCase):
with Image.open("Tests/images/drawing_roundDown.emf") as im:
self.assertEqual(im.info["dpi"], 1426)
def test_load_set_dpi(self):
with Image.open("Tests/images/drawing.wmf") as im:
self.assertEquals(im.size, (82, 82))
if hasattr(Image.core, "drawwmf"):
im.load(144)
self.assertEquals(im.size, (164, 164))
with Image.open("Tests/images/drawing_wmf_ref_144.png") as expected:
self.assert_image_similar(im, expected, 2.0)
def test_save(self):
im = hopper()

View File

@ -1,17 +1,10 @@
import os
import subprocess
import sys
import unittest
from unittest import TestCase
from .helper import is_pypy, is_win32, on_github_actions
class TestMain(TestCase):
@unittest.skipIf(
is_win32() and is_pypy() and on_github_actions(),
"Failing on Windows on GitHub Actions running PyPy",
)
def test_main(self):
out = subprocess.check_output([sys.executable, "-m", "PIL"]).decode("utf-8")
lines = out.splitlines()

View File

@ -1019,6 +1019,43 @@ this format.
By default, a Quake2 standard palette is attached to the texture. To override
the palette, use the putpalette method.
WMF
^^^
Pillow can identify WMF files.
On Windows, it can read WMF files. By default, it will load the image at 72
dpi. To load it at another resolution:
.. code-block:: python
from PIL import Image
with Image.open("drawing.wmf") as im:
im.load(dpi=144)
To add other read or write support, use
:py:func:`PIL.WmfImagePlugin.register_handler` to register a WMF handler.
.. code-block:: python
from PIL import Image
from PIL import WmfImagePlugin
class WmfHandler:
def open(self, im):
...
def load(self, im):
...
return image
def save(self, im, fp, filename):
...
wmf_handler = WmfHandler()
WmfImagePlugin.register_handler(wmf_handler)
im = Image.open("sample.wmf")
XPM
^^^
@ -1176,35 +1213,3 @@ MPEG
^^^^
Pillow identifies MPEG files.
WMF
^^^
Pillow can identify playable WMF files.
In PIL 1.1.4 and earlier, the WMF driver provides some limited rendering
support, but not enough to be useful for any real application.
In PIL 1.1.5 and later, the WMF driver is a stub driver. To add WMF read or
write support to your application, use
:py:func:`PIL.WmfImagePlugin.register_handler` to register a WMF handler.
::
from PIL import Image
from PIL import WmfImagePlugin
class WmfHandler:
def open(self, im):
...
def load(self, im):
...
return image
def save(self, im, fp, filename):
...
wmf_handler = WmfHandler()
WmfImagePlugin.register_handler(wmf_handler)
im = Image.open("sample.wmf")

View File

@ -73,18 +73,6 @@ bounds of resulting image. This may be useful in a subsequent
.. _chain methods: https://en.wikipedia.org/wiki/Method_chaining
API Changes
===========
Deprecations
^^^^^^^^^^^^
TODO
~~~~
TODO
API Additions
=============
@ -121,6 +109,18 @@ to reduce an image by integer times. Normally, it shouldn't be used directly.
Used internally by :py:meth:`~PIL.Image.Image.resize` and :py:meth:`~PIL.Image.Image.thumbnail`
methods to speed up resize when a new argument ``reducing_gap`` is set.
Loading WMF images at a given DPI
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
On Windows, Pillow can read WMF files, with a default DPI of 72. An image can
now also be loaded at another resolution:
.. code-block:: python
from PIL import Image
with Image.open("drawing.wmf") as im:
im.load(dpi=144)
Other Changes
=============

View File

@ -78,6 +78,7 @@ class WmfStubImageFile(ImageFile.StubImageFile):
format_description = "Windows Metafile"
def _open(self):
self._inch = None
# check placable header
s = self.fp.read(80)
@ -87,7 +88,7 @@ class WmfStubImageFile(ImageFile.StubImageFile):
# placeable windows metafile
# get units per inch
inch = word(s, 14)
self._inch = word(s, 14)
# get bounding box
x0 = short(s, 6)
@ -96,12 +97,14 @@ class WmfStubImageFile(ImageFile.StubImageFile):
y1 = short(s, 12)
# normalize size to 72 dots per inch
size = (x1 - x0) * 72 // inch, (y1 - y0) * 72 // inch
self.info["dpi"] = 72
size = (
(x1 - x0) * self.info["dpi"] // self._inch,
(y1 - y0) * self.info["dpi"] // self._inch,
)
self.info["wmf_bbox"] = x0, y0, x1, y1
self.info["dpi"] = 72
# sanity check (standard metafile header)
if s[22:26] != b"\x01\x00\t\x00":
raise SyntaxError("Unsupported WMF file format")
@ -118,7 +121,6 @@ class WmfStubImageFile(ImageFile.StubImageFile):
# get frame (in 0.01 millimeter units)
frame = _long(s, 24), _long(s, 28), _long(s, 32), _long(s, 36)
# normalize size to 72 dots per inch
size = x1 - x0, y1 - y0
# calculate dots per inch from bbox and frame
@ -145,6 +147,16 @@ class WmfStubImageFile(ImageFile.StubImageFile):
def _load(self):
return _handler
def load(self, dpi=None):
if dpi is not None and self._inch is not None:
self.info["dpi"] = int(dpi + 0.5)
x0, y0, x1, y1 = self.info["wmf_bbox"]
self._size = (
(x1 - x0) * self.info["dpi"] // self._inch,
(y1 - y0) * self.info["dpi"] // self._inch,
)
super().load()
def _save(im, fp, filename):
if _handler is None or not hasattr(_handler, "save"):