mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-01-13 10:46:16 +03:00
Merge branch 'master' into reduce-in-resize
# Conflicts: # docs/releasenotes/7.0.0.rst
This commit is contained in:
commit
c74c20eb9f
|
@ -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]
|
||||
|
||||
|
|
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:
|
||||
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()
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
=============
|
||||
|
||||
|
|
|
@ -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"):
|
||||
|
|
Loading…
Reference in New Issue
Block a user