Merge pull request #4311 from radarhere/wmf

Allow loading of WMF images at a given DPI
This commit is contained in:
Andrew Murray 2019-12-30 10:24:44 +11:00 committed by GitHub
commit 2a0653ee81
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 77 additions and 37 deletions

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

@ -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

@ -82,6 +82,18 @@ Custom unidentified image error
Pillow will now throw a custom ``UnidentifiedImageError`` when an image cannot be
identified. For backwards compatibility, this will inherit from ``IOError``.
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"):