mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-03-03 11:35:52 +03:00
Merge pull request #4311 from radarhere/wmf
Allow loading of WMF images at a given DPI
This commit is contained in:
commit
2a0653ee81
BIN
Tests/images/drawing_wmf_ref_144.png
Normal file
BIN
Tests/images/drawing_wmf_ref_144.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.2 KiB |
|
@ -53,6 +53,17 @@ class TestFileWmf(PillowTestCase):
|
||||||
with Image.open("Tests/images/drawing_roundDown.emf") as im:
|
with Image.open("Tests/images/drawing_roundDown.emf") as im:
|
||||||
self.assertEqual(im.info["dpi"], 1426)
|
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):
|
def test_save(self):
|
||||||
im = hopper()
|
im = hopper()
|
||||||
|
|
||||||
|
|
|
@ -1019,6 +1019,43 @@ this format.
|
||||||
By default, a Quake2 standard palette is attached to the texture. To override
|
By default, a Quake2 standard palette is attached to the texture. To override
|
||||||
the palette, use the putpalette method.
|
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
|
XPM
|
||||||
^^^
|
^^^
|
||||||
|
|
||||||
|
@ -1176,35 +1213,3 @@ MPEG
|
||||||
^^^^
|
^^^^
|
||||||
|
|
||||||
Pillow identifies MPEG files.
|
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")
|
|
||||||
|
|
|
@ -82,6 +82,18 @@ Custom unidentified image error
|
||||||
Pillow will now throw a custom ``UnidentifiedImageError`` when an image cannot be
|
Pillow will now throw a custom ``UnidentifiedImageError`` when an image cannot be
|
||||||
identified. For backwards compatibility, this will inherit from ``IOError``.
|
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
|
Other Changes
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
|
|
@ -78,6 +78,7 @@ class WmfStubImageFile(ImageFile.StubImageFile):
|
||||||
format_description = "Windows Metafile"
|
format_description = "Windows Metafile"
|
||||||
|
|
||||||
def _open(self):
|
def _open(self):
|
||||||
|
self._inch = None
|
||||||
|
|
||||||
# check placable header
|
# check placable header
|
||||||
s = self.fp.read(80)
|
s = self.fp.read(80)
|
||||||
|
@ -87,7 +88,7 @@ class WmfStubImageFile(ImageFile.StubImageFile):
|
||||||
# placeable windows metafile
|
# placeable windows metafile
|
||||||
|
|
||||||
# get units per inch
|
# get units per inch
|
||||||
inch = word(s, 14)
|
self._inch = word(s, 14)
|
||||||
|
|
||||||
# get bounding box
|
# get bounding box
|
||||||
x0 = short(s, 6)
|
x0 = short(s, 6)
|
||||||
|
@ -96,12 +97,14 @@ class WmfStubImageFile(ImageFile.StubImageFile):
|
||||||
y1 = short(s, 12)
|
y1 = short(s, 12)
|
||||||
|
|
||||||
# normalize size to 72 dots per inch
|
# 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["wmf_bbox"] = x0, y0, x1, y1
|
||||||
|
|
||||||
self.info["dpi"] = 72
|
|
||||||
|
|
||||||
# sanity check (standard metafile header)
|
# sanity check (standard metafile header)
|
||||||
if s[22:26] != b"\x01\x00\t\x00":
|
if s[22:26] != b"\x01\x00\t\x00":
|
||||||
raise SyntaxError("Unsupported WMF file format")
|
raise SyntaxError("Unsupported WMF file format")
|
||||||
|
@ -118,7 +121,6 @@ class WmfStubImageFile(ImageFile.StubImageFile):
|
||||||
# get frame (in 0.01 millimeter units)
|
# get frame (in 0.01 millimeter units)
|
||||||
frame = _long(s, 24), _long(s, 28), _long(s, 32), _long(s, 36)
|
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
|
size = x1 - x0, y1 - y0
|
||||||
|
|
||||||
# calculate dots per inch from bbox and frame
|
# calculate dots per inch from bbox and frame
|
||||||
|
@ -145,6 +147,16 @@ class WmfStubImageFile(ImageFile.StubImageFile):
|
||||||
def _load(self):
|
def _load(self):
|
||||||
return _handler
|
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):
|
def _save(im, fp, filename):
|
||||||
if _handler is None or not hasattr(_handler, "save"):
|
if _handler is None or not hasattr(_handler, "save"):
|
||||||
|
|
Loading…
Reference in New Issue
Block a user