diff --git a/PIL/WmfImagePlugin.py b/PIL/WmfImagePlugin.py index 9416035c0..1dbd9f964 100644 --- a/PIL/WmfImagePlugin.py +++ b/PIL/WmfImagePlugin.py @@ -14,6 +14,10 @@ # # See the README file for information on usage and redistribution. # +# WMF/EMF reference documentation: +# https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-WMF/[MS-WMF].pdf +# http://wvware.sourceforge.net/caolan/index.html +# http://wvware.sourceforge.net/caolan/ora-wmf.html from PIL import Image, ImageFile, _binary @@ -56,16 +60,9 @@ if hasattr(Image.core, "drawwmf"): # -------------------------------------------------------------------- word = _binary.i16le - - -def short(c, o=0): - v = word(c, o) - if v >= 32768: - v -= 65536 - return v - +short = _binary.si16le dword = _binary.i32le - +_long = _binary.si32le # # -------------------------------------------------------------------- @@ -121,13 +118,13 @@ class WmfStubImageFile(ImageFile.StubImageFile): # enhanced metafile # get bounding box - x0 = dword(s, 8) - y0 = dword(s, 12) - x1 = dword(s, 16) - y1 = dword(s, 20) + x0 = _long(s, 8) + y0 = _long(s, 12) + x1 = _long(s, 16) + y1 = _long(s, 20) # get frame (in 0.01 millimeter units) - frame = dword(s, 24), dword(s, 28), dword(s, 32), dword(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 diff --git a/PIL/_binary.py b/PIL/_binary.py index 1cbe59dea..9760b86cd 100644 --- a/PIL/_binary.py +++ b/PIL/_binary.py @@ -31,23 +31,41 @@ else: # TODO: replace with more readable struct.unpack equivalent def i16le(c, o=0): """ - Converts a 2-bytes (16 bits) string to an integer. + Converts a 2-bytes (16 bits) string to an unsigned integer. c: string containing bytes to convert o: offset of bytes to convert in string """ return unpack("H", c[o:o+2])[0] diff --git a/Tests/images/drawing.emf b/Tests/images/drawing.emf new file mode 100644 index 000000000..ef751cd51 Binary files /dev/null and b/Tests/images/drawing.emf differ diff --git a/Tests/images/drawing.wmf b/Tests/images/drawing.wmf new file mode 100644 index 000000000..d9cfda453 Binary files /dev/null and b/Tests/images/drawing.wmf differ diff --git a/Tests/images/drawing_emf_ref.png b/Tests/images/drawing_emf_ref.png new file mode 100644 index 000000000..3e66cbd44 Binary files /dev/null and b/Tests/images/drawing_emf_ref.png differ diff --git a/Tests/images/drawing_wmf_ref.png b/Tests/images/drawing_wmf_ref.png new file mode 100644 index 000000000..207160de0 Binary files /dev/null and b/Tests/images/drawing_wmf_ref.png differ diff --git a/Tests/test_file_wmf.py b/Tests/test_file_wmf.py new file mode 100644 index 000000000..f08ee249f --- /dev/null +++ b/Tests/test_file_wmf.py @@ -0,0 +1,31 @@ +from helper import unittest, PillowTestCase +from PIL import Image +from io import BytesIO + +class TestFileWmf(PillowTestCase): + + def test_load_raw(self): + + # Test basic EMF open and rendering + im = Image.open('Tests/images/drawing.emf') + if hasattr(Image.core, "drawwmf"): + # Currently, support for WMF/EMF is Windows-only + im.load() + # Compare to reference rendering + imref = Image.open('Tests/images/drawing_emf_ref.png') + imref.load() + self.assert_image_similar(im, imref, 0) + + # Test basic WMF open and rendering + im = Image.open('Tests/images/drawing.wmf') + if hasattr(Image.core, "drawwmf"): + # Currently, support for WMF/EMF is Windows-only + im.load() + # Compare to reference rendering + imref = Image.open('Tests/images/drawing_wmf_ref.png') + imref.load() + self.assert_image_similar(im, imref, 0.5) + + +if __name__ == '__main__': + unittest.main()