Merge #772 and master

This commit is contained in:
wiredfool 2014-07-08 10:29:53 -07:00
commit 552effb90d
118 changed files with 555 additions and 242 deletions

View File

@ -14,9 +14,10 @@ python:
- 3.4 - 3.4
install: install:
- "sudo apt-get -qq install libfreetype6-dev liblcms2-dev python-qt4 ghostscript libffi-dev libjpeg-turbo-progs cmake" - "sudo apt-get -qq install libfreetype6-dev liblcms2-dev python-qt4 ghostscript libffi-dev libjpeg-turbo-progs cmake imagemagick"
- "pip install cffi" - "pip install cffi"
- "pip install coveralls nose pyroma" - "pip install coveralls nose"
- travis_retry pip install pyroma
- if [ "$TRAVIS_PYTHON_VERSION" == "2.6" ]; then pip install unittest2; fi - if [ "$TRAVIS_PYTHON_VERSION" == "2.6" ]; then pip install unittest2; fi
# webp # webp

View File

@ -1,6 +1,25 @@
Changelog (Pillow) Changelog (Pillow)
================== ==================
2.6.0 (unreleased)
------------------
- Fix return value of FreeTypeFont.textsize() does not include font offsets
[tk0miya]
- Fix dispose calculations for animated GIFs #765
[larsjsol]
- 32bit mult overflow fix #782
[wiredfool]
- Added class checking to Image __eq__ function #775
[radarhere, hugovk]
- Test PalmImagePlugin and method to skip known bad tests #776
[hugovk, wiredfool]
2.5.0 (2014-07-01) 2.5.0 (2014-07-01)
------------------ ------------------

View File

@ -17,8 +17,6 @@
import os import os
from PIL import Image, _binary from PIL import Image, _binary
import marshal
try: try:
import zlib import zlib
except ImportError: except ImportError:
@ -26,6 +24,7 @@ except ImportError:
WIDTH = 800 WIDTH = 800
def puti16(fp, values): def puti16(fp, values):
# write network order (big-endian) 16-bit sequence # write network order (big-endian) 16-bit sequence
for v in values: for v in values:
@ -33,6 +32,7 @@ def puti16(fp, values):
v += 65536 v += 65536
fp.write(_binary.o16be(v)) fp.write(_binary.o16be(v))
## ##
# Base class for raster font file handlers. # Base class for raster font file handlers.
@ -95,9 +95,8 @@ class FontFile:
# print chr(i), dst, s # print chr(i), dst, s
self.metrics[i] = d, dst, s self.metrics[i] = d, dst, s
def save(self, filename):
def save1(self, filename): "Save font"
"Save font in version 1 format"
self.compile() self.compile()
@ -117,30 +116,4 @@ class FontFile:
puti16(fp, m[0] + m[1] + m[2]) puti16(fp, m[0] + m[1] + m[2])
fp.close() fp.close()
# End of file
def save2(self, filename):
"Save font in version 2 format"
# THIS IS WORK IN PROGRESS
self.compile()
data = marshal.dumps((self.metrics, self.info))
if zlib:
data = b"z" + zlib.compress(data, 9)
else:
data = b"u" + data
fp = open(os.path.splitext(filename)[0] + ".pil", "wb")
fp.write(b"PILfont2\n" + self.name + "\n" + "DATA\n")
fp.write(data)
self.bitmap.save(fp, "PNG")
fp.close()
save = save1 # for now

View File

@ -96,8 +96,15 @@ class GifImageFile(ImageFile.ImageFile):
# rewind # rewind
self.__offset = 0 self.__offset = 0
self.dispose = None self.dispose = None
self.dispose_extent = [0, 0, 0, 0] #x0, y0, x1, y1
self.__frame = -1 self.__frame = -1
self.__fp.seek(self.__rewind) self.__fp.seek(self.__rewind)
self._prev_im = None
self.disposal_method = 0
else:
# ensure that the previous frame was loaded
if not self.im:
self.load()
if frame != self.__frame + 1: if frame != self.__frame + 1:
raise ValueError("cannot seek to frame %d" % frame) raise ValueError("cannot seek to frame %d" % frame)
@ -114,8 +121,7 @@ class GifImageFile(ImageFile.ImageFile):
self.__offset = 0 self.__offset = 0
if self.dispose: if self.dispose:
self.im = self.dispose self.im.paste(self.dispose, self.dispose_extent)
self.dispose = None
from copy import copy from copy import copy
self.palette = copy(self.global_palette) self.palette = copy(self.global_palette)
@ -140,17 +146,16 @@ class GifImageFile(ImageFile.ImageFile):
if flags & 1: if flags & 1:
self.info["transparency"] = i8(block[3]) self.info["transparency"] = i8(block[3])
self.info["duration"] = i16(block[1:3]) * 10 self.info["duration"] = i16(block[1:3]) * 10
try:
# disposal methods # disposal method - find the value of bits 4 - 6
if flags & 8: dispose_bits = 0b00011100 & flags
# replace with background colour dispose_bits = dispose_bits >> 2
self.dispose = Image.core.fill("P", self.size, if dispose_bits:
self.info["background"]) # only set the dispose if it is not
elif flags & 16: # unspecified. I'm not sure if this is
# replace with previous contents # correct, but it seems to prevent the last
self.dispose = self.im.copy() # frame from looking odd for some animations
except (AttributeError, KeyError): self.disposal_method = dispose_bits
pass
elif i8(s) == 255: elif i8(s) == 255:
# #
# application extension # application extension
@ -172,6 +177,7 @@ class GifImageFile(ImageFile.ImageFile):
# extent # extent
x0, y0 = i16(s[0:]), i16(s[2:]) x0, y0 = i16(s[0:]), i16(s[2:])
x1, y1 = x0 + i16(s[4:]), y0 + i16(s[6:]) x1, y1 = x0 + i16(s[4:]), y0 + i16(s[6:])
self.dispose_extent = x0, y0, x1, y1
flags = i8(s[8]) flags = i8(s[8])
interlace = (flags & 64) != 0 interlace = (flags & 64) != 0
@ -194,6 +200,26 @@ class GifImageFile(ImageFile.ImageFile):
pass pass
# raise IOError, "illegal GIF tag `%x`" % i8(s) # raise IOError, "illegal GIF tag `%x`" % i8(s)
try:
if self.disposal_method < 2:
# do not dispose or none specified
self.dispose = None
elif self.disposal_method == 2:
# replace with background colour
self.dispose = Image.core.fill("P", self.size,
self.info["background"])
else:
# replace with previous contents
if self.im:
self.dispose = self.im.copy()
# only dispose the extent in this frame
if self.dispose:
self.dispose = self.dispose.crop(self.dispose_extent)
except (AttributeError, KeyError):
pass
if not self.tile: if not self.tile:
# self.__fp = None # self.__fp = None
raise EOFError("no more images in GIF file") raise EOFError("no more images in GIF file")
@ -205,6 +231,18 @@ class GifImageFile(ImageFile.ImageFile):
def tell(self): def tell(self):
return self.__frame return self.__frame
def load_end(self):
ImageFile.ImageFile.load_end(self)
# if the disposal method is 'do not dispose', transparent
# pixels should show the content of the previous frame
if self._prev_im and self.disposal_method == 1:
# we do this by pasting the updated area onto the previous
# frame which we then use as the current image content
updated = self.im.crop(self.dispose_extent)
self._prev_im.paste(updated, self.dispose_extent, updated.convert('RGBA'))
self.im = self._prev_im
self._prev_im = self.im.copy()
# -------------------------------------------------------------------- # --------------------------------------------------------------------
# Write GIF files # Write GIF files

View File

@ -573,6 +573,8 @@ class Image:
return file return file
def __eq__(self, other): def __eq__(self, other):
if self.__class__.__name__ != other.__class__.__name__:
return False
a = (self.mode == other.mode) a = (self.mode == other.mode)
b = (self.size == other.size) b = (self.size == other.size)
c = (self.getpalette() == other.getpalette()) c = (self.getpalette() == other.getpalette())

View File

@ -147,7 +147,8 @@ class FreeTypeFont:
return self.font.ascent, self.font.descent return self.font.ascent, self.font.descent
def getsize(self, text): def getsize(self, text):
return self.font.getsize(text)[0] size, offset = self.font.getsize(text)
return (size[0] + offset[0], size[1] + offset[1])
def getoffset(self, text): def getoffset(self, text):
return self.font.getsize(text)[1] return self.font.getsize(text)[1]

View File

@ -77,6 +77,7 @@ _Palm8BitColormapValues = (
( 0, 0, 0), ( 0, 0, 0), ( 0, 0, 0), ( 0, 0, 0), ( 0, 0, 0), ( 0, 0, 0), ( 0, 0, 0), ( 0, 0, 0),
( 0, 0, 0), ( 0, 0, 0), ( 0, 0, 0), ( 0, 0, 0)) ( 0, 0, 0), ( 0, 0, 0), ( 0, 0, 0), ( 0, 0, 0))
# so build a prototype image to be used for palette resampling # so build a prototype image to be used for palette resampling
def build_prototype_image(): def build_prototype_image():
image = Image.new("L", (1, len(_Palm8BitColormapValues),)) image = Image.new("L", (1, len(_Palm8BitColormapValues),))
@ -91,7 +92,8 @@ def build_prototype_image():
Palm8BitColormapImage = build_prototype_image() Palm8BitColormapImage = build_prototype_image()
# OK, we now have in Palm8BitColormapImage, a "P"-mode image with the right palette # OK, we now have in Palm8BitColormapImage,
# a "P"-mode image with the right palette
# #
# -------------------------------------------------------------------- # --------------------------------------------------------------------
@ -110,6 +112,7 @@ _COMPRESSION_TYPES = {
o8 = _binary.o8 o8 = _binary.o8
o16b = _binary.o16be o16b = _binary.o16be
# #
# -------------------------------------------------------------------- # --------------------------------------------------------------------
@ -127,12 +130,16 @@ def _save(im, fp, filename, check=0):
bpp = 8 bpp = 8
version = 1 version = 1
elif im.mode == "L" and "bpp" in im.encoderinfo and im.encoderinfo["bpp"] in (1, 2, 4): elif (im.mode == "L" and
"bpp" in im.encoderinfo and
im.encoderinfo["bpp"] in (1, 2, 4)):
# this is 8-bit grayscale, so we shift it to get the high-order bits, and invert it because # this is 8-bit grayscale, so we shift it to get the high-order bits,
# and invert it because
# Palm does greyscale from white (0) to black (1) # Palm does greyscale from white (0) to black (1)
bpp = im.encoderinfo["bpp"] bpp = im.encoderinfo["bpp"]
im = im.point(lambda x, shift=8-bpp, maxval=(1 << bpp)-1: maxval - (x >> shift)) im = im.point(
lambda x, shift=8-bpp, maxval=(1 << bpp)-1: maxval - (x >> shift))
# we ignore the palette here # we ignore the palette here
im.mode = "P" im.mode = "P"
rawmode = "P;" + str(bpp) rawmode = "P;" + str(bpp)
@ -140,8 +147,9 @@ def _save(im, fp, filename, check=0):
elif im.mode == "L" and "bpp" in im.info and im.info["bpp"] in (1, 2, 4): elif im.mode == "L" and "bpp" in im.info and im.info["bpp"] in (1, 2, 4):
# here we assume that even though the inherent mode is 8-bit grayscale, only # here we assume that even though the inherent mode is 8-bit grayscale,
# the lower bpp bits are significant. We invert them to match the Palm. # only the lower bpp bits are significant.
# We invert them to match the Palm.
bpp = im.info["bpp"] bpp = im.info["bpp"]
im = im.point(lambda x, maxval=(1 << bpp)-1: maxval - (x & maxval)) im = im.point(lambda x, maxval=(1 << bpp)-1: maxval - (x & maxval))
# we ignore the palette here # we ignore the palette here
@ -172,7 +180,7 @@ def _save(im, fp, filename, check=0):
cols = im.size[0] cols = im.size[0]
rows = im.size[1] rows = im.size[1]
rowbytes = ((cols + (16//bpp - 1)) / (16 // bpp)) * 2 rowbytes = int((cols + (16//bpp - 1)) / (16 // bpp)) * 2
transparent_index = 0 transparent_index = 0
compression_type = _COMPRESSION_TYPES["none"] compression_type = _COMPRESSION_TYPES["none"]
@ -205,12 +213,19 @@ def _save(im, fp, filename, check=0):
for i in range(256): for i in range(256):
fp.write(o8(i)) fp.write(o8(i))
if colormapmode == 'RGB': if colormapmode == 'RGB':
fp.write(o8(colormap[3 * i]) + o8(colormap[3 * i + 1]) + o8(colormap[3 * i + 2])) fp.write(
o8(colormap[3 * i]) +
o8(colormap[3 * i + 1]) +
o8(colormap[3 * i + 2]))
elif colormapmode == 'RGBA': elif colormapmode == 'RGBA':
fp.write(o8(colormap[4 * i]) + o8(colormap[4 * i + 1]) + o8(colormap[4 * i + 2])) fp.write(
o8(colormap[4 * i]) +
o8(colormap[4 * i + 1]) +
o8(colormap[4 * i + 2]))
# now convert data to raw form # now convert data to raw form
ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode, rowbytes, 1))]) ImageFile._save(
im, fp, [("raw", (0, 0)+im.size, 0, (rawmode, rowbytes, 1))])
fp.flush() fp.flush()

View File

@ -3,20 +3,25 @@ import os
if bytes is str: if bytes is str:
def isStringType(t): def isStringType(t):
return isinstance(t, basestring) return isinstance(t, basestring)
def isPath(f): def isPath(f):
return isinstance(f, basestring) return isinstance(f, basestring)
else: else:
def isStringType(t): def isStringType(t):
return isinstance(t, str) return isinstance(t, str)
def isPath(f): def isPath(f):
return isinstance(f, (bytes, str)) return isinstance(f, (bytes, str))
# Checks if an object is a string, and that it points to a directory. # Checks if an object is a string, and that it points to a directory.
def isDirectory(f): def isDirectory(f):
return isPath(f) and os.path.isdir(f) return isPath(f) and os.path.isdir(f)
class deferred_error(object): class deferred_error(object):
def __init__(self, ex): def __init__(self, ex):
self.ex = ex self.ex = ex
def __getattr__(self, elt): def __getattr__(self, elt):
raise self.ex raise self.ex

View File

@ -0,0 +1,10 @@
#!/usr/bin/env python
from PIL import Image
import sys
if sys.maxsize < 2**32:
im = Image.new('L', (999999, 999999), 0)

View File

@ -5,22 +5,19 @@ from __future__ import print_function
import sys import sys
import tempfile import tempfile
import os import os
import glob
if sys.version_info[:2] <= (2, 6): if sys.version_info[:2] <= (2, 6):
import unittest2 as unittest import unittest2 as unittest
else: else:
import unittest import unittest
def tearDownModule():
#remove me later
pass
class PillowTestCase(unittest.TestCase): class PillowTestCase(unittest.TestCase):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
unittest.TestCase.__init__(self, *args, **kwargs) unittest.TestCase.__init__(self, *args, **kwargs)
self.currentResult = None # holds last result object passed to run method # holds last result object passed to run method:
self.currentResult = None
def run(self, result=None): def run(self, result=None):
self.currentResult = result # remember result for use later self.currentResult = result # remember result for use later
@ -123,6 +120,21 @@ class PillowTestCase(unittest.TestCase):
self.assertTrue(found) self.assertTrue(found)
return result return result
def skipKnownBadTest(self, msg=None, platform=None, travis=None):
# Skip if platform/travis matches, and
# PILLOW_RUN_KNOWN_BAD is not true in the environment.
if bool(os.environ.get('PILLOW_RUN_KNOWN_BAD', False)):
print (os.environ.get('PILLOW_RUN_KNOWN_BAD', False))
return
skip = True
if platform is not None:
skip = sys.platform.startswith(platform)
if travis is not None:
skip = skip and (travis == bool(os.environ.get('TRAVIS', False)))
if skip:
self.skipTest(msg or "Known Bad Test")
def tempfile(self, template): def tempfile(self, template):
assert template[:5] in ("temp.", "temp_") assert template[:5] in ("temp.", "temp_")
(fd, path) = tempfile.mkstemp(template[4:], template[:4]) (fd, path) = tempfile.mkstemp(template[4:], template[:4])
@ -131,6 +143,17 @@ class PillowTestCase(unittest.TestCase):
self.addCleanup(self.delete_tempfile, path) self.addCleanup(self.delete_tempfile, path)
return path return path
def open_withImagemagick(self, f):
if not imagemagick_available():
raise IOError()
outfile = self.tempfile("temp.png")
if command_succeeds(['convert', f, outfile]):
from PIL import Image
return Image.open(outfile)
raise IOError()
# helpers # helpers
import sys import sys
@ -184,14 +207,21 @@ def command_succeeds(cmd):
return False return False
return True return True
def djpeg_available(): def djpeg_available():
return command_succeeds(['djpeg', '--help']) return command_succeeds(['djpeg', '--help'])
def cjpeg_available(): def cjpeg_available():
return command_succeeds(['cjpeg', '--help']) return command_succeeds(['cjpeg', '--help'])
def netpbm_available(): def netpbm_available():
return command_succeeds(["ppmquant", "--help"]) and \ return (command_succeeds(["ppmquant", "--help"]) and
command_succeeds(["ppmtogif", "--help"]) command_succeeds(["ppmtogif", "--help"]))
def imagemagick_available():
return command_succeeds(['convert', '-version'])
# End of file # End of file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

BIN
Tests/images/iss634.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule from helper import unittest, PillowTestCase
import PIL import PIL
import PIL.Image import PIL.Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule from helper import unittest, PillowTestCase
from PIL import Image from PIL import Image
import os import os

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
try: try:
import cffi import cffi

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule from helper import unittest, PillowTestCase
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
from PIL import Image from PIL import Image
import io import io

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule from helper import unittest, PillowTestCase
from PIL import Image, EpsImagePlugin from PIL import Image, EpsImagePlugin
import io import io

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule from helper import unittest, PillowTestCase
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena, netpbm_available from helper import unittest, PillowTestCase, lena, netpbm_available
from PIL import Image from PIL import Image
from PIL import GifImagePlugin from PIL import GifImagePlugin
@ -106,6 +106,50 @@ class TestFileGif(PillowTestCase):
GifImagePlugin._save_netpbm(img, 0, tempfile) GifImagePlugin._save_netpbm(img, 0, tempfile)
self.assert_image_similar(img, Image.open(tempfile).convert("L"), 0) self.assert_image_similar(img, Image.open(tempfile).convert("L"), 0)
def test_seek(self):
img = Image.open("Tests/images/dispose_none.gif")
framecount = 0
try:
while True:
framecount += 1
img.seek(img.tell() +1)
except EOFError:
self.assertEqual(framecount, 5)
def test_dispose_none(self):
img = Image.open("Tests/images/dispose_none.gif")
try:
while True:
img.seek(img.tell() +1)
self.assertEqual(img.disposal_method, 1)
except EOFError:
pass
def test_dispose_background(self):
img = Image.open("Tests/images/dispose_bgnd.gif")
try:
while True:
img.seek(img.tell() +1)
self.assertEqual(img.disposal_method, 2)
except EOFError:
pass
def test_dispose_previous(self):
img = Image.open("Tests/images/dispose_prev.gif")
try:
while True:
img.seek(img.tell() +1)
self.assertEqual(img.disposal_method, 3)
except EOFError:
pass
def test_iss634(self):
img = Image.open("Tests/images/iss634.gif")
# seek to the second frame
img.seek(img.tell() +1)
# all transparent pixels should be replaced with the color from the first frame
self.assertEqual(img.histogram()[img.info['transparency']], 0)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule from helper import unittest, PillowTestCase
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule from helper import unittest, PillowTestCase
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena, py3 from helper import unittest, PillowTestCase, lena, py3
from helper import djpeg_available, cjpeg_available from helper import djpeg_available, cjpeg_available
import random import random

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule from helper import unittest, PillowTestCase
from PIL import Image from PIL import Image
from io import BytesIO from io import BytesIO

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena, py3 from helper import unittest, PillowTestCase, lena, py3
import os import os

View File

@ -1,4 +1,4 @@
from helper import unittest, tearDownModule from helper import unittest
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
from PIL import Image from PIL import Image

61
Tests/test_file_palm.py Normal file
View File

@ -0,0 +1,61 @@
from helper import unittest, PillowTestCase, lena, imagemagick_available
import os.path
class TestFilePalm(PillowTestCase):
_roundtrip = imagemagick_available()
def helper_save_as_palm(self, mode):
# Arrange
im = lena(mode)
outfile = self.tempfile("temp_" + mode + ".palm")
# Act
im.save(outfile)
# Assert
self.assertTrue(os.path.isfile(outfile))
self.assertGreater(os.path.getsize(outfile), 0)
def roundtrip(self, mode):
if not self._roundtrip:
return
im = lena(mode)
outfile = self.tempfile("temp.palm")
im.save(outfile)
converted = self.open_withImagemagick(outfile)
self.assert_image_equal(converted, im)
def test_monochrome(self):
# Arrange
mode = "1"
# Act / Assert
self.helper_save_as_palm(mode)
self.roundtrip(mode)
def test_p_mode(self):
# Arrange
mode = "P"
# Act / Assert
self.helper_save_as_palm(mode)
self.skipKnownBadTest("Palm P image is wrong")
self.roundtrip(mode)
def test_rgb_ioerror(self):
# Arrange
mode = "RGB"
# Act / Assert
self.assertRaises(IOError, lambda: self.helper_save_as_palm(mode))
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
import os.path import os.path

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
from io import BytesIO from io import BytesIO

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule from helper import unittest, PillowTestCase
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule from helper import unittest, PillowTestCase
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
from PIL import Image from PIL import Image
from PIL import SpiderImagePlugin from PIL import SpiderImagePlugin

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule from helper import unittest, PillowTestCase
from PIL import Image, TarIO from PIL import Image, TarIO

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena, py3 from helper import unittest, PillowTestCase, lena, py3
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
from PIL import Image, TiffImagePlugin, TiffTags from PIL import Image, TiffImagePlugin, TiffTags

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule from helper import unittest, PillowTestCase
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule from helper import unittest, PillowTestCase
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule from helper import unittest, PillowTestCase
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule from helper import unittest, PillowTestCase
from PIL import FontFile, BdfFontFile from PIL import FontFile, BdfFontFile

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule from helper import unittest, PillowTestCase
from PIL import Image, FontFile, PcfFontFile from PIL import Image, FontFile, PcfFontFile
from PIL import ImageFont, ImageDraw from PIL import ImageFont, ImageDraw

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule from helper import unittest, PillowTestCase
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule from helper import unittest, PillowTestCase
from PIL import Image from PIL import Image
@ -44,6 +44,17 @@ class TestImage(PillowTestCase):
file = self.tempfile("temp.ppm") file = self.tempfile("temp.ppm")
im._dump(file) im._dump(file)
def test_comparison_with_other_type(self):
# Arrange
item = Image.new('RGB', (25, 25), '#000')
num = 12
# Act/Assert
# Shouldn't cause AttributeError (#774)
self.assertFalse(item is None)
self.assertFalse(item == None)
self.assertFalse(item == num)
if __name__ == '__main__': if __name__ == '__main__':
unittest.main() unittest.main()

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, fromstring, tostring from helper import unittest, PillowTestCase, fromstring, tostring
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
from PIL import Image from PIL import Image
from PIL import ImageFilter from PIL import ImageFilter

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule from helper import unittest, PillowTestCase
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
class TestImageGetColors(PillowTestCase): class TestImageGetColors(PillowTestCase):

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
class TestImageGetData(PillowTestCase): class TestImageGetData(PillowTestCase):

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
class TestImageGetExtrema(PillowTestCase): class TestImageGetExtrema(PillowTestCase):

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena, py3 from helper import unittest, PillowTestCase, lena, py3
class TestImageGetIm(PillowTestCase): class TestImageGetIm(PillowTestCase):

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
class TestImageGetPalette(PillowTestCase): class TestImageGetPalette(PillowTestCase):

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule from helper import unittest, PillowTestCase
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
class TestImageHistogram(PillowTestCase): class TestImageHistogram(PillowTestCase):

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
class TestImageOffset(PillowTestCase): class TestImageOffset(PillowTestCase):

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
import sys import sys

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule from helper import unittest, PillowTestCase
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
import sys import sys

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
from PIL import ImagePalette from PIL import ImagePalette

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
class TestImageResize(PillowTestCase): class TestImageResize(PillowTestCase):

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
class TestImageRotate(PillowTestCase): class TestImageRotate(PillowTestCase):

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
class TestImageThumbnail(PillowTestCase): class TestImageThumbnail(PillowTestCase):

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena, fromstring from helper import unittest, PillowTestCase, lena, fromstring
class TestImageToBitmap(PillowTestCase): class TestImageToBitmap(PillowTestCase):

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
from PIL import Image from PIL import Image
from PIL import ImageChops from PIL import ImageChops

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
from PIL import Image from PIL import Image

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule from helper import unittest, PillowTestCase
from PIL import Image from PIL import Image
from PIL import ImageColor from PIL import ImageColor

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
from PIL import Image from PIL import Image
from PIL import ImageColor from PIL import ImageColor

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
from PIL import Image from PIL import Image
from PIL import ImageEnhance from PIL import ImageEnhance

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena, fromstring, tostring from helper import unittest, PillowTestCase, lena, fromstring, tostring
from io import BytesIO from io import BytesIO

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena, tostring from helper import unittest, PillowTestCase, lena, tostring
from PIL import Image from PIL import Image
from PIL import ImageFileIO from PIL import ImageFileIO

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule from helper import unittest, PillowTestCase
from PIL import ImageFilter from PIL import ImageFilter

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule from helper import unittest, PillowTestCase
from PIL import Image from PIL import Image
from PIL import ImageDraw from PIL import ImageDraw
@ -71,11 +71,25 @@ try:
self.assert_image_equal(img_path, img_filelike) self.assert_image_equal(img_path, img_filelike)
self._clean() self._clean()
def test_textsize_equal(self):
im = Image.new(mode='RGB', size=(300, 100))
draw = ImageDraw.Draw(im)
ttf = ImageFont.truetype(font_path, font_size)
txt = "Hello World!"
size = draw.textsize(txt, ttf)
draw.text((10, 10), txt, font=ttf)
draw.rectangle((10, 10, 10 + size[0], 10 + size[1]))
target = 'Tests/images/rectangle_surrounding_text.png'
target_img = Image.open(target)
self.assert_image_equal(im, target_img)
def test_render_multiline(self): def test_render_multiline(self):
im = Image.new(mode='RGB', size=(300, 100)) im = Image.new(mode='RGB', size=(300, 100))
draw = ImageDraw.Draw(im) draw = ImageDraw.Draw(im)
ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE) ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
line_spacing = draw.textsize('A', font=ttf)[1] + 8 line_spacing = draw.textsize('A', font=ttf)[1] + 4
lines = ['hey you', 'you are awesome', 'this looks awkward'] lines = ['hey you', 'you are awesome', 'this looks awkward']
y = 0 y = 0
for line in lines: for line in lines:

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule from helper import unittest, PillowTestCase
try: try:
from PIL import ImageGrab from PIL import ImageGrab

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule from helper import unittest, PillowTestCase
from PIL import Image from PIL import Image
from PIL import ImageMath from PIL import ImageMath

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule from helper import unittest, PillowTestCase
from PIL import ImageMode from PIL import ImageMode

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
from PIL import ImageOps from PIL import ImageOps

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule from helper import unittest, PillowTestCase
from PIL import Image from PIL import Image
from PIL import ImageOps from PIL import ImageOps

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule from helper import unittest, PillowTestCase
from PIL import ImagePalette from PIL import ImagePalette

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule from helper import unittest, PillowTestCase
from PIL import ImagePath from PIL import ImagePath

View File

@ -1,4 +1,4 @@
from helper import unittest, PillowTestCase, tearDownModule, lena from helper import unittest, PillowTestCase, lena
try: try:
from PIL import ImageQt from PIL import ImageQt

Some files were not shown because too many files have changed in this diff Show More