Merge from master

This commit is contained in:
wiredfool 2014-06-20 00:34:32 -07:00
commit 7dc4dcc9fd
134 changed files with 6076 additions and 4463 deletions

11
.coveragerc Normal file
View File

@ -0,0 +1,11 @@
# .coveragerc to control coverage.py
[report]
# Regexes for lines to exclude from consideration
exclude_lines =
# Have to re-enable the standard pragma:
pragma: no cover
# Don't complain if non-runnable code isn't run:
if 0:
if __name__ == .__main__.:

View File

@ -14,7 +14,8 @@ python:
install: install:
- "sudo apt-get -qq install libfreetype6-dev liblcms2-dev python-qt4 ghostscript libffi-dev cmake" - "sudo apt-get -qq install libfreetype6-dev liblcms2-dev python-qt4 ghostscript libffi-dev cmake"
- "pip install cffi" - "pip install cffi"
- "pip install coveralls" - "pip install coveralls nose"
- if [ "$TRAVIS_PYTHON_VERSION" == "2.6" ]; then pip install unittest2; fi
# webp # webp
- pushd depends && ./install_webp.sh && popd - pushd depends && ./install_webp.sh && popd
@ -28,18 +29,18 @@ script:
- python setup.py build_ext --inplace - python setup.py build_ext --inplace
# Don't cover PyPy: it fails intermittently and is x5.8 slower (#640) # Don't cover PyPy: it fails intermittently and is x5.8 slower (#640)
- if [ "$TRAVIS_PYTHON_VERSION" == "pypy" ]; then python selftest.py; fi - if [ "$TRAVIS_PYTHON_VERSION" == "pypy" ]; then time python selftest.py; fi
- if [ "$TRAVIS_PYTHON_VERSION" == "pypy" ]; then python Tests/run.py; fi - if [ "$TRAVIS_PYTHON_VERSION" == "pypy" ]; then time nosetests Tests/test_*.py; fi
# Cover the others # Cover the others
- if [ "$TRAVIS_PYTHON_VERSION" != "pypy" ]; then coverage run --append --include=PIL/* selftest.py; fi - if [ "$TRAVIS_PYTHON_VERSION" != "pypy" ]; then time coverage run --append --include=PIL/* selftest.py; fi
- if [ "$TRAVIS_PYTHON_VERSION" != "pypy" ]; then python Tests/run.py --coverage; fi - if [ "$TRAVIS_PYTHON_VERSION" != "pypy" ]; then time coverage run --append --include=PIL/* -m nose Tests/test_*.py; fi
after_success: after_success:
- coverage report - coverage report
- coveralls - coveralls
- pip install pep8 pyflakes - pip install pep8 pyflakes
- pep8 PIL/*.py - pep8 --statistics --count PIL/*.py
- pyflakes PIL/*.py - pep8 --statistics --count Tests/*.py
- pep8 Tests/*.py - pyflakes PIL/*.py | tee >(wc -l)
- pyflakes Tests/*.py - pyflakes Tests/*.py | tee >(wc -l)

View File

@ -3,33 +3,46 @@ Changelog (Pillow)
2.5.0 (unreleased) 2.5.0 (unreleased)
------------------ ------------------
- Use unittest for tests
[hugovk]
- ImageCms fixes
[hugovk]
- Added more ImageDraw tests
[hugovk]
- Added tests for Spider files
[hugovk]
- Use libtiff to write any compressed tiff files - Use libtiff to write any compressed tiff files
[wiredfool] [wiredfool]
- Support for pickling Image objects - Support for pickling Image objects
[hugovk] [hugovk]
- Fixed resolution handling for EPS thumbnails - Fixed resolution handling for EPS thumbnails
[eliempje] [eliempje]
- Fixed rendering of some binary EPS files (Issue #302) - Fixed rendering of some binary EPS files (Issue #302)
[eliempje] [eliempje]
- Rename variables not to use built-in function names - Rename variables not to use built-in function names
[hugovk] [hugovk]
- Ignore junk JPEG markers - Ignore junk JPEG markers
[hugovk] [hugovk]
- Change default interpolation for Image.thumbnail to Image.ANTIALIAS - Change default interpolation for Image.thumbnail to Image.ANTIALIAS
[hugovk] [hugovk]
- Add tests and fixes for saving PDFs - Add tests and fixes for saving PDFs
[hugovk] [hugovk]
- Remove transparency resource after P->RGBA conversion - Remove transparency resource after P->RGBA conversion
[hugovk] [hugovk]
- Clean up preprocessor cruft for Windows - Clean up preprocessor cruft for Windows
[CounterPillow] [CounterPillow]
@ -39,13 +52,13 @@ Changelog (Pillow)
- Added Image.close, context manager support. - Added Image.close, context manager support.
[wiredfool] [wiredfool]
- Added support for 16 bit PGM files. - Added support for 16 bit PGM files.
[wiredfool] [wiredfool]
- Updated OleFileIO to version 0.30 from upstream - Updated OleFileIO to version 0.30 from upstream
[hugovk] [hugovk]
- Added support for additional TIFF floating point format - Added support for additional TIFF floating point format
[Hijackal] [Hijackal]
- Have the tempfile use a suffix with a dot - Have the tempfile use a suffix with a dot
@ -75,7 +88,7 @@ Changelog (Pillow)
- Added support for JPEG 2000 - Added support for JPEG 2000
[al45tair] [al45tair]
- Add more detailed error messages to Image.py - Add more detailed error messages to Image.py
[larsmans] [larsmans]
- Avoid conflicting _expand functions in PIL & MINGW, fixes #538 - Avoid conflicting _expand functions in PIL & MINGW, fixes #538
@ -103,7 +116,7 @@ Changelog (Pillow)
[wiredfool] [wiredfool]
- Fixed palette handling when converting from mode P->RGB->P - Fixed palette handling when converting from mode P->RGB->P
[d_schmidt] [d_schmidt]
- Fixed saving mode P image as a PNG with transparency = palette color 0 - Fixed saving mode P image as a PNG with transparency = palette color 0
[d-schmidt] [d-schmidt]
@ -113,7 +126,7 @@ Changelog (Pillow)
- Fixed DOS with invalid palette size or invalid image size in BMP file - Fixed DOS with invalid palette size or invalid image size in BMP file
[wiredfool] [wiredfool]
- Added support for BMP version 4 and 5 - Added support for BMP version 4 and 5
[eddwardo, wiredfool] [eddwardo, wiredfool]
@ -146,7 +159,7 @@ Changelog (Pillow)
- Prefer homebrew freetype over X11 freetype (but still allow both) - Prefer homebrew freetype over X11 freetype (but still allow both)
[dmckeone] [dmckeone]
2.3.1 (2014-03-14) 2.3.1 (2014-03-14)
------------------ ------------------
@ -271,7 +284,7 @@ Changelog (Pillow)
[nikmolnar] [nikmolnar]
- Fix for encoding of b_whitespace, similar to closed issue #272 - Fix for encoding of b_whitespace, similar to closed issue #272
[mhogg] [mhogg]
- Fix #273: Add numpy array interface support for 16 and 32 bit integer modes - Fix #273: Add numpy array interface support for 16 and 32 bit integer modes
[cgohlke] [cgohlke]
@ -431,7 +444,7 @@ Changelog (Pillow)
- Add Python 3 support. (Pillow >= 2.0.0 supports Python 2.6, 2.7, 3.2, 3.3. Pillow < 2.0.0 supports Python 2.4, 2.5, 2.6, 2.7.) - Add Python 3 support. (Pillow >= 2.0.0 supports Python 2.6, 2.7, 3.2, 3.3. Pillow < 2.0.0 supports Python 2.4, 2.5, 2.6, 2.7.)
[fluggo] [fluggo]
- Add PyPy support (experimental, please see: https://github.com/python-imaging/Pillow/issues/67) - Add PyPy support (experimental, please see: https://github.com/python-pillow/Pillow/issues/67)
- Add WebP support. - Add WebP support.
[lqs] [lqs]

View File

@ -1529,7 +1529,7 @@ class Image:
clockwise around its centre. clockwise around its centre.
:param angle: In degrees counter clockwise. :param angle: In degrees counter clockwise.
:param filter: An optional resampling filter. This can be :param resample: An optional resampling filter. This can be
one of :py:attr:`PIL.Image.NEAREST` (use nearest neighbour), one of :py:attr:`PIL.Image.NEAREST` (use nearest neighbour),
:py:attr:`PIL.Image.BILINEAR` (linear interpolation in a 2x2 :py:attr:`PIL.Image.BILINEAR` (linear interpolation in a 2x2
environment), or :py:attr:`PIL.Image.BICUBIC` environment), or :py:attr:`PIL.Image.BICUBIC`
@ -1550,7 +1550,6 @@ class Image:
math.cos(angle), math.sin(angle), 0.0, math.cos(angle), math.sin(angle), 0.0,
-math.sin(angle), math.cos(angle), 0.0 -math.sin(angle), math.cos(angle), 0.0
] ]
def transform(x, y, matrix=matrix): def transform(x, y, matrix=matrix):
(a, b, c, d, e, f) = matrix (a, b, c, d, e, f) = matrix

View File

@ -1,19 +1,19 @@
# """
# The Python Imaging Library. The Python Imaging Library.
# $Id$ $Id$
#
# optional color managment support, based on Kevin Cazabon's PyCMS Optional color managment support, based on Kevin Cazabon's PyCMS
# library. library.
#
# History: History:
# 2009-03-08 fl Added to PIL. 2009-03-08 fl Added to PIL.
#
# Copyright (C) 2002-2003 Kevin Cazabon Copyright (C) 2002-2003 Kevin Cazabon
# Copyright (c) 2009 by Fredrik Lundh Copyright (c) 2009 by Fredrik Lundh
#
# See the README file for information on usage and redistribution. See See the README file for information on usage and redistribution. See
# below for the original description. below for the original description.
# """
from __future__ import print_function from __future__ import print_function
@ -66,7 +66,8 @@ pyCMS
Added try/except statements arount type() checks of Added try/except statements arount type() checks of
potential CObjects... Python won't let you use type() potential CObjects... Python won't let you use type()
on them, and raises a TypeError (stupid, if you ask me!) on them, and raises a TypeError (stupid, if you ask
me!)
Added buildProofTransformFromOpenProfiles() function. Added buildProofTransformFromOpenProfiles() function.
Additional fixes in DLL, see DLL code for details. Additional fixes in DLL, see DLL code for details.
@ -88,9 +89,9 @@ try:
from PIL import _imagingcms from PIL import _imagingcms
except ImportError as ex: except ImportError as ex:
# Allow error import for doc purposes, but error out when accessing # Allow error import for doc purposes, but error out when accessing
# anything in core. # anything in core.
from _util import deferred_error from _util import import_err
_imagingcms = deferred_error(ex) _imagingcms = import_err(ex)
from PIL._util import isStringType from PIL._util import isStringType
core = _imagingcms core = _imagingcms
@ -113,22 +114,24 @@ DIRECTION_PROOF = 2
FLAGS = { FLAGS = {
"MATRIXINPUT": 1, "MATRIXINPUT": 1,
"MATRIXOUTPUT": 2, "MATRIXOUTPUT": 2,
"MATRIXONLY": (1|2), "MATRIXONLY": (1 | 2),
"NOWHITEONWHITEFIXUP": 4, # Don't hot fix scum dot "NOWHITEONWHITEFIXUP": 4, # Don't hot fix scum dot
"NOPRELINEARIZATION": 16, # Don't create prelinearization tables on precalculated transforms (internal use) # Don't create prelinearization tables on precalculated transforms
"GUESSDEVICECLASS": 32, # Guess device class (for transform2devicelink) # (internal use):
"NOTCACHE": 64, # Inhibit 1-pixel cache "NOPRELINEARIZATION": 16,
"GUESSDEVICECLASS": 32, # Guess device class (for transform2devicelink)
"NOTCACHE": 64, # Inhibit 1-pixel cache
"NOTPRECALC": 256, "NOTPRECALC": 256,
"NULLTRANSFORM": 512, # Don't transform anyway "NULLTRANSFORM": 512, # Don't transform anyway
"HIGHRESPRECALC": 1024, # Use more memory to give better accurancy "HIGHRESPRECALC": 1024, # Use more memory to give better accurancy
"LOWRESPRECALC": 2048, # Use less memory to minimize resouces "LOWRESPRECALC": 2048, # Use less memory to minimize resouces
"WHITEBLACKCOMPENSATION": 8192, "WHITEBLACKCOMPENSATION": 8192,
"BLACKPOINTCOMPENSATION": 8192, "BLACKPOINTCOMPENSATION": 8192,
"GAMUTCHECK": 4096, # Out of Gamut alarm "GAMUTCHECK": 4096, # Out of Gamut alarm
"SOFTPROOFING": 16384, # Do softproofing "SOFTPROOFING": 16384, # Do softproofing
"PRESERVEBLACK": 32768, # Black preservation "PRESERVEBLACK": 32768, # Black preservation
"NODEFAULTRESOURCEDEF": 16777216, # CRD special "NODEFAULTRESOURCEDEF": 16777216, # CRD special
"GRIDPOINTS": lambda n: ((n) & 0xFF) << 16 # Gridpoints "GRIDPOINTS": lambda n: ((n) & 0xFF) << 16 # Gridpoints
} }
_MAX_FLAG = 0 _MAX_FLAG = 0
@ -136,6 +139,7 @@ for flag in FLAGS.values():
if isinstance(flag, int): if isinstance(flag, int):
_MAX_FLAG = _MAX_FLAG | flag _MAX_FLAG = _MAX_FLAG | flag
# --------------------------------------------------------------------. # --------------------------------------------------------------------.
# Experimental PIL-level API # Experimental PIL-level API
# --------------------------------------------------------------------. # --------------------------------------------------------------------.
@ -153,40 +157,42 @@ class ImageCmsProfile:
elif hasattr(profile, "read"): elif hasattr(profile, "read"):
self._set(core.profile_frombytes(profile.read())) self._set(core.profile_frombytes(profile.read()))
else: else:
self._set(profile) # assume it's already a profile self._set(profile) # assume it's already a profile
def _set(self, profile, filename=None): def _set(self, profile, filename=None):
self.profile = profile self.profile = profile
self.filename = filename self.filename = filename
if profile: if profile:
self.product_name = None #profile.product_name self.product_name = None # profile.product_name
self.product_info = None #profile.product_info self.product_info = None # profile.product_info
else: else:
self.product_name = None self.product_name = None
self.product_info = None self.product_info = None
class ImageCmsTransform(Image.ImagePointHandler): class ImageCmsTransform(Image.ImagePointHandler):
"""Transform. This can be used with the procedural API, or with the """Transform. This can be used with the procedural API, or with the
standard Image.point() method. standard Image.point() method.
""" """
def __init__(self, input, output, input_mode, output_mode, def __init__(self, input, output, input_mode, output_mode,
intent=INTENT_PERCEPTUAL, intent=INTENT_PERCEPTUAL, proof=None,
proof=None, proof_intent=INTENT_ABSOLUTE_COLORIMETRIC, flags=0): proof_intent=INTENT_ABSOLUTE_COLORIMETRIC, flags=0):
if proof is None: if proof is None:
self.transform = core.buildTransform( self.transform = core.buildTransform(
input.profile, output.profile, input.profile, output.profile,
input_mode, output_mode, input_mode, output_mode,
intent, intent,
flags flags
) )
else: else:
self.transform = core.buildProofTransform( self.transform = core.buildProofTransform(
input.profile, output.profile, proof.profile, input.profile, output.profile, proof.profile,
input_mode, output_mode, input_mode, output_mode,
intent, proof_intent, intent, proof_intent,
flags flags
) )
# Note: inputMode and outputMode are for pyCMS compatibility only # Note: inputMode and outputMode are for pyCMS compatibility only
self.input_mode = self.inputMode = input_mode self.input_mode = self.inputMode = input_mode
self.output_mode = self.outputMode = output_mode self.output_mode = self.outputMode = output_mode
@ -198,21 +204,22 @@ class ImageCmsTransform(Image.ImagePointHandler):
im.load() im.load()
if imOut is None: if imOut is None:
imOut = Image.new(self.output_mode, im.size, None) imOut = Image.new(self.output_mode, im.size, None)
result = self.transform.apply(im.im.id, imOut.im.id) self.transform.apply(im.im.id, imOut.im.id)
return imOut return imOut
def apply_in_place(self, im): def apply_in_place(self, im):
im.load() im.load()
if im.mode != self.output_mode: if im.mode != self.output_mode:
raise ValueError("mode mismatch") # wrong output mode raise ValueError("mode mismatch") # wrong output mode
result = self.transform.apply(im.im.id, im.im.id) self.transform.apply(im.im.id, im.im.id)
return im return im
def get_display_profile(handle=None): def get_display_profile(handle=None):
""" (experimental) Fetches the profile for the current display device. """ (experimental) Fetches the profile for the current display device.
:returns: None if the profile is not known. :returns: None if the profile is not known.
""" """
import sys import sys
if sys.platform == "win32": if sys.platform == "win32":
from PIL import ImageWin from PIL import ImageWin
@ -229,15 +236,21 @@ def get_display_profile(handle=None):
profile = get() profile = get()
return ImageCmsProfile(profile) return ImageCmsProfile(profile)
# --------------------------------------------------------------------. # --------------------------------------------------------------------.
# pyCMS compatible layer # pyCMS compatible layer
# --------------------------------------------------------------------. # --------------------------------------------------------------------.
class PyCMSError(Exception): class PyCMSError(Exception):
""" (pyCMS) Exception class. This is used for all errors in the pyCMS API. """
""" (pyCMS) Exception class.
This is used for all errors in the pyCMS API. """
pass pass
def profileToProfile(im, inputProfile, outputProfile, renderingIntent=INTENT_PERCEPTUAL, outputMode=None, inPlace=0, flags=0):
def profileToProfile(
im, inputProfile, outputProfile, renderingIntent=INTENT_PERCEPTUAL,
outputMode=None, inPlace=0, flags=0):
""" """
(pyCMS) Applies an ICC transformation to a given image, mapping from (pyCMS) Applies an ICC transformation to a given image, mapping from
inputProfile to outputProfile. inputProfile to outputProfile.
@ -259,40 +272,45 @@ def profileToProfile(im, inputProfile, outputProfile, renderingIntent=INTENT_PER
profiles, the input profile must handle RGB data, and the output profiles, the input profile must handle RGB data, and the output
profile must handle CMYK data. profile must handle CMYK data.
:param im: An open PIL image object (i.e. Image.new(...) or Image.open(...), etc.) :param im: An open PIL image object (i.e. Image.new(...) or
:param inputProfile: String, as a valid filename path to the ICC input profile Image.open(...), etc.)
you wish to use for this image, or a profile object :param inputProfile: String, as a valid filename path to the ICC input
profile you wish to use for this image, or a profile object
:param outputProfile: String, as a valid filename path to the ICC output :param outputProfile: String, as a valid filename path to the ICC output
profile you wish to use for this image, or a profile object profile you wish to use for this image, or a profile object
:param renderingIntent: Integer (0-3) specifying the rendering intent you wish :param renderingIntent: Integer (0-3) specifying the rendering intent you
to use for the transform wish to use for the transform
INTENT_PERCEPTUAL = 0 (DEFAULT) (ImageCms.INTENT_PERCEPTUAL) INTENT_PERCEPTUAL = 0 (DEFAULT) (ImageCms.INTENT_PERCEPTUAL)
INTENT_RELATIVE_COLORIMETRIC = 1 (ImageCms.INTENT_RELATIVE_COLORIMETRIC) INTENT_RELATIVE_COLORIMETRIC = 1 (ImageCms.INTENT_RELATIVE_COLORIMETRIC)
INTENT_SATURATION = 2 (ImageCms.INTENT_SATURATION) INTENT_SATURATION = 2 (ImageCms.INTENT_SATURATION)
INTENT_ABSOLUTE_COLORIMETRIC = 3 (ImageCms.INTENT_ABSOLUTE_COLORIMETRIC) INTENT_ABSOLUTE_COLORIMETRIC = 3 (ImageCms.INTENT_ABSOLUTE_COLORIMETRIC)
see the pyCMS documentation for details on rendering intents and what they do. see the pyCMS documentation for details on rendering intents and what
:param outputMode: A valid PIL mode for the output image (i.e. "RGB", "CMYK", they do.
etc.). Note: if rendering the image "inPlace", outputMode MUST be the :param outputMode: A valid PIL mode for the output image (i.e. "RGB",
same mode as the input, or omitted completely. If omitted, the outputMode "CMYK", etc.). Note: if rendering the image "inPlace", outputMode
will be the same as the mode of the input image (im.mode) MUST be the same mode as the input, or omitted completely. If
:param inPlace: Boolean (1 = True, None or 0 = False). If True, the original omitted, the outputMode will be the same as the mode of the input
image is modified in-place, and None is returned. If False (default), a image (im.mode)
new Image object is returned with the transform applied. :param inPlace: Boolean (1 = True, None or 0 = False). If True, the
original image is modified in-place, and None is returned. If False
(default), a new Image object is returned with the transform applied.
:param flags: Integer (0-...) specifying additional flags :param flags: Integer (0-...) specifying additional flags
:returns: Either None or a new PIL image object, depending on value of inPlace :returns: Either None or a new PIL image object, depending on value of
inPlace
:exception PyCMSError: :exception PyCMSError:
""" """
if outputMode is None: if outputMode is None:
outputMode = im.mode outputMode = im.mode
if not isinstance(renderingIntent, int) or not (0 <= renderingIntent <=3): if not isinstance(renderingIntent, int) or not (0 <= renderingIntent <= 3):
raise PyCMSError("renderingIntent must be an integer between 0 and 3") raise PyCMSError("renderingIntent must be an integer between 0 and 3")
if not isinstance(flags, int) or not (0 <= flags <= _MAX_FLAG): if not isinstance(flags, int) or not (0 <= flags <= _MAX_FLAG):
raise PyCMSError("flags must be an integer between 0 and %s" + _MAX_FLAG) raise PyCMSError(
"flags must be an integer between 0 and %s" + _MAX_FLAG)
try: try:
if not isinstance(inputProfile, ImageCmsProfile): if not isinstance(inputProfile, ImageCmsProfile):
@ -300,8 +318,9 @@ def profileToProfile(im, inputProfile, outputProfile, renderingIntent=INTENT_PER
if not isinstance(outputProfile, ImageCmsProfile): if not isinstance(outputProfile, ImageCmsProfile):
outputProfile = ImageCmsProfile(outputProfile) outputProfile = ImageCmsProfile(outputProfile)
transform = ImageCmsTransform( transform = ImageCmsTransform(
inputProfile, outputProfile, im.mode, outputMode, renderingIntent, flags=flags inputProfile, outputProfile, im.mode, outputMode,
) renderingIntent, flags=flags
)
if inPlace: if inPlace:
transform.apply_in_place(im) transform.apply_in_place(im)
imOut = None imOut = None
@ -323,8 +342,8 @@ def getOpenProfile(profileFilename):
If profileFilename is not a vaild filename for an ICC profile, a PyCMSError If profileFilename is not a vaild filename for an ICC profile, a PyCMSError
will be raised. will be raised.
:param profileFilename: String, as a valid filename path to the ICC profile you :param profileFilename: String, as a valid filename path to the ICC profile
wish to open, or a file-like object. you wish to open, or a file-like object.
:returns: A CmsProfile class object. :returns: A CmsProfile class object.
:exception PyCMSError: :exception PyCMSError:
""" """
@ -334,7 +353,10 @@ def getOpenProfile(profileFilename):
except (IOError, TypeError, ValueError) as v: except (IOError, TypeError, ValueError) as v:
raise PyCMSError(v) raise PyCMSError(v)
def buildTransform(inputProfile, outputProfile, inMode, outMode, renderingIntent=INTENT_PERCEPTUAL, flags=0):
def buildTransform(
inputProfile, outputProfile, inMode, outMode,
renderingIntent=INTENT_PERCEPTUAL, flags=0):
""" """
(pyCMS) Builds an ICC transform mapping from the inputProfile to the (pyCMS) Builds an ICC transform mapping from the inputProfile to the
outputProfile. Use applyTransform to apply the transform to a given outputProfile. Use applyTransform to apply the transform to a given
@ -367,14 +389,14 @@ def buildTransform(inputProfile, outputProfile, inMode, outMode, renderingIntent
manually overridden if you really want to, but I don't know of any manually overridden if you really want to, but I don't know of any
time that would be of use, or would even work). time that would be of use, or would even work).
:param inputProfile: String, as a valid filename path to the ICC input profile :param inputProfile: String, as a valid filename path to the ICC input
you wish to use for this transform, or a profile object profile you wish to use for this transform, or a profile object
:param outputProfile: String, as a valid filename path to the ICC output :param outputProfile: String, as a valid filename path to the ICC output
profile you wish to use for this transform, or a profile object profile you wish to use for this transform, or a profile object
:param inMode: String, as a valid PIL mode that the appropriate profile also :param inMode: String, as a valid PIL mode that the appropriate profile
supports (i.e. "RGB", "RGBA", "CMYK", etc.) also supports (i.e. "RGB", "RGBA", "CMYK", etc.)
:param outMode: String, as a valid PIL mode that the appropriate profile also :param outMode: String, as a valid PIL mode that the appropriate profile
supports (i.e. "RGB", "RGBA", "CMYK", etc.) also supports (i.e. "RGB", "RGBA", "CMYK", etc.)
:param renderingIntent: Integer (0-3) specifying the rendering intent you :param renderingIntent: Integer (0-3) specifying the rendering intent you
wish to use for the transform wish to use for the transform
@ -383,28 +405,37 @@ def buildTransform(inputProfile, outputProfile, inMode, outMode, renderingIntent
INTENT_SATURATION = 2 (ImageCms.INTENT_SATURATION) INTENT_SATURATION = 2 (ImageCms.INTENT_SATURATION)
INTENT_ABSOLUTE_COLORIMETRIC = 3 (ImageCms.INTENT_ABSOLUTE_COLORIMETRIC) INTENT_ABSOLUTE_COLORIMETRIC = 3 (ImageCms.INTENT_ABSOLUTE_COLORIMETRIC)
see the pyCMS documentation for details on rendering intents and what they do. see the pyCMS documentation for details on rendering intents and what
they do.
:param flags: Integer (0-...) specifying additional flags :param flags: Integer (0-...) specifying additional flags
:returns: A CmsTransform class object. :returns: A CmsTransform class object.
:exception PyCMSError: :exception PyCMSError:
""" """
if not isinstance(renderingIntent, int) or not (0 <= renderingIntent <=3): if not isinstance(renderingIntent, int) or not (0 <= renderingIntent <= 3):
raise PyCMSError("renderingIntent must be an integer between 0 and 3") raise PyCMSError("renderingIntent must be an integer between 0 and 3")
if not isinstance(flags, int) or not (0 <= flags <= _MAX_FLAG): if not isinstance(flags, int) or not (0 <= flags <= _MAX_FLAG):
raise PyCMSError("flags must be an integer between 0 and %s" + _MAX_FLAG) raise PyCMSError(
"flags must be an integer between 0 and %s" + _MAX_FLAG)
try: try:
if not isinstance(inputProfile, ImageCmsProfile): if not isinstance(inputProfile, ImageCmsProfile):
inputProfile = ImageCmsProfile(inputProfile) inputProfile = ImageCmsProfile(inputProfile)
if not isinstance(outputProfile, ImageCmsProfile): if not isinstance(outputProfile, ImageCmsProfile):
outputProfile = ImageCmsProfile(outputProfile) outputProfile = ImageCmsProfile(outputProfile)
return ImageCmsTransform(inputProfile, outputProfile, inMode, outMode, renderingIntent, flags=flags) return ImageCmsTransform(
inputProfile, outputProfile, inMode, outMode,
renderingIntent, flags=flags)
except (IOError, TypeError, ValueError) as v: except (IOError, TypeError, ValueError) as v:
raise PyCMSError(v) raise PyCMSError(v)
def buildProofTransform(inputProfile, outputProfile, proofProfile, inMode, outMode, renderingIntent=INTENT_PERCEPTUAL, proofRenderingIntent=INTENT_ABSOLUTE_COLORIMETRIC, flags=FLAGS["SOFTPROOFING"]):
def buildProofTransform(
inputProfile, outputProfile, proofProfile, inMode, outMode,
renderingIntent=INTENT_PERCEPTUAL,
proofRenderingIntent=INTENT_ABSOLUTE_COLORIMETRIC,
flags=FLAGS["SOFTPROOFING"]):
""" """
(pyCMS) Builds an ICC transform mapping from the inputProfile to the (pyCMS) Builds an ICC transform mapping from the inputProfile to the
outputProfile, but tries to simulate the result that would be outputProfile, but tries to simulate the result that would be
@ -443,17 +474,17 @@ def buildProofTransform(inputProfile, outputProfile, proofProfile, inMode, outMo
when the simulated device has a much wider gamut than the output when the simulated device has a much wider gamut than the output
device, you may obtain marginal results. device, you may obtain marginal results.
:param inputProfile: String, as a valid filename path to the ICC input profile :param inputProfile: String, as a valid filename path to the ICC input
you wish to use for this transform, or a profile object profile you wish to use for this transform, or a profile object
:param outputProfile: String, as a valid filename path to the ICC output :param outputProfile: String, as a valid filename path to the ICC output
(monitor, usually) profile you wish to use for this transform, or a (monitor, usually) profile you wish to use for this transform, or a
profile object profile object
:param proofProfile: String, as a valid filename path to the ICC proof profile :param proofProfile: String, as a valid filename path to the ICC proof
you wish to use for this transform, or a profile object profile you wish to use for this transform, or a profile object
:param inMode: String, as a valid PIL mode that the appropriate profile also :param inMode: String, as a valid PIL mode that the appropriate profile
supports (i.e. "RGB", "RGBA", "CMYK", etc.) also supports (i.e. "RGB", "RGBA", "CMYK", etc.)
:param outMode: String, as a valid PIL mode that the appropriate profile also :param outMode: String, as a valid PIL mode that the appropriate profile
supports (i.e. "RGB", "RGBA", "CMYK", etc.) also supports (i.e. "RGB", "RGBA", "CMYK", etc.)
:param renderingIntent: Integer (0-3) specifying the rendering intent you :param renderingIntent: Integer (0-3) specifying the rendering intent you
wish to use for the input->proof (simulated) transform wish to use for the input->proof (simulated) transform
@ -462,7 +493,8 @@ def buildProofTransform(inputProfile, outputProfile, proofProfile, inMode, outMo
INTENT_SATURATION = 2 (ImageCms.INTENT_SATURATION) INTENT_SATURATION = 2 (ImageCms.INTENT_SATURATION)
INTENT_ABSOLUTE_COLORIMETRIC = 3 (ImageCms.INTENT_ABSOLUTE_COLORIMETRIC) INTENT_ABSOLUTE_COLORIMETRIC = 3 (ImageCms.INTENT_ABSOLUTE_COLORIMETRIC)
see the pyCMS documentation for details on rendering intents and what they do. see the pyCMS documentation for details on rendering intents and what
they do.
:param proofRenderingIntent: Integer (0-3) specifying the rendering intent you :param proofRenderingIntent: Integer (0-3) specifying the rendering intent you
wish to use for proof->output transform wish to use for proof->output transform
@ -471,17 +503,19 @@ def buildProofTransform(inputProfile, outputProfile, proofProfile, inMode, outMo
INTENT_SATURATION = 2 (ImageCms.INTENT_SATURATION) INTENT_SATURATION = 2 (ImageCms.INTENT_SATURATION)
INTENT_ABSOLUTE_COLORIMETRIC = 3 (ImageCms.INTENT_ABSOLUTE_COLORIMETRIC) INTENT_ABSOLUTE_COLORIMETRIC = 3 (ImageCms.INTENT_ABSOLUTE_COLORIMETRIC)
see the pyCMS documentation for details on rendering intents and what they do. see the pyCMS documentation for details on rendering intents and what
they do.
:param flags: Integer (0-...) specifying additional flags :param flags: Integer (0-...) specifying additional flags
:returns: A CmsTransform class object. :returns: A CmsTransform class object.
:exception PyCMSError: :exception PyCMSError:
""" """
if not isinstance(renderingIntent, int) or not (0 <= renderingIntent <=3): if not isinstance(renderingIntent, int) or not (0 <= renderingIntent <= 3):
raise PyCMSError("renderingIntent must be an integer between 0 and 3") raise PyCMSError("renderingIntent must be an integer between 0 and 3")
if not isinstance(flags, int) or not (0 <= flags <= _MAX_FLAG): if not isinstance(flags, int) or not (0 <= flags <= _MAX_FLAG):
raise PyCMSError("flags must be an integer between 0 and %s" + _MAX_FLAG) raise PyCMSError(
"flags must be an integer between 0 and %s" + _MAX_FLAG)
try: try:
if not isinstance(inputProfile, ImageCmsProfile): if not isinstance(inputProfile, ImageCmsProfile):
@ -490,13 +524,16 @@ def buildProofTransform(inputProfile, outputProfile, proofProfile, inMode, outMo
outputProfile = ImageCmsProfile(outputProfile) outputProfile = ImageCmsProfile(outputProfile)
if not isinstance(proofProfile, ImageCmsProfile): if not isinstance(proofProfile, ImageCmsProfile):
proofProfile = ImageCmsProfile(proofProfile) proofProfile = ImageCmsProfile(proofProfile)
return ImageCmsTransform(inputProfile, outputProfile, inMode, outMode, renderingIntent, proofProfile, proofRenderingIntent, flags) return ImageCmsTransform(
inputProfile, outputProfile, inMode, outMode, renderingIntent,
proofProfile, proofRenderingIntent, flags)
except (IOError, TypeError, ValueError) as v: except (IOError, TypeError, ValueError) as v:
raise PyCMSError(v) raise PyCMSError(v)
buildTransformFromOpenProfiles = buildTransform buildTransformFromOpenProfiles = buildTransform
buildProofTransformFromOpenProfiles = buildProofTransform buildProofTransformFromOpenProfiles = buildProofTransform
def applyTransform(im, transform, inPlace=0): def applyTransform(im, transform, inPlace=0):
""" """
(pyCMS) Applies a transform to a given image. (pyCMS) Applies a transform to a given image.
@ -514,8 +551,8 @@ def applyTransform(im, transform, inPlace=0):
is raised. is raised.
This function applies a pre-calculated transform (from This function applies a pre-calculated transform (from
ImageCms.buildTransform() or ImageCms.buildTransformFromOpenProfiles()) to an ImageCms.buildTransform() or ImageCms.buildTransformFromOpenProfiles())
image. The transform can be used for multiple images, saving to an image. The transform can be used for multiple images, saving
considerable calcuation time if doing the same conversion multiple times. considerable calcuation time if doing the same conversion multiple times.
If you want to modify im in-place instead of receiving a new image as If you want to modify im in-place instead of receiving a new image as
@ -528,10 +565,12 @@ def applyTransform(im, transform, inPlace=0):
:param im: A PIL Image object, and im.mode must be the same as the inMode :param im: A PIL Image object, and im.mode must be the same as the inMode
supported by the transform. supported by the transform.
:param transform: A valid CmsTransform class object :param transform: A valid CmsTransform class object
:param inPlace: Bool (1 == True, 0 or None == False). If True, im is modified :param inPlace: Bool (1 == True, 0 or None == False). If True, im is
in place and None is returned, if False, a new Image object with the modified in place and None is returned, if False, a new Image object
transform applied is returned (and im is not changed). The default is False. with the transform applied is returned (and im is not changed). The
:returns: Either None, or a new PIL Image object, depending on the value of inPlace default is False.
:returns: Either None, or a new PIL Image object, depending on the value of
inPlace
:exception PyCMSError: :exception PyCMSError:
""" """
@ -546,6 +585,7 @@ def applyTransform(im, transform, inPlace=0):
return imOut return imOut
def createProfile(colorSpace, colorTemp=-1): def createProfile(colorSpace, colorTemp=-1):
""" """
(pyCMS) Creates a profile. (pyCMS) Creates a profile.
@ -562,30 +602,36 @@ def createProfile(colorSpace, colorTemp=-1):
ImageCms.buildTransformFromOpenProfiles() to create a transform to apply ImageCms.buildTransformFromOpenProfiles() to create a transform to apply
to images. to images.
:param colorSpace: String, the color space of the profile you wish to create. :param colorSpace: String, the color space of the profile you wish to
create.
Currently only "LAB", "XYZ", and "sRGB" are supported. Currently only "LAB", "XYZ", and "sRGB" are supported.
:param colorTemp: Positive integer for the white point for the profile, in :param colorTemp: Positive integer for the white point for the profile, in
degrees Kelvin (i.e. 5000, 6500, 9600, etc.). The default is for D50 degrees Kelvin (i.e. 5000, 6500, 9600, etc.). The default is for D50
illuminant if omitted (5000k). colorTemp is ONLY applied to LAB profiles, illuminant if omitted (5000k). colorTemp is ONLY applied to LAB
and is ignored for XYZ and sRGB. profiles, and is ignored for XYZ and sRGB.
:returns: A CmsProfile class object :returns: A CmsProfile class object
:exception PyCMSError: :exception PyCMSError:
""" """
if colorSpace not in ["LAB", "XYZ", "sRGB"]: if colorSpace not in ["LAB", "XYZ", "sRGB"]:
raise PyCMSError("Color space not supported for on-the-fly profile creation (%s)" % colorSpace) raise PyCMSError(
"Color space not supported for on-the-fly profile creation (%s)"
% colorSpace)
if colorSpace == "LAB": if colorSpace == "LAB":
try: try:
colorTemp = float(colorTemp) colorTemp = float(colorTemp)
except: except:
raise PyCMSError("Color temperature must be numeric, \"%s\" not valid" % colorTemp) raise PyCMSError(
"Color temperature must be numeric, \"%s\" not valid"
% colorTemp)
try: try:
return core.createProfile(colorSpace, colorTemp) return core.createProfile(colorSpace, colorTemp)
except (TypeError, ValueError) as v: except (TypeError, ValueError) as v:
raise PyCMSError(v) raise PyCMSError(v)
def getProfileName(profile): def getProfileName(profile):
""" """
@ -600,10 +646,10 @@ def getProfileName(profile):
profile was originally created. Sometimes this tag also contains profile was originally created. Sometimes this tag also contains
additional information supplied by the creator. additional information supplied by the creator.
:param profile: EITHER a valid CmsProfile object, OR a string of the filename :param profile: EITHER a valid CmsProfile object, OR a string of the
of an ICC profile. filename of an ICC profile.
:returns: A string containing the internal name of the profile as stored in an :returns: A string containing the internal name of the profile as stored
ICC tag. in an ICC tag.
:exception PyCMSError: :exception PyCMSError:
""" """
@ -612,14 +658,14 @@ def getProfileName(profile):
if not isinstance(profile, ImageCmsProfile): if not isinstance(profile, ImageCmsProfile):
profile = ImageCmsProfile(profile) profile = ImageCmsProfile(profile)
# do it in python, not c. # do it in python, not c.
# // name was "%s - %s" (model, manufacturer) || Description , # // name was "%s - %s" (model, manufacturer) || Description ,
# // but if the Model and Manufacturer were the same or the model # // but if the Model and Manufacturer were the same or the model
# // was long, Just the model, in 1.x # // was long, Just the model, in 1.x
model = profile.profile.product_model model = profile.profile.product_model
manufacturer = profile.profile.product_manufacturer manufacturer = profile.profile.product_manufacturer
if not (model or manufacturer): if not (model or manufacturer):
return profile.profile.product_description+"\n" return profile.profile.product_description + "\n"
if not manufacturer or len(model) > 30: if not manufacturer or len(model) > 30:
return model + "\n" return model + "\n"
return "%s - %s\n" % (model, manufacturer) return "%s - %s\n" % (model, manufacturer)
@ -627,6 +673,7 @@ def getProfileName(profile):
except (AttributeError, IOError, TypeError, ValueError) as v: except (AttributeError, IOError, TypeError, ValueError) as v:
raise PyCMSError(v) raise PyCMSError(v)
def getProfileInfo(profile): def getProfileInfo(profile):
""" """
(pyCMS) Gets the internal product information for the given profile. (pyCMS) Gets the internal product information for the given profile.
@ -641,18 +688,19 @@ def getProfileInfo(profile):
info tag. This often contains details about the profile, and how it info tag. This often contains details about the profile, and how it
was created, as supplied by the creator. was created, as supplied by the creator.
:param profile: EITHER a valid CmsProfile object, OR a string of the filename :param profile: EITHER a valid CmsProfile object, OR a string of the
of an ICC profile. filename of an ICC profile.
:returns: A string containing the internal profile information stored in an ICC :returns: A string containing the internal profile information stored in
tag. an ICC tag.
:exception PyCMSError: :exception PyCMSError:
""" """
try: try:
if not isinstance(profile, ImageCmsProfile): if not isinstance(profile, ImageCmsProfile):
profile = ImageCmsProfile(profile) profile = ImageCmsProfile(profile)
# add an extra newline to preserve pyCMS compatibility # add an extra newline to preserve pyCMS compatibility
# Python, not C. the white point bits weren't working well, so skipping. # Python, not C. the white point bits weren't working well,
# so skipping.
# // info was description \r\n\r\n copyright \r\n\r\n K007 tag \r\n\r\n whitepoint # // info was description \r\n\r\n copyright \r\n\r\n K007 tag \r\n\r\n whitepoint
description = profile.profile.product_description description = profile.profile.product_description
cpright = profile.profile.product_copyright cpright = profile.profile.product_copyright
@ -660,7 +708,7 @@ def getProfileInfo(profile):
for elt in (description, cpright): for elt in (description, cpright):
if elt: if elt:
arr.append(elt) arr.append(elt)
return "\r\n\r\n".join(arr)+"\r\n\r\n" return "\r\n\r\n".join(arr) + "\r\n\r\n"
except (AttributeError, IOError, TypeError, ValueError) as v: except (AttributeError, IOError, TypeError, ValueError) as v:
raise PyCMSError(v) raise PyCMSError(v)
@ -677,12 +725,12 @@ def getProfileCopyright(profile):
is raised is raised
Use this function to obtain the information stored in the profile's Use this function to obtain the information stored in the profile's
copyright tag. copyright tag.
:param profile: EITHER a valid CmsProfile object, OR a string of the filename :param profile: EITHER a valid CmsProfile object, OR a string of the
of an ICC profile. filename of an ICC profile.
:returns: A string containing the internal profile information stored in an ICC :returns: A string containing the internal profile information stored in
tag. an ICC tag.
:exception PyCMSError: :exception PyCMSError:
""" """
try: try:
@ -693,6 +741,7 @@ def getProfileCopyright(profile):
except (AttributeError, IOError, TypeError, ValueError) as v: except (AttributeError, IOError, TypeError, ValueError) as v:
raise PyCMSError(v) raise PyCMSError(v)
def getProfileManufacturer(profile): def getProfileManufacturer(profile):
""" """
(pyCMS) Gets the manufacturer for the given profile. (pyCMS) Gets the manufacturer for the given profile.
@ -700,16 +749,16 @@ def getProfileManufacturer(profile):
If profile isn't a valid CmsProfile object or filename to a profile, If profile isn't a valid CmsProfile object or filename to a profile,
a PyCMSError is raised. a PyCMSError is raised.
If an error occurs while trying to obtain the manufacturer tag, a PyCMSError If an error occurs while trying to obtain the manufacturer tag, a
is raised PyCMSError is raised
Use this function to obtain the information stored in the profile's Use this function to obtain the information stored in the profile's
manufacturer tag. manufacturer tag.
:param profile: EITHER a valid CmsProfile object, OR a string of the filename :param profile: EITHER a valid CmsProfile object, OR a string of the
of an ICC profile. filename of an ICC profile.
:returns: A string containing the internal profile information stored in an ICC :returns: A string containing the internal profile information stored in
tag. an ICC tag.
:exception PyCMSError: :exception PyCMSError:
""" """
try: try:
@ -720,23 +769,24 @@ def getProfileManufacturer(profile):
except (AttributeError, IOError, TypeError, ValueError) as v: except (AttributeError, IOError, TypeError, ValueError) as v:
raise PyCMSError(v) raise PyCMSError(v)
def getProfileModel(profile): def getProfileModel(profile):
""" """
(pyCMS) Gets the model for the given profile. (pyCMS) Gets the model for the given profile.
If profile isn't a valid CmsProfile object or filename to a profile, If profile isn't a valid CmsProfile object or filename to a profile,
a PyCMSError is raised. a PyCMSError is raised.
If an error occurs while trying to obtain the model tag, a PyCMSError If an error occurs while trying to obtain the model tag, a PyCMSError
is raised is raised
Use this function to obtain the information stored in the profile's Use this function to obtain the information stored in the profile's
model tag. model tag.
:param profile: EITHER a valid CmsProfile object, OR a string of the filename :param profile: EITHER a valid CmsProfile object, OR a string of the
of an ICC profile. filename of an ICC profile.
:returns: A string containing the internal profile information stored in an ICC :returns: A string containing the internal profile information stored in
tag. an ICC tag.
:exception PyCMSError: :exception PyCMSError:
""" """
@ -748,6 +798,7 @@ def getProfileModel(profile):
except (AttributeError, IOError, TypeError, ValueError) as v: except (AttributeError, IOError, TypeError, ValueError) as v:
raise PyCMSError(v) raise PyCMSError(v)
def getProfileDescription(profile): def getProfileDescription(profile):
""" """
(pyCMS) Gets the description for the given profile. (pyCMS) Gets the description for the given profile.
@ -759,12 +810,12 @@ def getProfileDescription(profile):
is raised is raised
Use this function to obtain the information stored in the profile's Use this function to obtain the information stored in the profile's
description tag. description tag.
:param profile: EITHER a valid CmsProfile object, OR a string of the filename :param profile: EITHER a valid CmsProfile object, OR a string of the
of an ICC profile. filename of an ICC profile.
:returns: A string containing the internal profile information stored in an ICC :returns: A string containing the internal profile information stored in an
tag. ICC tag.
:exception PyCMSError: :exception PyCMSError:
""" """
@ -793,16 +844,18 @@ def getDefaultIntent(profile):
If you wish to use a different intent than returned, use If you wish to use a different intent than returned, use
ImageCms.isIntentSupported() to verify it will work first. ImageCms.isIntentSupported() to verify it will work first.
:param profile: EITHER a valid CmsProfile object, OR a string of the filename :param profile: EITHER a valid CmsProfile object, OR a string of the
of an ICC profile. filename of an ICC profile.
:returns: Integer 0-3 specifying the default rendering intent for this profile. :returns: Integer 0-3 specifying the default rendering intent for this
profile.
INTENT_PERCEPTUAL = 0 (DEFAULT) (ImageCms.INTENT_PERCEPTUAL) INTENT_PERCEPTUAL = 0 (DEFAULT) (ImageCms.INTENT_PERCEPTUAL)
INTENT_RELATIVE_COLORIMETRIC = 1 (ImageCms.INTENT_RELATIVE_COLORIMETRIC) INTENT_RELATIVE_COLORIMETRIC = 1 (ImageCms.INTENT_RELATIVE_COLORIMETRIC)
INTENT_SATURATION = 2 (ImageCms.INTENT_SATURATION) INTENT_SATURATION = 2 (ImageCms.INTENT_SATURATION)
INTENT_ABSOLUTE_COLORIMETRIC = 3 (ImageCms.INTENT_ABSOLUTE_COLORIMETRIC) INTENT_ABSOLUTE_COLORIMETRIC = 3 (ImageCms.INTENT_ABSOLUTE_COLORIMETRIC)
see the pyCMS documentation for details on rendering intents and what they do. see the pyCMS documentation for details on rendering intents and what
they do.
:exception PyCMSError: :exception PyCMSError:
""" """
@ -813,6 +866,7 @@ def getDefaultIntent(profile):
except (AttributeError, IOError, TypeError, ValueError) as v: except (AttributeError, IOError, TypeError, ValueError) as v:
raise PyCMSError(v) raise PyCMSError(v)
def isIntentSupported(profile, intent, direction): def isIntentSupported(profile, intent, direction):
""" """
(pyCMS) Checks if a given intent is supported. (pyCMS) Checks if a given intent is supported.
@ -828,17 +882,18 @@ def isIntentSupported(profile, intent, direction):
potential PyCMSError that will occur if they don't support the modes potential PyCMSError that will occur if they don't support the modes
you select. you select.
:param profile: EITHER a valid CmsProfile object, OR a string of the filename :param profile: EITHER a valid CmsProfile object, OR a string of the
of an ICC profile. filename of an ICC profile.
:param intent: Integer (0-3) specifying the rendering intent you wish to use :param intent: Integer (0-3) specifying the rendering intent you wish to
with this profile use with this profile
INTENT_PERCEPTUAL = 0 (DEFAULT) (ImageCms.INTENT_PERCEPTUAL) INTENT_PERCEPTUAL = 0 (DEFAULT) (ImageCms.INTENT_PERCEPTUAL)
INTENT_RELATIVE_COLORIMETRIC = 1 (ImageCms.INTENT_RELATIVE_COLORIMETRIC) INTENT_RELATIVE_COLORIMETRIC = 1 (ImageCms.INTENT_RELATIVE_COLORIMETRIC)
INTENT_SATURATION = 2 (ImageCms.INTENT_SATURATION) INTENT_SATURATION = 2 (ImageCms.INTENT_SATURATION)
INTENT_ABSOLUTE_COLORIMETRIC = 3 (ImageCms.INTENT_ABSOLUTE_COLORIMETRIC) INTENT_ABSOLUTE_COLORIMETRIC = 3 (ImageCms.INTENT_ABSOLUTE_COLORIMETRIC)
see the pyCMS documentation for details on rendering intents and what they do. see the pyCMS documentation for details on rendering intents and what
they do.
:param direction: Integer specifing if the profile is to be used for input, :param direction: Integer specifing if the profile is to be used for input,
output, or proof output, or proof
@ -862,15 +917,17 @@ def isIntentSupported(profile, intent, direction):
except (AttributeError, IOError, TypeError, ValueError) as v: except (AttributeError, IOError, TypeError, ValueError) as v:
raise PyCMSError(v) raise PyCMSError(v)
def versions(): def versions():
""" """
(pyCMS) Fetches versions. (pyCMS) Fetches versions.
""" """
import sys import sys
return ( return (
VERSION, core.littlecms_version, sys.version.split()[0], Image.VERSION VERSION, core.littlecms_version,
) sys.version.split()[0], Image.VERSION
)
# -------------------------------------------------------------------- # --------------------------------------------------------------------
@ -880,14 +937,16 @@ if __name__ == "__main__":
from PIL import ImageCms from PIL import ImageCms
print(__doc__) print(__doc__)
for f in dir(pyCMS): for f in dir(ImageCms):
print("="*80) doc = None
print("%s" %f)
try: try:
exec ("doc = ImageCms.%s.__doc__" %(f)) exec("doc = %s.__doc__" % (f))
if "pyCMS" in doc: if "pyCMS" in doc:
# so we don't get the __doc__ string for imported modules # so we don't get the __doc__ string for imported modules
print("=" * 80)
print("%s" % f)
print(doc) print(doc)
except AttributeError: except (AttributeError, TypeError):
pass pass
# End of file

View File

@ -15,20 +15,21 @@
__version__ = "0.1" __version__ = "0.1"
from PIL import Image, ImageFile, _binary from PIL import Image, ImageFile
import struct import struct
import os import os
import io import io
def _parse_codestream(fp): def _parse_codestream(fp):
"""Parse the JPEG 2000 codestream to extract the size and component """Parse the JPEG 2000 codestream to extract the size and component
count from the SIZ marker segment, returning a PIL (size, mode) tuple.""" count from the SIZ marker segment, returning a PIL (size, mode) tuple."""
hdr = fp.read(2) hdr = fp.read(2)
lsiz = struct.unpack('>H', hdr)[0] lsiz = struct.unpack('>H', hdr)[0]
siz = hdr + fp.read(lsiz - 2) siz = hdr + fp.read(lsiz - 2)
lsiz, rsiz, xsiz, ysiz, xosiz, yosiz, xtsiz, ytsiz, \ lsiz, rsiz, xsiz, ysiz, xosiz, yosiz, xtsiz, ytsiz, \
xtosiz, ytosiz, csiz \ xtosiz, ytosiz, csiz \
= struct.unpack('>HHIIIIIIIIH', siz[:38]) = struct.unpack('>HHIIIIIIIIH', siz[:38])
ssiz = [None]*csiz ssiz = [None]*csiz
xrsiz = [None]*csiz xrsiz = [None]*csiz
@ -48,13 +49,14 @@ def _parse_codestream(fp):
mode == 'RGBA' mode == 'RGBA'
else: else:
mode = None mode = None
return (size, mode) return (size, mode)
def _parse_jp2_header(fp): def _parse_jp2_header(fp):
"""Parse the JP2 header box to extract size, component count and """Parse the JP2 header box to extract size, component count and
color space information, returning a PIL (size, mode) tuple.""" color space information, returning a PIL (size, mode) tuple."""
# Find the JP2 header box # Find the JP2 header box
header = None header = None
while True: while True:
@ -76,7 +78,7 @@ def _parse_jp2_header(fp):
size = None size = None
mode = None mode = None
hio = io.BytesIO(header) hio = io.BytesIO(header)
while True: while True:
lbox, tbox = struct.unpack('>I4s', hio.read(8)) lbox, tbox = struct.unpack('>I4s', hio.read(8))
@ -90,7 +92,7 @@ def _parse_jp2_header(fp):
if tbox == b'ihdr': if tbox == b'ihdr':
height, width, nc, bpc, c, unkc, ipr \ height, width, nc, bpc, c, unkc, ipr \
= struct.unpack('>IIHBBBB', content) = struct.unpack('>IIHBBBB', content)
size = (width, height) size = (width, height)
if unkc: if unkc:
if nc == 1: if nc == 1:
@ -112,13 +114,13 @@ def _parse_jp2_header(fp):
elif nc == 4: elif nc == 4:
mode = 'RGBA' mode = 'RGBA'
break break
elif cs == 17: # grayscale elif cs == 17: # grayscale
if nc == 1: if nc == 1:
mode = 'L' mode = 'L'
elif nc == 2: elif nc == 2:
mode = 'LA' mode = 'LA'
break break
elif cs == 18: # sYCC elif cs == 18: # sYCC
if nc == 3: if nc == 3:
mode = 'RGB' mode = 'RGB'
elif nc == 4: elif nc == 4:
@ -127,6 +129,7 @@ def _parse_jp2_header(fp):
return (size, mode) return (size, mode)
## ##
# Image plugin for JPEG2000 images. # Image plugin for JPEG2000 images.
@ -141,16 +144,16 @@ class Jpeg2KImageFile(ImageFile.ImageFile):
self.size, self.mode = _parse_codestream(self.fp) self.size, self.mode = _parse_codestream(self.fp)
else: else:
sig = sig + self.fp.read(8) sig = sig + self.fp.read(8)
if sig == b'\x00\x00\x00\x0cjP \x0d\x0a\x87\x0a': if sig == b'\x00\x00\x00\x0cjP \x0d\x0a\x87\x0a':
self.codec = "jp2" self.codec = "jp2"
self.size, self.mode = _parse_jp2_header(self.fp) self.size, self.mode = _parse_jp2_header(self.fp)
else: else:
raise SyntaxError('not a JPEG 2000 file') raise SyntaxError('not a JPEG 2000 file')
if self.size is None or self.mode is None: if self.size is None or self.mode is None:
raise SyntaxError('unable to determine size/mode') raise SyntaxError('unable to determine size/mode')
self.reduce = 0 self.reduce = 0
self.layers = 0 self.layers = 0
@ -177,13 +180,15 @@ class Jpeg2KImageFile(ImageFile.ImageFile):
t = self.tile[0] t = self.tile[0]
t3 = (t[3][0], self.reduce, self.layers, t[3][3]) t3 = (t[3][0], self.reduce, self.layers, t[3][3])
self.tile = [(t[0], (0, 0) + self.size, t[2], t3)] self.tile = [(t[0], (0, 0) + self.size, t[2], t3)]
ImageFile.ImageFile.load(self) ImageFile.ImageFile.load(self)
def _accept(prefix): def _accept(prefix):
return (prefix[:4] == b'\xff\x4f\xff\x51' return (prefix[:4] == b'\xff\x4f\xff\x51'
or prefix[:12] == b'\x00\x00\x00\x0cjP \x0d\x0a\x87\x0a') or prefix[:12] == b'\x00\x00\x00\x0cjP \x0d\x0a\x87\x0a')
# ------------------------------------------------------------ # ------------------------------------------------------------
# Save support # Save support
@ -214,7 +219,7 @@ def _save(im, fp, filename):
fd = fp.fileno() fd = fp.fileno()
except: except:
fd = -1 fd = -1
im.encoderconfig = ( im.encoderconfig = (
offset, offset,
tile_offset, tile_offset,
@ -228,10 +233,10 @@ def _save(im, fp, filename):
progression, progression,
cinema_mode, cinema_mode,
fd fd
) )
ImageFile._save(im, fp, [('jpeg2k', (0, 0)+im.size, 0, kind)]) ImageFile._save(im, fp, [('jpeg2k', (0, 0)+im.size, 0, kind)])
# ------------------------------------------------------------ # ------------------------------------------------------------
# Registry stuff # Registry stuff

View File

@ -7,7 +7,7 @@ This is an improved version of the OleFileIO module from [PIL](http://www.python
As far as I know, this module is now the most complete and robust Python implementation to read MS OLE2 files, portable on several operating systems. (please tell me if you know other similar Python modules) As far as I know, this module is now the most complete and robust Python implementation to read MS OLE2 files, portable on several operating systems. (please tell me if you know other similar Python modules)
OleFileIO_PL can be used as an independent module or with PIL. The goal is to have it integrated into [Pillow](http://python-imaging.github.io/), the friendly fork of PIL. OleFileIO_PL can be used as an independent module or with PIL. The goal is to have it integrated into [Pillow](http://python-pillow.github.io/), the friendly fork of PIL.
OleFileIO\_PL is mostly meant for developers. If you are looking for tools to analyze OLE files or to extract data, then please also check [python-oletools](http://www.decalage.info/python/oletools), which are built upon OleFileIO_PL. OleFileIO\_PL is mostly meant for developers. If you are looking for tools to analyze OLE files or to extract data, then please also check [python-oletools](http://www.decalage.info/python/oletools), which are built upon OleFileIO_PL.
@ -348,4 +348,4 @@ By obtaining, using, and/or copying this software and/or its associated document
Permission to use, copy, modify, and distribute this software and its associated documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appears in all copies, and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Secret Labs AB or the author not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. Permission to use, copy, modify, and distribute this software and its associated documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appears in all copies, and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Secret Labs AB or the author not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission.
SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

View File

@ -36,17 +36,23 @@
from __future__ import print_function from __future__ import print_function
from PIL import Image, ImageFile from PIL import Image, ImageFile
import os, struct, sys import os
import struct
import sys
def isInt(f): def isInt(f):
try: try:
i = int(f) i = int(f)
if f-i == 0: return 1 if f-i == 0:
else: return 0 return 1
else:
return 0
except: except:
return 0 return 0
iforms = [1,3,-11,-12,-21,-22] iforms = [1, 3, -11, -12, -21, -22]
# There is no magic number to identify Spider files, so just check a # There is no magic number to identify Spider files, so just check a
# series of header locations to see if they have reasonable values. # series of header locations to see if they have reasonable values.
@ -56,30 +62,32 @@ iforms = [1,3,-11,-12,-21,-22]
def isSpiderHeader(t): def isSpiderHeader(t):
h = (99,) + t # add 1 value so can use spider header index start=1 h = (99,) + t # add 1 value so can use spider header index start=1
# header values 1,2,5,12,13,22,23 should be integers # header values 1,2,5,12,13,22,23 should be integers
for i in [1,2,5,12,13,22,23]: for i in [1, 2, 5, 12, 13, 22, 23]:
if not isInt(h[i]): return 0 if not isInt(h[i]):
return 0
# check iform # check iform
iform = int(h[5]) iform = int(h[5])
if not iform in iforms: return 0 if iform not in iforms:
return 0
# check other header values # check other header values
labrec = int(h[13]) # no. records in file header labrec = int(h[13]) # no. records in file header
labbyt = int(h[22]) # total no. of bytes in header labbyt = int(h[22]) # total no. of bytes in header
lenbyt = int(h[23]) # record length in bytes lenbyt = int(h[23]) # record length in bytes
#print "labrec = %d, labbyt = %d, lenbyt = %d" % (labrec,labbyt,lenbyt) # print "labrec = %d, labbyt = %d, lenbyt = %d" % (labrec,labbyt,lenbyt)
if labbyt != (labrec * lenbyt): return 0 if labbyt != (labrec * lenbyt):
return 0
# looks like a valid header # looks like a valid header
return labbyt return labbyt
def isSpiderImage(filename): def isSpiderImage(filename):
fp = open(filename,'rb') fp = open(filename, 'rb')
f = fp.read(92) # read 23 * 4 bytes f = fp.read(92) # read 23 * 4 bytes
fp.close() fp.close()
bigendian = 1 t = struct.unpack('>23f', f) # try big-endian first
t = struct.unpack('>23f',f) # try big-endian first
hdrlen = isSpiderHeader(t) hdrlen = isSpiderHeader(t)
if hdrlen == 0: if hdrlen == 0:
bigendian = 0 t = struct.unpack('<23f', f) # little-endian
t = struct.unpack('<23f',f) # little-endian
hdrlen = isSpiderHeader(t) hdrlen = isSpiderHeader(t)
return hdrlen return hdrlen
@ -96,11 +104,11 @@ class SpiderImageFile(ImageFile.ImageFile):
try: try:
self.bigendian = 1 self.bigendian = 1
t = struct.unpack('>27f',f) # try big-endian first t = struct.unpack('>27f', f) # try big-endian first
hdrlen = isSpiderHeader(t) hdrlen = isSpiderHeader(t)
if hdrlen == 0: if hdrlen == 0:
self.bigendian = 0 self.bigendian = 0
t = struct.unpack('<27f',f) # little-endian t = struct.unpack('<27f', f) # little-endian
hdrlen = isSpiderHeader(t) hdrlen = isSpiderHeader(t)
if hdrlen == 0: if hdrlen == 0:
raise SyntaxError("not a valid Spider file") raise SyntaxError("not a valid Spider file")
@ -112,7 +120,7 @@ class SpiderImageFile(ImageFile.ImageFile):
if iform != 1: if iform != 1:
raise SyntaxError("not a Spider 2D image") raise SyntaxError("not a Spider 2D image")
self.size = int(h[12]), int(h[2]) # size in pixels (width, height) self.size = int(h[12]), int(h[2]) # size in pixels (width, height)
self.istack = int(h[24]) self.istack = int(h[24])
self.imgnumber = int(h[27]) self.imgnumber = int(h[27])
@ -141,9 +149,10 @@ class SpiderImageFile(ImageFile.ImageFile):
self.rawmode = "F;32F" self.rawmode = "F;32F"
self.mode = "F" self.mode = "F"
self.tile = [("raw", (0, 0) + self.size, offset, self.tile = [
(self.rawmode, 0, 1))] ("raw", (0, 0) + self.size, offset,
self.__fp = self.fp # FIXME: hack (self.rawmode, 0, 1))]
self.__fp = self.fp # FIXME: hack
# 1st image index is zero (although SPIDER imgnumber starts at 1) # 1st image index is zero (although SPIDER imgnumber starts at 1)
def tell(self): def tell(self):
@ -176,6 +185,7 @@ class SpiderImageFile(ImageFile.ImageFile):
from PIL import ImageTk from PIL import ImageTk
return ImageTk.PhotoImage(self.convert2byte(), palette=256) return ImageTk.PhotoImage(self.convert2byte(), palette=256)
# -------------------------------------------------------------------- # --------------------------------------------------------------------
# Image series # Image series
@ -200,17 +210,19 @@ def loadImageSeries(filelist=None):
imglist.append(im) imglist.append(im)
return imglist return imglist
# -------------------------------------------------------------------- # --------------------------------------------------------------------
# For saving images in Spider format # For saving images in Spider format
def makeSpiderHeader(im): def makeSpiderHeader(im):
nsam,nrow = im.size nsam, nrow = im.size
lenbyt = nsam * 4 # There are labrec records in the header lenbyt = nsam * 4 # There are labrec records in the header
labrec = 1024 / lenbyt labrec = 1024 / lenbyt
if 1024%lenbyt != 0: labrec += 1 if 1024 % lenbyt != 0:
labrec += 1
labbyt = labrec * lenbyt labbyt = labrec * lenbyt
hdr = [] hdr = []
nvalues = labbyt / 4 nvalues = int(labbyt / 4)
for i in range(nvalues): for i in range(nvalues):
hdr.append(0.0) hdr.append(0.0)
@ -218,13 +230,13 @@ def makeSpiderHeader(im):
return [] return []
# NB these are Fortran indices # NB these are Fortran indices
hdr[1] = 1.0 # nslice (=1 for an image) hdr[1] = 1.0 # nslice (=1 for an image)
hdr[2] = float(nrow) # number of rows per slice hdr[2] = float(nrow) # number of rows per slice
hdr[5] = 1.0 # iform for 2D image hdr[5] = 1.0 # iform for 2D image
hdr[12] = float(nsam) # number of pixels per line hdr[12] = float(nsam) # number of pixels per line
hdr[13] = float(labrec) # number of records in file header hdr[13] = float(labrec) # number of records in file header
hdr[22] = float(labbyt) # total number of bytes in header hdr[22] = float(labbyt) # total number of bytes in header
hdr[23] = float(lenbyt) # record length in bytes hdr[23] = float(lenbyt) # record length in bytes
# adjust for Fortran indexing # adjust for Fortran indexing
hdr = hdr[1:] hdr = hdr[1:]
@ -232,9 +244,10 @@ def makeSpiderHeader(im):
# pack binary data into a string # pack binary data into a string
hdrstr = [] hdrstr = []
for v in hdr: for v in hdr:
hdrstr.append(struct.pack('f',v)) hdrstr.append(struct.pack('f', v))
return hdrstr return hdrstr
def _save(im, fp, filename): def _save(im, fp, filename):
if im.mode[0] != "F": if im.mode[0] != "F":
im = im.convert('F') im = im.convert('F')
@ -250,11 +263,12 @@ def _save(im, fp, filename):
raise IOError("Unable to open %s for writing" % filename) raise IOError("Unable to open %s for writing" % filename)
fp.writelines(hdr) fp.writelines(hdr)
rawmode = "F;32NF" #32-bit native floating point rawmode = "F;32NF" # 32-bit native floating point
ImageFile._save(im, fp, [("raw", (0,0)+im.size, 0, (rawmode,0,1))]) ImageFile._save(im, fp, [("raw", (0, 0)+im.size, 0, (rawmode, 0, 1))])
fp.close() fp.close()
def _save_spider(im, fp, filename): def _save_spider(im, fp, filename):
# get the filename extension and register it with Image # get the filename extension and register it with Image
fn, ext = os.path.splitext(filename) fn, ext = os.path.splitext(filename)
@ -292,5 +306,7 @@ if __name__ == "__main__":
if outfile != "": if outfile != "":
# perform some image operation # perform some image operation
im = im.transpose(Image.FLIP_LEFT_RIGHT) im = im.transpose(Image.FLIP_LEFT_RIGHT)
print("saving a flipped version of %s as %s " % (os.path.basename(filename), outfile)) print(
"saving a flipped version of %s as %s " %
(os.path.basename(filename), outfile))
im.save(outfile, "SPIDER") im.save(outfile, "SPIDER")

View File

@ -54,7 +54,7 @@ import collections
import itertools import itertools
import os import os
# Set these to true to force use of libtiff for reading or writing. # Set these to true to force use of libtiff for reading or writing.
READ_LIBTIFF = False READ_LIBTIFF = False
WRITE_LIBTIFF= False WRITE_LIBTIFF= False
@ -238,7 +238,7 @@ class ImageFileDirectory(collections.MutableMapping):
Value: integer corresponding to the data type from Value: integer corresponding to the data type from
`TiffTags.TYPES` `TiffTags.TYPES`
'internal' 'internal'
* self.tags = {} Key: numerical tiff tag number * self.tags = {} Key: numerical tiff tag number
Value: Decoded data, Generally a tuple. Value: Decoded data, Generally a tuple.
* If set from __setval__ -- always a tuple * If set from __setval__ -- always a tuple
@ -489,10 +489,10 @@ class ImageFileDirectory(collections.MutableMapping):
if tag in self.tagtype: if tag in self.tagtype:
typ = self.tagtype[tag] typ = self.tagtype[tag]
if Image.DEBUG: if Image.DEBUG:
print ("Tag %s, Type: %s, Value: %s" % (tag, typ, value)) print ("Tag %s, Type: %s, Value: %s" % (tag, typ, value))
if typ == 1: if typ == 1:
# byte data # byte data
if isinstance(value, tuple): if isinstance(value, tuple):
@ -512,7 +512,7 @@ class ImageFileDirectory(collections.MutableMapping):
# and doesn't match the tiff spec: 8-bit byte that # and doesn't match the tiff spec: 8-bit byte that
# contains a 7-bit ASCII code; the last byte must be # contains a 7-bit ASCII code; the last byte must be
# NUL (binary zero). Also, I don't think this was well # NUL (binary zero). Also, I don't think this was well
# excersized before. # excersized before.
data = value = b"" + value.encode('ascii', 'replace') + b"\0" data = value = b"" + value.encode('ascii', 'replace') + b"\0"
else: else:
# integer data # integer data
@ -859,7 +859,7 @@ class TiffImageFile(ImageFile.ImageFile):
# libtiff handles the fillmode for us, so 1;IR should # libtiff handles the fillmode for us, so 1;IR should
# actually be 1;I. Including the R double reverses the # actually be 1;I. Including the R double reverses the
# bits, so stripes of the image are reversed. See # bits, so stripes of the image are reversed. See
# https://github.com/python-imaging/Pillow/issues/279 # https://github.com/python-pillow/Pillow/issues/279
if fillorder == 2: if fillorder == 2:
key = ( key = (
self.tag.prefix, photo, format, 1, self.tag.prefix, photo, format, 1,
@ -984,11 +984,11 @@ def _save(im, fp, filename):
compression = im.encoderinfo.get('compression',im.info.get('compression','raw')) compression = im.encoderinfo.get('compression',im.info.get('compression','raw'))
libtiff = WRITE_LIBTIFF or compression != 'raw' libtiff = WRITE_LIBTIFF or compression != 'raw'
# required for color libtiff images # required for color libtiff images
ifd[PLANAR_CONFIGURATION] = getattr(im, '_planar_configuration', 1) ifd[PLANAR_CONFIGURATION] = getattr(im, '_planar_configuration', 1)
# -- multi-page -- skip TIFF header on subsequent pages # -- multi-page -- skip TIFF header on subsequent pages
if not libtiff and fp.tell() == 0: if not libtiff and fp.tell() == 0:
# tiff header (write via IFD to get everything right) # tiff header (write via IFD to get everything right)
@ -1025,7 +1025,7 @@ def _save(im, fp, filename):
# which support profiles as TIFF) -- 2008-06-06 Florian Hoech # which support profiles as TIFF) -- 2008-06-06 Florian Hoech
if "icc_profile" in im.info: if "icc_profile" in im.info:
ifd[ICCPROFILE] = im.info["icc_profile"] ifd[ICCPROFILE] = im.info["icc_profile"]
if "description" in im.encoderinfo: if "description" in im.encoderinfo:
ifd[IMAGEDESCRIPTION] = im.encoderinfo["description"] ifd[IMAGEDESCRIPTION] = im.encoderinfo["description"]
if "resolution" in im.encoderinfo: if "resolution" in im.encoderinfo:
@ -1091,7 +1091,7 @@ def _save(im, fp, filename):
blocklist = [STRIPOFFSETS, STRIPBYTECOUNTS, ROWSPERSTRIP, ICCPROFILE] # ICC Profile crashes. blocklist = [STRIPOFFSETS, STRIPBYTECOUNTS, ROWSPERSTRIP, ICCPROFILE] # ICC Profile crashes.
atts={} atts={}
# bits per sample is a single short in the tiff directory, not a list. # bits per sample is a single short in the tiff directory, not a list.
atts[BITSPERSAMPLE] = bits[0] atts[BITSPERSAMPLE] = bits[0]
# Merge the ones that we have with (optional) more bits from # Merge the ones that we have with (optional) more bits from
# the original file, e.g x,y resolution so that we can # the original file, e.g x,y resolution so that we can

View File

@ -5,8 +5,8 @@ Pillow
Pillow is the "friendly" PIL fork by Alex Clark and Contributors. PIL is the Python Imaging Library by Fredrik Lundh and Contributors. Pillow is the "friendly" PIL fork by Alex Clark and Contributors. PIL is the Python Imaging Library by Fredrik Lundh and Contributors.
.. image:: https://travis-ci.org/python-imaging/Pillow.svg?branch=master .. image:: https://travis-ci.org/python-pillow/Pillow.svg?branch=master
:target: https://travis-ci.org/python-imaging/Pillow :target: https://travis-ci.org/python-pillow/Pillow
:alt: Travis CI build status :alt: Travis CI build status
.. image:: https://pypip.in/v/Pillow/badge.png .. image:: https://pypip.in/v/Pillow/badge.png
@ -17,7 +17,7 @@ Pillow is the "friendly" PIL fork by Alex Clark and Contributors. PIL is the Pyt
:target: https://pypi.python.org/pypi/Pillow/ :target: https://pypi.python.org/pypi/Pillow/
:alt: Number of PyPI downloads :alt: Number of PyPI downloads
.. image:: https://coveralls.io/repos/python-imaging/Pillow/badge.png?branch=master .. image:: https://coveralls.io/repos/python-pillow/Pillow/badge.png?branch=master
:target: https://coveralls.io/r/python-imaging/Pillow?branch=master :target: https://coveralls.io/r/python-pillow/Pillow?branch=master
The documentation is hosted at http://pillow.readthedocs.org/. It contains installation instructions, tutorials, reference, compatibility details, and more. The documentation is hosted at http://pillow.readthedocs.org/. It contains installation instructions, tutorials, reference, compatibility details, and more.

341
Tests/helper.py Normal file
View File

@ -0,0 +1,341 @@
"""
Helper functions.
"""
from __future__ import print_function
import sys
if sys.version_info[:2] <= (2, 6):
import unittest2 as unittest
else:
import unittest
def tearDownModule():
import glob
import os
import tempfile
temp_root = os.path.join(tempfile.gettempdir(), 'pillow-tests')
tempfiles = glob.glob(os.path.join(temp_root, "temp_*"))
if tempfiles:
print("===", "remaining temporary files")
for file in tempfiles:
print(file)
print("-"*68)
class PillowTestCase(unittest.TestCase):
currentResult = None # holds last result object passed to run method
_tempfiles = []
def run(self, result=None):
self.addCleanup(self.delete_tempfiles)
self.currentResult = result # remember result for use later
unittest.TestCase.run(self, result) # call superclass run method
def delete_tempfiles(self):
try:
ok = self.currentResult.wasSuccessful()
except AttributeError: # for nosetests
proxy = self.currentResult
ok = (len(proxy.errors) + len(proxy.failures) == 0)
if ok:
# only clean out tempfiles if test passed
import os
import os.path
import tempfile
for file in self._tempfiles:
try:
os.remove(file)
except OSError:
pass # report?
temp_root = os.path.join(tempfile.gettempdir(), 'pillow-tests')
try:
os.rmdir(temp_root)
except OSError:
pass
def assert_almost_equal(self, a, b, msg=None, eps=1e-6):
self.assertLess(
abs(a-b), eps,
msg or "got %r, expected %r" % (a, b))
def assert_deep_equal(self, a, b, msg=None):
try:
self.assertEqual(
len(a), len(b),
msg or "got length %s, expected %s" % (len(a), len(b)))
self.assertTrue(
all([x == y for x, y in zip(a, b)]),
msg or "got %s, expected %s" % (a, b))
except:
self.assertEqual(a, b, msg)
def assert_image(self, im, mode, size, msg=None):
if mode is not None:
self.assertEqual(
im.mode, mode,
msg or "got mode %r, expected %r" % (im.mode, mode))
if size is not None:
self.assertEqual(
im.size, size,
msg or "got size %r, expected %r" % (im.size, size))
def assert_image_equal(self, a, b, msg=None):
self.assertEqual(
a.mode, b.mode,
msg or "got mode %r, expected %r" % (a.mode, b.mode))
self.assertEqual(
a.size, b.size,
msg or "got size %r, expected %r" % (a.size, b.size))
self.assertEqual(
a.tobytes(), b.tobytes(),
msg or "got different content")
def assert_image_similar(self, a, b, epsilon, msg=None):
epsilon = float(epsilon)
self.assertEqual(
a.mode, b.mode,
msg or "got mode %r, expected %r" % (a.mode, b.mode))
self.assertEqual(
a.size, b.size,
msg or "got size %r, expected %r" % (a.size, b.size))
diff = 0
try:
ord(b'0')
for abyte, bbyte in zip(a.tobytes(), b.tobytes()):
diff += abs(ord(abyte)-ord(bbyte))
except:
for abyte, bbyte in zip(a.tobytes(), b.tobytes()):
diff += abs(abyte-bbyte)
ave_diff = float(diff)/(a.size[0]*a.size[1])
self.assertGreaterEqual(
epsilon, ave_diff,
msg or "average pixel value difference %.4f > epsilon %.4f" % (
ave_diff, epsilon))
def assert_warning(self, warn_class, func):
import warnings
result = None
with warnings.catch_warnings(record=True) as w:
# Cause all warnings to always be triggered.
warnings.simplefilter("always")
# Hopefully trigger a warning.
result = func()
# Verify some things.
self.assertGreaterEqual(len(w), 1)
found = False
for v in w:
if issubclass(v.category, warn_class):
found = True
break
self.assertTrue(found)
return result
def tempfile(self, template, *extra):
import os
import os.path
import sys
import tempfile
files = []
root = os.path.join(tempfile.gettempdir(), 'pillow-tests')
try:
os.mkdir(root)
except OSError:
pass
for temp in (template,) + extra:
assert temp[:5] in ("temp.", "temp_")
name = os.path.basename(sys.argv[0])
name = temp[:4] + os.path.splitext(name)[0][4:]
name = name + "_%d" % len(self._tempfiles) + temp[4:]
name = os.path.join(root, name)
files.append(name)
self._tempfiles.extend(files)
return files[0]
# # require that deprecation warnings are triggered
# import warnings
# warnings.simplefilter('default')
# # temporarily turn off resource warnings that warn about unclosed
# # files in the test scripts.
# try:
# warnings.filterwarnings("ignore", category=ResourceWarning)
# except NameError:
# # we expect a NameError on py2.x, since it doesn't have ResourceWarnings.
# pass
import sys
py3 = (sys.version_info >= (3, 0))
# # some test helpers
#
# _target = None
# _tempfiles = []
# _logfile = None
#
#
# def success():
# import sys
# success.count += 1
# if _logfile:
# print(sys.argv[0], success.count, failure.count, file=_logfile)
# return True
#
#
# def failure(msg=None, frame=None):
# import sys
# import linecache
# failure.count += 1
# if _target:
# if frame is None:
# frame = sys._getframe()
# while frame.f_globals.get("__name__") != _target.__name__:
# frame = frame.f_back
# location = (frame.f_code.co_filename, frame.f_lineno)
# prefix = "%s:%d: " % location
# line = linecache.getline(*location)
# print(prefix + line.strip() + " failed:")
# if msg:
# print("- " + msg)
# if _logfile:
# print(sys.argv[0], success.count, failure.count, file=_logfile)
# return False
#
# success.count = failure.count = 0
#
# helpers
def fromstring(data):
from io import BytesIO
from PIL import Image
return Image.open(BytesIO(data))
def tostring(im, format, **options):
from io import BytesIO
out = BytesIO()
im.save(out, format, **options)
return out.getvalue()
def lena(mode="RGB", cache={}):
from PIL import Image
im = None
# im = cache.get(mode)
if im is None:
if mode == "RGB":
im = Image.open("Images/lena.ppm")
elif mode == "F":
im = lena("L").convert(mode)
elif mode[:4] == "I;16":
im = lena("I").convert(mode)
else:
im = lena("RGB").convert(mode)
# cache[mode] = im
return im
# def assert_image_completely_equal(a, b, msg=None):
# if a != b:
# failure(msg or "images different")
# else:
# success()
#
#
# # test runner
#
# def run():
# global _target, _tests, run
# import sys
# import traceback
# _target = sys.modules["__main__"]
# run = None # no need to run twice
# tests = []
# for name, value in list(vars(_target).items()):
# if name[:5] == "test_" and type(value) is type(success):
# tests.append((value.__code__.co_firstlineno, name, value))
# tests.sort() # sort by line
# for lineno, name, func in tests:
# try:
# _tests = []
# func()
# for func, args in _tests:
# func(*args)
# except:
# t, v, tb = sys.exc_info()
# tb = tb.tb_next
# if tb:
# failure(frame=tb.tb_frame)
# traceback.print_exception(t, v, tb)
# else:
# print("%s:%d: cannot call test function: %s" % (
# sys.argv[0], lineno, v))
# failure.count += 1
#
#
# def yield_test(function, *args):
# # collect delayed/generated tests
# _tests.append((function, args))
#
#
# def skip(msg=None):
# import os
# print("skip")
# os._exit(0) # don't run exit handlers
#
#
# def ignore(pattern):
# """Tells the driver to ignore messages matching the pattern, for the
# duration of the current test."""
# print('ignore: %s' % pattern)
#
#
# def _setup():
# global _logfile
#
# import sys
# if "--coverage" in sys.argv:
# # Temporary: ignore PendingDeprecationWarning from Coverage (Py3.4)
# with warnings.catch_warnings():
# warnings.simplefilter("ignore")
# import coverage
# cov = coverage.coverage(auto_data=True, include="PIL/*")
# cov.start()
#
# def report():
# if run:
# run()
# if success.count and not failure.count:
# print("ok")
# # only clean out tempfiles if test passed
# import os
# import os.path
# import tempfile
# for file in _tempfiles:
# try:
# os.remove(file)
# except OSError:
# pass # report?
# temp_root = os.path.join(tempfile.gettempdir(), 'pillow-tests')
# try:
# os.rmdir(temp_root)
# except OSError:
# pass
#
# import atexit
# atexit.register(report)
#
# if "--log" in sys.argv:
# _logfile = open("test.log", "a")
#
#
# _setup()

Binary file not shown.

After

Width:  |  Height:  |  Size: 284 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 286 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 405 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 292 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 228 B

BIN
Tests/images/lena.spider Normal file

Binary file not shown.

View File

@ -1,24 +1,32 @@
from __future__ import print_function from helper import unittest, PillowTestCase, tearDownModule
from tester import *
import PIL import PIL
import PIL.Image import PIL.Image
# Make sure we have the binary extension
im = PIL.Image.core.new("L", (100, 100))
assert PIL.Image.VERSION[:3] == '1.1' class TestSanity(PillowTestCase):
# Create an image and do stuff with it. def test_sanity(self):
im = PIL.Image.new("1", (100, 100))
assert (im.mode, im.size) == ('1', (100, 100))
assert len(im.tobytes()) == 1300
# Create images in all remaining major modes. # Make sure we have the binary extension
im = PIL.Image.new("L", (100, 100)) im = PIL.Image.core.new("L", (100, 100))
im = PIL.Image.new("P", (100, 100))
im = PIL.Image.new("RGB", (100, 100))
im = PIL.Image.new("I", (100, 100))
im = PIL.Image.new("F", (100, 100))
print("ok") self.assertEqual(PIL.Image.VERSION[:3], '1.1')
# Create an image and do stuff with it.
im = PIL.Image.new("1", (100, 100))
self.assertEqual((im.mode, im.size), ('1', (100, 100)))
self.assertEqual(len(im.tobytes()), 1300)
# Create images in all remaining major modes.
im = PIL.Image.new("L", (100, 100))
im = PIL.Image.new("P", (100, 100))
im = PIL.Image.new("RGB", (100, 100))
im = PIL.Image.new("I", (100, 100))
im = PIL.Image.new("F", (100, 100))
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,23 +0,0 @@
import PIL
import PIL.Image
import glob, os
for file in glob.glob("../pil-archive/*"):
f, e = os.path.splitext(file)
if e in [".txt", ".ttf", ".otf", ".zip"]:
continue
try:
im = PIL.Image.open(file)
im.load()
except IOError as v:
print("-", "failed to open", file, "-", v)
else:
print("+", file, im.mode, im.size, im.format)
if e == ".exif":
try:
info = im._getexif()
except KeyError as v:
print("-", "failed to get exif info from", file, "-", v)
print("ok")

View File

@ -1,4 +1,4 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule
from PIL import Image from PIL import Image
import os import os
@ -6,81 +6,89 @@ import os
base = os.path.join('Tests', 'images', 'bmp') base = os.path.join('Tests', 'images', 'bmp')
def get_files(d, ext='.bmp'): class TestBmpReference(PillowTestCase):
return [os.path.join(base,d,f) for f
in os.listdir(os.path.join(base, d)) if ext in f]
def test_bad(): def get_files(self, d, ext='.bmp'):
""" These shouldn't crash/dos, but they shouldn't return anything either """ return [os.path.join(base, d, f) for f
for f in get_files('b'): in os.listdir(os.path.join(base, d)) if ext in f]
try:
im = Image.open(f)
im.load()
except Exception as msg:
pass
# print ("Bad Image %s: %s" %(f,msg))
def test_questionable(): def test_bad(self):
""" These shouldn't crash/dos, but its not well defined that these are in spec """ """ These shouldn't crash/dos, but they shouldn't return anything
for f in get_files('q'): either """
try: for f in self.get_files('b'):
im = Image.open(f) try:
im.load() im = Image.open(f)
except Exception as msg: im.load()
pass except Exception: # as msg:
# print ("Bad Image %s: %s" %(f,msg)) pass
# print ("Bad Image %s: %s" %(f,msg))
def test_questionable(self):
""" These shouldn't crash/dos, but its not well defined that these
are in spec """
for f in self.get_files('q'):
try:
im = Image.open(f)
im.load()
except Exception: # as msg:
pass
# print ("Bad Image %s: %s" %(f,msg))
def test_good(self):
""" These should all work. There's a set of target files in the
html directory that we can compare against. """
# Target files, if they're not just replacing the extension
file_map = {'pal1wb.bmp': 'pal1.png',
'pal4rle.bmp': 'pal4.png',
'pal8-0.bmp': 'pal8.png',
'pal8rle.bmp': 'pal8.png',
'pal8topdown.bmp': 'pal8.png',
'pal8nonsquare.bmp': 'pal8nonsquare-v.png',
'pal8os2.bmp': 'pal8.png',
'pal8os2sp.bmp': 'pal8.png',
'pal8os2v2.bmp': 'pal8.png',
'pal8os2v2-16.bmp': 'pal8.png',
'pal8v4.bmp': 'pal8.png',
'pal8v5.bmp': 'pal8.png',
'rgb16-565pal.bmp': 'rgb16-565.png',
'rgb24pal.bmp': 'rgb24.png',
'rgb32.bmp': 'rgb24.png',
'rgb32bf.bmp': 'rgb24.png'
}
def get_compare(f):
(head, name) = os.path.split(f)
if name in file_map:
return os.path.join(base, 'html', file_map[name])
(name, ext) = os.path.splitext(name)
return os.path.join(base, 'html', "%s.png" % name)
for f in self.get_files('g'):
try:
im = Image.open(f)
im.load()
compare = Image.open(get_compare(f))
compare.load()
if im.mode == 'P':
# assert image similar doesn't really work
# with paletized image, since the palette might
# be differently ordered for an equivalent image.
im = im.convert('RGBA')
compare = im.convert('RGBA')
self.assert_image_similar(im, compare, 5)
except Exception as msg:
# there are three here that are unsupported:
unsupported = (os.path.join(base, 'g', 'rgb32bf.bmp'),
os.path.join(base, 'g', 'pal8rle.bmp'),
os.path.join(base, 'g', 'pal4rle.bmp'))
if f not in unsupported:
self.assertTrue(
False, "Unsupported Image %s: %s" % (f, msg))
def test_good(): if __name__ == '__main__':
""" These should all work. There's a set of target files in the unittest.main()
html directory that we can compare against. """
# Target files, if they're not just replacing the extension
file_map = { 'pal1wb.bmp': 'pal1.png',
'pal4rle.bmp': 'pal4.png',
'pal8-0.bmp': 'pal8.png',
'pal8rle.bmp': 'pal8.png',
'pal8topdown.bmp': 'pal8.png',
'pal8nonsquare.bmp': 'pal8nonsquare-v.png',
'pal8os2.bmp': 'pal8.png',
'pal8os2sp.bmp': 'pal8.png',
'pal8os2v2.bmp': 'pal8.png',
'pal8os2v2-16.bmp': 'pal8.png',
'pal8v4.bmp': 'pal8.png',
'pal8v5.bmp': 'pal8.png',
'rgb16-565pal.bmp': 'rgb16-565.png',
'rgb24pal.bmp': 'rgb24.png',
'rgb32.bmp': 'rgb24.png',
'rgb32bf.bmp': 'rgb24.png'
}
def get_compare(f):
(head, name) = os.path.split(f)
if name in file_map:
return os.path.join(base, 'html', file_map[name])
(name,ext) = os.path.splitext(name)
return os.path.join(base, 'html', "%s.png"%name)
for f in get_files('g'):
try:
im = Image.open(f)
im.load()
compare = Image.open(get_compare(f))
compare.load()
if im.mode == 'P':
# assert image similar doesn't really work
# with paletized image, since the palette might
# be differently ordered for an equivalent image.
im = im.convert('RGBA')
compare = im.convert('RGBA')
assert_image_similar(im, compare,5)
except Exception as msg:
# there are three here that are unsupported:
unsupported = (os.path.join(base, 'g', 'rgb32bf.bmp'),
os.path.join(base, 'g', 'pal8rle.bmp'),
os.path.join(base, 'g', 'pal4rle.bmp'))
if f not in unsupported:
assert_true(False, "Unsupported Image %s: %s" %(f,msg))
# End of file

View File

@ -1,99 +1,136 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
try: try:
import cffi import cffi
from PIL import PyAccess
except: except:
skip() # Skip in setUp()
pass
from PIL import Image, PyAccess
import test_image_putpixel as put from PIL import Image
import test_image_getpixel as get
from test_image_putpixel import TestImagePutPixel
from test_image_getpixel import TestImageGetPixel
Image.USE_CFFI_ACCESS = True Image.USE_CFFI_ACCESS = True
def test_put():
put.test_sanity()
def test_get(): class TestCffiPutPixel(TestImagePutPixel):
get.test_basic()
get.test_signedness()
def _test_get_access(im): def setUp(self):
""" Do we get the same thing as the old pixel access """ try:
import cffi
except:
self.skipTest("No cffi")
""" Using private interfaces, forcing a capi access and a pyaccess for the same image """ def test_put(self):
caccess = im.im.pixel_access(False) self.test_sanity()
access = PyAccess.new(im, False)
w,h = im.size
for x in range(0,w,10):
for y in range(0,h,10):
assert_equal(access[(x,y)], caccess[(x,y)])
def test_get_vs_c():
_test_get_access(lena('RGB'))
_test_get_access(lena('RGBA'))
_test_get_access(lena('L'))
_test_get_access(lena('LA'))
_test_get_access(lena('1'))
_test_get_access(lena('P'))
#_test_get_access(lena('PA')) # PA -- how do I make a PA image???
_test_get_access(lena('F'))
im = Image.new('I;16', (10,10), 40000)
_test_get_access(im)
im = Image.new('I;16L', (10,10), 40000)
_test_get_access(im)
im = Image.new('I;16B', (10,10), 40000)
_test_get_access(im)
im = Image.new('I', (10,10), 40000)
_test_get_access(im)
# These don't actually appear to be modes that I can actually make,
# as unpack sets them directly into the I mode.
#im = Image.new('I;32L', (10,10), -2**10)
#_test_get_access(im)
#im = Image.new('I;32B', (10,10), 2**10)
#_test_get_access(im)
class TestCffiGetPixel(TestImageGetPixel):
def _test_set_access(im, color): def setUp(self):
""" Are we writing the correct bits into the image? """ try:
import cffi
except:
self.skipTest("No cffi")
""" Using private interfaces, forcing a capi access and a pyaccess for the same image """ def test_get(self):
caccess = im.im.pixel_access(False) self.test_basic()
access = PyAccess.new(im, False) self.test_signedness()
w,h = im.size
for x in range(0,w,10):
for y in range(0,h,10):
access[(x,y)] = color
assert_equal(color, caccess[(x,y)])
def test_set_vs_c(): class TestCffi(PillowTestCase):
_test_set_access(lena('RGB'), (255, 128,0) )
_test_set_access(lena('RGBA'), (255, 192, 128, 0))
_test_set_access(lena('L'), 128)
_test_set_access(lena('LA'), (128,128))
_test_set_access(lena('1'), 255)
_test_set_access(lena('P') , 128)
##_test_set_access(i, (128,128)) #PA -- undone how to make
_test_set_access(lena('F'), 1024.0)
im = Image.new('I;16', (10,10), 40000)
_test_set_access(im, 45000)
im = Image.new('I;16L', (10,10), 40000)
_test_set_access(im, 45000)
im = Image.new('I;16B', (10,10), 40000)
_test_set_access(im, 45000)
im = Image.new('I', (10,10), 40000) def setUp(self):
_test_set_access(im, 45000) try:
# im = Image.new('I;32L', (10,10), -(2**10)) import cffi
# _test_set_access(im, -(2**13)+1) except:
#im = Image.new('I;32B', (10,10), 2**10) self.skipTest("No cffi")
#_test_set_access(im, 2**13-1)
def _test_get_access(self, im):
""" Do we get the same thing as the old pixel access """
""" Using private interfaces, forcing a capi access and
a pyaccess for the same image """
caccess = im.im.pixel_access(False)
access = PyAccess.new(im, False)
w, h = im.size
for x in range(0, w, 10):
for y in range(0, h, 10):
self.assertEqual(access[(x, y)], caccess[(x, y)])
def test_get_vs_c(self):
rgb = lena('RGB')
rgb.load()
self._test_get_access(rgb)
self._test_get_access(lena('RGBA'))
self._test_get_access(lena('L'))
self._test_get_access(lena('LA'))
self._test_get_access(lena('1'))
self._test_get_access(lena('P'))
# self._test_get_access(lena('PA')) # PA -- how do I make a PA image?
self._test_get_access(lena('F'))
im = Image.new('I;16', (10, 10), 40000)
self._test_get_access(im)
im = Image.new('I;16L', (10, 10), 40000)
self._test_get_access(im)
im = Image.new('I;16B', (10, 10), 40000)
self._test_get_access(im)
im = Image.new('I', (10, 10), 40000)
self._test_get_access(im)
# These don't actually appear to be modes that I can actually make,
# as unpack sets them directly into the I mode.
# im = Image.new('I;32L', (10, 10), -2**10)
# self._test_get_access(im)
# im = Image.new('I;32B', (10, 10), 2**10)
# self._test_get_access(im)
def _test_set_access(self, im, color):
""" Are we writing the correct bits into the image? """
""" Using private interfaces, forcing a capi access and
a pyaccess for the same image """
caccess = im.im.pixel_access(False)
access = PyAccess.new(im, False)
w, h = im.size
for x in range(0, w, 10):
for y in range(0, h, 10):
access[(x, y)] = color
self.assertEqual(color, caccess[(x, y)])
def test_set_vs_c(self):
rgb = lena('RGB')
rgb.load()
self._test_set_access(rgb, (255, 128, 0))
self._test_set_access(lena('RGBA'), (255, 192, 128, 0))
self._test_set_access(lena('L'), 128)
self._test_set_access(lena('LA'), (128, 128))
self._test_set_access(lena('1'), 255)
self._test_set_access(lena('P'), 128)
# self._test_set_access(i, (128, 128)) #PA -- undone how to make
self._test_set_access(lena('F'), 1024.0)
im = Image.new('I;16', (10, 10), 40000)
self._test_set_access(im, 45000)
im = Image.new('I;16L', (10, 10), 40000)
self._test_set_access(im, 45000)
im = Image.new('I;16B', (10, 10), 40000)
self._test_set_access(im, 45000)
im = Image.new('I', (10, 10), 40000)
self._test_set_access(im, 45000)
# im = Image.new('I;32L', (10, 10), -(2**10))
# self._test_set_access(im, -(2**13)+1)
# im = Image.new('I;32B', (10, 10), 2**10)
# self._test_set_access(im, 2**13-1)
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,38 +1,44 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image from PIL import Image
import io import io
def roundtrip(im):
outfile = tempfile("temp.bmp")
im.save(outfile, 'BMP') class TestFileBmp(PillowTestCase):
reloaded = Image.open(outfile) def roundtrip(self, im):
reloaded.load() outfile = self.tempfile("temp.bmp")
assert_equal(im.mode, reloaded.mode)
assert_equal(im.size, reloaded.size) im.save(outfile, 'BMP')
assert_equal(reloaded.format, "BMP")
reloaded = Image.open(outfile)
reloaded.load()
self.assertEqual(im.mode, reloaded.mode)
self.assertEqual(im.size, reloaded.size)
self.assertEqual(reloaded.format, "BMP")
def test_sanity(self):
self.roundtrip(lena())
self.roundtrip(lena("1"))
self.roundtrip(lena("L"))
self.roundtrip(lena("P"))
self.roundtrip(lena("RGB"))
def test_save_to_bytes(self):
output = io.BytesIO()
im = lena()
im.save(output, "BMP")
output.seek(0)
reloaded = Image.open(output)
self.assertEqual(im.mode, reloaded.mode)
self.assertEqual(im.size, reloaded.size)
self.assertEqual(reloaded.format, "BMP")
def test_sanity(): if __name__ == '__main__':
roundtrip(lena()) unittest.main()
roundtrip(lena("1"))
roundtrip(lena("L"))
roundtrip(lena("P"))
roundtrip(lena("RGB"))
# End of file
def test_save_to_bytes():
output = io.BytesIO()
im = lena()
im.save(output, "BMP")
output.seek(0)
reloaded = Image.open(output)
assert_equal(im.mode, reloaded.mode)
assert_equal(im.size, reloaded.size)
assert_equal(reloaded.format, "BMP")

View File

@ -1,11 +1,8 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule
from PIL import Image, EpsImagePlugin from PIL import Image, EpsImagePlugin
import io import io
if not EpsImagePlugin.has_ghostscript():
skip()
# Our two EPS test files (they are identical except for their bounding boxes) # Our two EPS test files (they are identical except for their bounding boxes)
file1 = "Tests/images/zero_bb.eps" file1 = "Tests/images/zero_bb.eps"
file2 = "Tests/images/non_zero_bb.eps" file2 = "Tests/images/non_zero_bb.eps"
@ -20,123 +17,127 @@ file2_compare_scale2 = "Tests/images/non_zero_bb_scale2.png"
# EPS test files with binary preview # EPS test files with binary preview
file3 = "Tests/images/binary_preview_map.eps" file3 = "Tests/images/binary_preview_map.eps"
def test_sanity():
# Regular scale
image1 = Image.open(file1)
image1.load()
assert_equal(image1.mode, "RGB")
assert_equal(image1.size, (460, 352))
assert_equal(image1.format, "EPS")
image2 = Image.open(file2) class TestFileEps(PillowTestCase):
image2.load()
assert_equal(image2.mode, "RGB")
assert_equal(image2.size, (360, 252))
assert_equal(image2.format, "EPS")
# Double scale def setUp(self):
image1_scale2 = Image.open(file1) if not EpsImagePlugin.has_ghostscript():
image1_scale2.load(scale=2) self.skipTest("Ghostscript not available")
assert_equal(image1_scale2.mode, "RGB")
assert_equal(image1_scale2.size, (920, 704))
assert_equal(image1_scale2.format, "EPS")
image2_scale2 = Image.open(file2) def test_sanity(self):
image2_scale2.load(scale=2) # Regular scale
assert_equal(image2_scale2.mode, "RGB") image1 = Image.open(file1)
assert_equal(image2_scale2.size, (720, 504)) image1.load()
assert_equal(image2_scale2.format, "EPS") self.assertEqual(image1.mode, "RGB")
self.assertEqual(image1.size, (460, 352))
self.assertEqual(image1.format, "EPS")
image2 = Image.open(file2)
image2.load()
self.assertEqual(image2.mode, "RGB")
self.assertEqual(image2.size, (360, 252))
self.assertEqual(image2.format, "EPS")
def test_file_object(): # Double scale
# issue 479 image1_scale2 = Image.open(file1)
image1 = Image.open(file1) image1_scale2.load(scale=2)
with open(tempfile('temp_file.eps'), 'wb') as fh: self.assertEqual(image1_scale2.mode, "RGB")
image1.save(fh, 'EPS') self.assertEqual(image1_scale2.size, (920, 704))
self.assertEqual(image1_scale2.format, "EPS")
image2_scale2 = Image.open(file2)
image2_scale2.load(scale=2)
self.assertEqual(image2_scale2.mode, "RGB")
self.assertEqual(image2_scale2.size, (720, 504))
self.assertEqual(image2_scale2.format, "EPS")
def test_iobase_object(): def test_file_object(self):
# issue 479 # issue 479
image1 = Image.open(file1) image1 = Image.open(file1)
with io.open(tempfile('temp_iobase.eps'), 'wb') as fh: with open(self.tempfile('temp_file.eps'), 'wb') as fh:
image1.save(fh, 'EPS') image1.save(fh, 'EPS')
def test_iobase_object(self):
# issue 479
image1 = Image.open(file1)
with io.open(self.tempfile('temp_iobase.eps'), 'wb') as fh:
image1.save(fh, 'EPS')
def test_render_scale1(): def test_render_scale1(self):
# We need png support for these render test # We need png support for these render test
codecs = dir(Image.core) codecs = dir(Image.core)
if "zip_encoder" not in codecs or "zip_decoder" not in codecs: if "zip_encoder" not in codecs or "zip_decoder" not in codecs:
skip("zip/deflate support not available") self.skipTest("zip/deflate support not available")
# Zero bounding box # Zero bounding box
image1_scale1 = Image.open(file1) image1_scale1 = Image.open(file1)
image1_scale1.load() image1_scale1.load()
image1_scale1_compare = Image.open(file1_compare).convert("RGB") image1_scale1_compare = Image.open(file1_compare).convert("RGB")
image1_scale1_compare.load() image1_scale1_compare.load()
assert_image_similar(image1_scale1, image1_scale1_compare, 5) self.assert_image_similar(image1_scale1, image1_scale1_compare, 5)
# Non-Zero bounding box # Non-Zero bounding box
image2_scale1 = Image.open(file2) image2_scale1 = Image.open(file2)
image2_scale1.load() image2_scale1.load()
image2_scale1_compare = Image.open(file2_compare).convert("RGB") image2_scale1_compare = Image.open(file2_compare).convert("RGB")
image2_scale1_compare.load() image2_scale1_compare.load()
assert_image_similar(image2_scale1, image2_scale1_compare, 10) self.assert_image_similar(image2_scale1, image2_scale1_compare, 10)
def test_render_scale2(self):
# We need png support for these render test
codecs = dir(Image.core)
if "zip_encoder" not in codecs or "zip_decoder" not in codecs:
self.skipTest("zip/deflate support not available")
def test_render_scale2(): # Zero bounding box
# We need png support for these render test image1_scale2 = Image.open(file1)
codecs = dir(Image.core) image1_scale2.load(scale=2)
if "zip_encoder" not in codecs or "zip_decoder" not in codecs: image1_scale2_compare = Image.open(file1_compare_scale2).convert("RGB")
skip("zip/deflate support not available") image1_scale2_compare.load()
self.assert_image_similar(image1_scale2, image1_scale2_compare, 5)
# Zero bounding box # Non-Zero bounding box
image1_scale2 = Image.open(file1) image2_scale2 = Image.open(file2)
image1_scale2.load(scale=2) image2_scale2.load(scale=2)
image1_scale2_compare = Image.open(file1_compare_scale2).convert("RGB") image2_scale2_compare = Image.open(file2_compare_scale2).convert("RGB")
image1_scale2_compare.load() image2_scale2_compare.load()
assert_image_similar(image1_scale2, image1_scale2_compare, 5) self.assert_image_similar(image2_scale2, image2_scale2_compare, 10)
# Non-Zero bounding box def test_resize(self):
image2_scale2 = Image.open(file2) # Arrange
image2_scale2.load(scale=2) image1 = Image.open(file1)
image2_scale2_compare = Image.open(file2_compare_scale2).convert("RGB") image2 = Image.open(file2)
image2_scale2_compare.load() new_size = (100, 100)
assert_image_similar(image2_scale2, image2_scale2_compare, 10)
# Act
image1 = image1.resize(new_size)
image2 = image2.resize(new_size)
def test_resize(): # Assert
# Arrange self.assertEqual(image1.size, new_size)
image1 = Image.open(file1) self.assertEqual(image2.size, new_size)
image2 = Image.open(file2)
new_size = (100, 100)
# Act def test_thumbnail(self):
image1 = image1.resize(new_size) # Issue #619
image2 = image2.resize(new_size) # Arrange
image1 = Image.open(file1)
image2 = Image.open(file2)
new_size = (100, 100)
# Assert # Act
assert_equal(image1.size, new_size) image1.thumbnail(new_size)
assert_equal(image2.size, new_size) image2.thumbnail(new_size)
# Assert
self.assertEqual(max(image1.size), max(new_size))
self.assertEqual(max(image2.size), max(new_size))
def test_thumbnail(): def test_read_binary_preview(self):
# Issue #619 # Issue 302
# Arrange # open image with binary preview
image1 = Image.open(file1) Image.open(file3)
image2 = Image.open(file2)
new_size = (100, 100)
# Act if __name__ == '__main__':
image1.thumbnail(new_size) unittest.main()
image2.thumbnail(new_size)
# Assert
assert_equal(max(image1.size), max(new_size))
assert_equal(max(image2.size), max(new_size))
def test_read_binary_preview():
# Issue 302
# open image with binary preview
image1 = Image.open(file3)
# End of file # End of file

View File

@ -1,4 +1,4 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule
from PIL import Image from PIL import Image
@ -6,9 +6,18 @@ from PIL import Image
file = "Images/lena.fli" file = "Images/lena.fli"
data = open(file, "rb").read() data = open(file, "rb").read()
def test_sanity():
im = Image.open(file) class TestFileFli(PillowTestCase):
im.load()
assert_equal(im.mode, "P") def test_sanity(self):
assert_equal(im.size, (128, 128)) im = Image.open(file)
assert_equal(im.format, "FLI") im.load()
self.assertEqual(im.mode, "P")
self.assertEqual(im.size, (128, 128))
self.assertEqual(im.format, "FLI")
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,87 +1,96 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image from PIL import Image
codecs = dir(Image.core) codecs = dir(Image.core)
if "gif_encoder" not in codecs or "gif_decoder" not in codecs:
skip("gif support not available") # can this happen?
# sample gif stream # sample gif stream
file = "Images/lena.gif" file = "Images/lena.gif"
with open(file, "rb") as f: with open(file, "rb") as f:
data = f.read() data = f.read()
def test_sanity():
im = Image.open(file)
im.load()
assert_equal(im.mode, "P")
assert_equal(im.size, (128, 128))
assert_equal(im.format, "GIF")
def test_optimize(): class TestFileGif(PillowTestCase):
def test(optimize):
im = Image.new("L", (1, 1), 0)
file = BytesIO()
im.save(file, "GIF", optimize=optimize)
return len(file.getvalue())
assert_equal(test(0), 800)
assert_equal(test(1), 38)
def test_roundtrip(): def setUp(self):
out = tempfile('temp.gif') if "gif_encoder" not in codecs or "gif_decoder" not in codecs:
im = lena() self.skipTest("gif support not available") # can this happen?
im.save(out)
reread = Image.open(out)
assert_image_similar(reread.convert('RGB'), im, 50) def test_sanity(self):
im = Image.open(file)
im.load()
self.assertEqual(im.mode, "P")
self.assertEqual(im.size, (128, 128))
self.assertEqual(im.format, "GIF")
def test_roundtrip2(): def test_optimize(self):
#see https://github.com/python-imaging/Pillow/issues/403 from io import BytesIO
out = tempfile('temp.gif')
im = Image.open('Images/lena.gif')
im2 = im.copy()
im2.save(out)
reread = Image.open(out)
assert_image_similar(reread.convert('RGB'), lena(), 50) def test(optimize):
im = Image.new("L", (1, 1), 0)
file = BytesIO()
im.save(file, "GIF", optimize=optimize)
return len(file.getvalue())
self.assertEqual(test(0), 800)
self.assertEqual(test(1), 38)
def test_roundtrip(self):
out = self.tempfile('temp.gif')
im = lena()
im.save(out)
reread = Image.open(out)
self.assert_image_similar(reread.convert('RGB'), im, 50)
def test_roundtrip2(self):
# see https://github.com/python-pillow/Pillow/issues/403
out = self.tempfile('temp.gif')
im = Image.open('Images/lena.gif')
im2 = im.copy()
im2.save(out)
reread = Image.open(out)
self.assert_image_similar(reread.convert('RGB'), lena(), 50)
def test_palette_handling(self):
# see https://github.com/python-pillow/Pillow/issues/513
im = Image.open('Images/lena.gif')
im = im.convert('RGB')
im = im.resize((100, 100), Image.ANTIALIAS)
im2 = im.convert('P', palette=Image.ADAPTIVE, colors=256)
f = self.tempfile('temp.gif')
im2.save(f, optimize=True)
reloaded = Image.open(f)
self.assert_image_similar(im, reloaded.convert('RGB'), 10)
def test_palette_434(self):
# see https://github.com/python-pillow/Pillow/issues/434
def roundtrip(im, *args, **kwargs):
out = self.tempfile('temp.gif')
im.save(out, *args, **kwargs)
reloaded = Image.open(out)
return [im, reloaded]
orig = "Tests/images/test.colors.gif"
im = Image.open(orig)
self.assert_image_equal(*roundtrip(im))
self.assert_image_equal(*roundtrip(im, optimize=True))
im = im.convert("RGB")
# check automatic P conversion
reloaded = roundtrip(im)[1].convert('RGB')
self.assert_image_equal(im, reloaded)
def test_palette_handling(): if __name__ == '__main__':
# see https://github.com/python-imaging/Pillow/issues/513 unittest.main()
im = Image.open('Images/lena.gif') # End of file
im = im.convert('RGB')
im = im.resize((100,100), Image.ANTIALIAS)
im2 = im.convert('P', palette=Image.ADAPTIVE, colors=256)
f = tempfile('temp.gif')
im2.save(f, optimize=True)
reloaded = Image.open(f)
assert_image_similar(im, reloaded.convert('RGB'), 10)
def test_palette_434():
# see https://github.com/python-imaging/Pillow/issues/434
def roundtrip(im, *args, **kwargs):
out = tempfile('temp.gif')
im.save(out, *args, **kwargs)
reloaded = Image.open(out)
return [im, reloaded]
orig = "Tests/images/test.colors.gif"
im = Image.open(orig)
assert_image_equal(*roundtrip(im))
assert_image_equal(*roundtrip(im, optimize=True))
im = im.convert("RGB")
# check automatic P conversion
reloaded = roundtrip(im)[1].convert('RGB')
assert_image_equal(im, reloaded)

View File

@ -1,4 +1,4 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule
from PIL import Image from PIL import Image
@ -8,59 +8,67 @@ data = open(file, "rb").read()
enable_jpeg2k = hasattr(Image.core, 'jp2klib_version') enable_jpeg2k = hasattr(Image.core, 'jp2klib_version')
def test_sanity():
# Loading this icon by default should result in the largest size
# (512x512@2x) being loaded
im = Image.open(file)
im.load()
assert_equal(im.mode, "RGBA")
assert_equal(im.size, (1024, 1024))
assert_equal(im.format, "ICNS")
def test_sizes(): class TestFileIcns(PillowTestCase):
# Check that we can load all of the sizes, and that the final pixel
# dimensions are as expected
im = Image.open(file)
for w,h,r in im.info['sizes']:
wr = w * r
hr = h * r
im2 = Image.open(file)
im2.size = (w, h, r)
im2.load()
assert_equal(im2.mode, 'RGBA')
assert_equal(im2.size, (wr, hr))
def test_older_icon(): def test_sanity(self):
# This icon was made with Icon Composer rather than iconutil; it still # Loading this icon by default should result in the largest size
# uses PNG rather than JP2, however (since it was made on 10.9). # (512x512@2x) being loaded
im = Image.open('Tests/images/pillow2.icns') im = Image.open(file)
for w,h,r in im.info['sizes']: im.load()
wr = w * r self.assertEqual(im.mode, "RGBA")
hr = h * r self.assertEqual(im.size, (1024, 1024))
im2 = Image.open('Tests/images/pillow2.icns') self.assertEqual(im.format, "ICNS")
im2.size = (w, h, r)
im2.load()
assert_equal(im2.mode, 'RGBA')
assert_equal(im2.size, (wr, hr))
def test_jp2_icon(): def test_sizes(self):
# This icon was made by using Uli Kusterer's oldiconutil to replace # Check that we can load all of the sizes, and that the final pixel
# the PNG images with JPEG 2000 ones. The advantage of doing this is # dimensions are as expected
# that OS X 10.5 supports JPEG 2000 but not PNG; some commercial im = Image.open(file)
# software therefore does just this. for w, h, r in im.info['sizes']:
wr = w * r
# (oldiconutil is here: https://github.com/uliwitness/oldiconutil) hr = h * r
im2 = Image.open(file)
im2.size = (w, h, r)
im2.load()
self.assertEqual(im2.mode, 'RGBA')
self.assertEqual(im2.size, (wr, hr))
if not enable_jpeg2k: def test_older_icon(self):
return # This icon was made with Icon Composer rather than iconutil; it still
# uses PNG rather than JP2, however (since it was made on 10.9).
im = Image.open('Tests/images/pillow3.icns') im = Image.open('Tests/images/pillow2.icns')
for w,h,r in im.info['sizes']: for w, h, r in im.info['sizes']:
wr = w * r wr = w * r
hr = h * r hr = h * r
im2 = Image.open('Tests/images/pillow3.icns') im2 = Image.open('Tests/images/pillow2.icns')
im2.size = (w, h, r) im2.size = (w, h, r)
im2.load() im2.load()
assert_equal(im2.mode, 'RGBA') self.assertEqual(im2.mode, 'RGBA')
assert_equal(im2.size, (wr, hr)) self.assertEqual(im2.size, (wr, hr))
def test_jp2_icon(self):
# This icon was made by using Uli Kusterer's oldiconutil to replace
# the PNG images with JPEG 2000 ones. The advantage of doing this is
# that OS X 10.5 supports JPEG 2000 but not PNG; some commercial
# software therefore does just this.
# (oldiconutil is here: https://github.com/uliwitness/oldiconutil)
if not enable_jpeg2k:
return
im = Image.open('Tests/images/pillow3.icns')
for w, h, r in im.info['sizes']:
wr = w * r
hr = h * r
im2 = Image.open('Tests/images/pillow3.icns')
im2.size = (w, h, r)
im2.load()
self.assertEqual(im2.mode, 'RGBA')
self.assertEqual(im2.size, (wr, hr))
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,4 +1,4 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule
from PIL import Image from PIL import Image
@ -6,9 +6,18 @@ from PIL import Image
file = "Images/lena.ico" file = "Images/lena.ico"
data = open(file, "rb").read() data = open(file, "rb").read()
def test_sanity():
im = Image.open(file) class TestFileIco(PillowTestCase):
im.load()
assert_equal(im.mode, "RGBA") def test_sanity(self):
assert_equal(im.size, (16, 16)) im = Image.open(file)
assert_equal(im.format, "ICO") im.load()
self.assertEqual(im.mode, "RGBA")
self.assertEqual(im.size, (16, 16))
self.assertEqual(im.format, "ICO")
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,245 +1,237 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena, py3
import random import random
from io import BytesIO
from PIL import Image from PIL import Image
from PIL import ImageFile from PIL import ImageFile
codecs = dir(Image.core) codecs = dir(Image.core)
if "jpeg_encoder" not in codecs or "jpeg_decoder" not in codecs: test_file = "Tests/images/lena.jpg"
skip("jpeg support not available")
test_file = "Images/lena.jpg"
def roundtrip(im, **options): class TestFileJpeg(PillowTestCase):
out = BytesIO()
im.save(out, "JPEG", **options)
bytes = out.tell()
out.seek(0)
im = Image.open(out)
im.bytes = bytes # for testing only
return im
# -------------------------------------------------------------------- def setUp(self):
if "jpeg_encoder" not in codecs or "jpeg_decoder" not in codecs:
self.skipTest("jpeg support not available")
def roundtrip(self, im, **options):
out = BytesIO()
im.save(out, "JPEG", **options)
bytes = out.tell()
out.seek(0)
im = Image.open(out)
im.bytes = bytes # for testing only
return im
def test_sanity(): def test_sanity(self):
# internal version number # internal version number
assert_match(Image.core.jpeglib_version, "\d+\.\d+$") self.assertRegexpMatches(Image.core.jpeglib_version, "\d+\.\d+$")
im = Image.open(test_file)
im.load()
assert_equal(im.mode, "RGB")
assert_equal(im.size, (128, 128))
assert_equal(im.format, "JPEG")
# --------------------------------------------------------------------
def test_app():
# Test APP/COM reader (@PIL135)
im = Image.open(test_file)
assert_equal(im.applist[0],
("APP0", b"JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00"))
assert_equal(im.applist[1], ("COM", b"Python Imaging Library"))
assert_equal(len(im.applist), 2)
def test_cmyk():
# Test CMYK handling. Thanks to Tim and Charlie for test data,
# Michael for getting me to look one more time.
f = "Tests/images/pil_sample_cmyk.jpg"
im = Image.open(f)
# the source image has red pixels in the upper left corner.
c, m, y, k = [x / 255.0 for x in im.getpixel((0, 0))]
assert_true(c == 0.0 and m > 0.8 and y > 0.8 and k == 0.0)
# the opposite corner is black
c, m, y, k = [x / 255.0 for x in im.getpixel((im.size[0]-1, im.size[1]-1))]
assert_true(k > 0.9)
# roundtrip, and check again
im = roundtrip(im)
c, m, y, k = [x / 255.0 for x in im.getpixel((0, 0))]
assert_true(c == 0.0 and m > 0.8 and y > 0.8 and k == 0.0)
c, m, y, k = [x / 255.0 for x in im.getpixel((im.size[0]-1, im.size[1]-1))]
assert_true(k > 0.9)
def test_dpi():
def test(xdpi, ydpi=None):
im = Image.open(test_file) im = Image.open(test_file)
im = roundtrip(im, dpi=(xdpi, ydpi or xdpi)) im.load()
return im.info.get("dpi") self.assertEqual(im.mode, "RGB")
assert_equal(test(72), (72, 72)) self.assertEqual(im.size, (128, 128))
assert_equal(test(300), (300, 300)) self.assertEqual(im.format, "JPEG")
assert_equal(test(100, 200), (100, 200))
assert_equal(test(0), None) # square pixels def test_app(self):
# Test APP/COM reader (@PIL135)
im = Image.open(test_file)
self.assertEqual(
im.applist[0],
("APP0", b"JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00"))
self.assertEqual(im.applist[1], ("COM", b"Python Imaging Library"))
self.assertEqual(len(im.applist), 2)
def test_cmyk(self):
# Test CMYK handling. Thanks to Tim and Charlie for test data,
# Michael for getting me to look one more time.
f = "Tests/images/pil_sample_cmyk.jpg"
im = Image.open(f)
# the source image has red pixels in the upper left corner.
c, m, y, k = [x / 255.0 for x in im.getpixel((0, 0))]
self.assertEqual(c, 0.0)
self.assertGreater(m, 0.8)
self.assertGreater(y, 0.8)
self.assertEqual(k, 0.0)
# the opposite corner is black
c, m, y, k = [x / 255.0 for x in im.getpixel((im.size[0]-1, im.size[1]-1))]
self.assertGreater(k, 0.9)
# roundtrip, and check again
im = self.roundtrip(im)
c, m, y, k = [x / 255.0 for x in im.getpixel((0, 0))]
self.assertEqual(c, 0.0)
self.assertGreater(m, 0.8)
self.assertGreater(y, 0.8)
self.assertEqual(k, 0.0)
c, m, y, k = [x / 255.0 for x in im.getpixel((im.size[0]-1, im.size[1]-1))]
self.assertGreater(k, 0.9)
def test_dpi(self):
def test(xdpi, ydpi=None):
im = Image.open(test_file)
im = self.roundtrip(im, dpi=(xdpi, ydpi or xdpi))
return im.info.get("dpi")
self.assertEqual(test(72), (72, 72))
self.assertEqual(test(300), (300, 300))
self.assertEqual(test(100, 200), (100, 200))
self.assertEqual(test(0), None) # square pixels
def test_icc(self):
# Test ICC support
im1 = Image.open("Tests/images/rgb.jpg")
icc_profile = im1.info["icc_profile"]
self.assertEqual(len(icc_profile), 3144)
# Roundtrip via physical file.
f = self.tempfile("temp.jpg")
im1.save(f, icc_profile=icc_profile)
im2 = Image.open(f)
self.assertEqual(im2.info.get("icc_profile"), icc_profile)
# Roundtrip via memory buffer.
im1 = self.roundtrip(lena())
im2 = self.roundtrip(lena(), icc_profile=icc_profile)
self.assert_image_equal(im1, im2)
self.assertFalse(im1.info.get("icc_profile"))
self.assertTrue(im2.info.get("icc_profile"))
def test_icc_big(self):
# Make sure that the "extra" support handles large blocks
def test(n):
# The ICC APP marker can store 65519 bytes per marker, so
# using a 4-byte test code should allow us to detect out of
# order issues.
icc_profile = (b"Test"*int(n/4+1))[:n]
assert len(icc_profile) == n # sanity
im1 = self.roundtrip(lena(), icc_profile=icc_profile)
self.assertEqual(im1.info.get("icc_profile"), icc_profile or None)
test(0)
test(1)
test(3)
test(4)
test(5)
test(65533-14) # full JPEG marker block
test(65533-14+1) # full block plus one byte
test(ImageFile.MAXBLOCK) # full buffer block
test(ImageFile.MAXBLOCK+1) # full buffer block plus one byte
test(ImageFile.MAXBLOCK*4+3) # large block
def test_optimize(self):
im1 = self.roundtrip(lena())
im2 = self.roundtrip(lena(), optimize=1)
self.assert_image_equal(im1, im2)
self.assertGreaterEqual(im1.bytes, im2.bytes)
def test_optimize_large_buffer(self):
# https://github.com/python-pillow/Pillow/issues/148
f = self.tempfile('temp.jpg')
# this requires ~ 1.5x Image.MAXBLOCK
im = Image.new("RGB", (4096, 4096), 0xff3333)
im.save(f, format="JPEG", optimize=True)
def test_progressive(self):
im1 = self.roundtrip(lena())
im2 = self.roundtrip(lena(), progressive=True)
self.assert_image_equal(im1, im2)
self.assertGreaterEqual(im1.bytes, im2.bytes)
def test_progressive_large_buffer(self):
f = self.tempfile('temp.jpg')
# this requires ~ 1.5x Image.MAXBLOCK
im = Image.new("RGB", (4096, 4096), 0xff3333)
im.save(f, format="JPEG", progressive=True)
def test_progressive_large_buffer_highest_quality(self):
f = self.tempfile('temp.jpg')
if py3:
a = bytes(random.randint(0, 255) for _ in range(256 * 256 * 3))
else:
a = b''.join(chr(random.randint(0, 255)) for _ in range(256 * 256 * 3))
im = Image.frombuffer("RGB", (256, 256), a, "raw", "RGB", 0, 1)
# this requires more bytes than pixels in the image
im.save(f, format="JPEG", progressive=True, quality=100)
def test_large_exif(self):
# https://github.com/python-pillow/Pillow/issues/148
f = self.tempfile('temp.jpg')
im = lena()
im.save(f, 'JPEG', quality=90, exif=b"1"*65532)
def test_progressive_compat(self):
im1 = self.roundtrip(lena())
im2 = self.roundtrip(lena(), progressive=1)
im3 = self.roundtrip(lena(), progression=1) # compatibility
self.assert_image_equal(im1, im2)
self.assert_image_equal(im1, im3)
self.assertFalse(im1.info.get("progressive"))
self.assertFalse(im1.info.get("progression"))
self.assertTrue(im2.info.get("progressive"))
self.assertTrue(im2.info.get("progression"))
self.assertTrue(im3.info.get("progressive"))
self.assertTrue(im3.info.get("progression"))
def test_quality(self):
im1 = self.roundtrip(lena())
im2 = self.roundtrip(lena(), quality=50)
self.assert_image(im1, im2.mode, im2.size)
self.assertGreaterEqual(im1.bytes, im2.bytes)
def test_smooth(self):
im1 = self.roundtrip(lena())
im2 = self.roundtrip(lena(), smooth=100)
self.assert_image(im1, im2.mode, im2.size)
def test_subsampling(self):
def getsampling(im):
layer = im.layer
return layer[0][1:3] + layer[1][1:3] + layer[2][1:3]
# experimental API
im = self.roundtrip(lena(), subsampling=-1) # default
self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1))
im = self.roundtrip(lena(), subsampling=0) # 4:4:4
self.assertEqual(getsampling(im), (1, 1, 1, 1, 1, 1))
im = self.roundtrip(lena(), subsampling=1) # 4:2:2
self.assertEqual(getsampling(im), (2, 1, 1, 1, 1, 1))
im = self.roundtrip(lena(), subsampling=2) # 4:1:1
self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1))
im = self.roundtrip(lena(), subsampling=3) # default (undefined)
self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1))
im = self.roundtrip(lena(), subsampling="4:4:4")
self.assertEqual(getsampling(im), (1, 1, 1, 1, 1, 1))
im = self.roundtrip(lena(), subsampling="4:2:2")
self.assertEqual(getsampling(im), (2, 1, 1, 1, 1, 1))
im = self.roundtrip(lena(), subsampling="4:1:1")
self.assertEqual(getsampling(im), (2, 2, 1, 1, 1, 1))
self.assertRaises(
TypeError, lambda: self.roundtrip(lena(), subsampling="1:1:1"))
def test_exif(self):
im = Image.open("Tests/images/pil_sample_rgb.jpg")
info = im._getexif()
self.assertEqual(info[305], 'Adobe Photoshop CS Macintosh')
def test_quality_keep(self):
im = Image.open("Tests/images/lena.jpg")
f = self.tempfile('temp.jpg')
im.save(f, quality='keep')
def test_junk_jpeg_header(self):
# https://github.com/python-pillow/Pillow/issues/630
filename = "Tests/images/junk_jpeg_header.jpg"
Image.open(filename)
def test_qtables():
im = Image.open("Tests/images/lena.jpg")
qtables = im.quantization
reloaded = self.roundtrip(im, qtables=qtables, subsampling=0)
self.assertEqual(im.quantization, reloaded.quantization)
def test_icc(): if __name__ == '__main__':
# Test ICC support unittest.main()
im1 = Image.open("Tests/images/rgb.jpg")
icc_profile = im1.info["icc_profile"]
assert_equal(len(icc_profile), 3144)
# Roundtrip via physical file.
f = tempfile("temp.jpg")
im1.save(f, icc_profile=icc_profile)
im2 = Image.open(f)
assert_equal(im2.info.get("icc_profile"), icc_profile)
# Roundtrip via memory buffer.
im1 = roundtrip(lena())
im2 = roundtrip(lena(), icc_profile=icc_profile)
assert_image_equal(im1, im2)
assert_false(im1.info.get("icc_profile"))
assert_true(im2.info.get("icc_profile"))
def test_icc_big():
# Make sure that the "extra" support handles large blocks
def test(n):
# The ICC APP marker can store 65519 bytes per marker, so
# using a 4-byte test code should allow us to detect out of
# order issues.
icc_profile = (b"Test"*int(n/4+1))[:n]
assert len(icc_profile) == n # sanity
im1 = roundtrip(lena(), icc_profile=icc_profile)
assert_equal(im1.info.get("icc_profile"), icc_profile or None)
test(0)
test(1)
test(3)
test(4)
test(5)
test(65533-14) # full JPEG marker block
test(65533-14+1) # full block plus one byte
test(ImageFile.MAXBLOCK) # full buffer block
test(ImageFile.MAXBLOCK+1) # full buffer block plus one byte
test(ImageFile.MAXBLOCK*4+3) # large block
def test_optimize():
im1 = roundtrip(lena())
im2 = roundtrip(lena(), optimize=1)
assert_image_equal(im1, im2)
assert_true(im1.bytes >= im2.bytes)
def test_optimize_large_buffer():
# https://github.com/python-imaging/Pillow/issues/148
f = tempfile('temp.jpg')
# this requires ~ 1.5x Image.MAXBLOCK
im = Image.new("RGB", (4096, 4096), 0xff3333)
im.save(f, format="JPEG", optimize=True)
def test_progressive():
im1 = roundtrip(lena())
im2 = roundtrip(lena(), progressive=True)
assert_image_equal(im1, im2)
assert_true(im1.bytes >= im2.bytes)
def test_progressive_large_buffer():
f = tempfile('temp.jpg')
# this requires ~ 1.5x Image.MAXBLOCK
im = Image.new("RGB", (4096, 4096), 0xff3333)
im.save(f, format="JPEG", progressive=True)
def test_progressive_large_buffer_highest_quality():
f = tempfile('temp.jpg')
if py3:
a = bytes(random.randint(0, 255) for _ in range(256 * 256 * 3))
else:
a = b''.join(chr(random.randint(0, 255)) for _ in range(256 * 256 * 3))
im = Image.frombuffer("RGB", (256, 256), a, "raw", "RGB", 0, 1)
# this requires more bytes than pixels in the image
im.save(f, format="JPEG", progressive=True, quality=100)
def test_large_exif():
# https://github.com/python-imaging/Pillow/issues/148
f = tempfile('temp.jpg')
im = lena()
im.save(f, 'JPEG', quality=90, exif=b"1"*65532)
def test_progressive_compat():
im1 = roundtrip(lena())
im2 = roundtrip(lena(), progressive=1)
im3 = roundtrip(lena(), progression=1) # compatibility
assert_image_equal(im1, im2)
assert_image_equal(im1, im3)
assert_false(im1.info.get("progressive"))
assert_false(im1.info.get("progression"))
assert_true(im2.info.get("progressive"))
assert_true(im2.info.get("progression"))
assert_true(im3.info.get("progressive"))
assert_true(im3.info.get("progression"))
def test_quality():
im1 = roundtrip(lena())
im2 = roundtrip(lena(), quality=50)
assert_image(im1, im2.mode, im2.size)
assert_true(im1.bytes >= im2.bytes)
def test_smooth():
im1 = roundtrip(lena())
im2 = roundtrip(lena(), smooth=100)
assert_image(im1, im2.mode, im2.size)
def test_subsampling():
def getsampling(im):
layer = im.layer
return layer[0][1:3] + layer[1][1:3] + layer[2][1:3]
# experimental API
im = roundtrip(lena(), subsampling=-1) # default
assert_equal(getsampling(im), (2, 2, 1, 1, 1, 1))
im = roundtrip(lena(), subsampling=0) # 4:4:4
assert_equal(getsampling(im), (1, 1, 1, 1, 1, 1))
im = roundtrip(lena(), subsampling=1) # 4:2:2
assert_equal(getsampling(im), (2, 1, 1, 1, 1, 1))
im = roundtrip(lena(), subsampling=2) # 4:1:1
assert_equal(getsampling(im), (2, 2, 1, 1, 1, 1))
im = roundtrip(lena(), subsampling=3) # default (undefined)
assert_equal(getsampling(im), (2, 2, 1, 1, 1, 1))
im = roundtrip(lena(), subsampling="4:4:4")
assert_equal(getsampling(im), (1, 1, 1, 1, 1, 1))
im = roundtrip(lena(), subsampling="4:2:2")
assert_equal(getsampling(im), (2, 1, 1, 1, 1, 1))
im = roundtrip(lena(), subsampling="4:1:1")
assert_equal(getsampling(im), (2, 2, 1, 1, 1, 1))
assert_exception(TypeError, lambda: roundtrip(lena(), subsampling="1:1:1"))
def test_exif():
im = Image.open("Tests/images/pil_sample_rgb.jpg")
info = im._getexif()
assert_equal(info[305], 'Adobe Photoshop CS Macintosh')
def test_quality_keep():
im = Image.open("Images/lena.jpg")
f = tempfile('temp.jpg')
assert_no_exception(lambda: im.save(f, quality='keep'))
def test_qtables():
im = Image.open("Images/lena.jpg")
qtables = im.quantization
f = tempfile('temp.jpg')
assert_no_exception(lambda: im.save(f, qtables=qtables, subsampling=0))
def test_junk_jpeg_header():
# https://github.com/python-imaging/Pillow/issues/630
filename = "Tests/images/junk_jpeg_header.jpg"
assert_no_exception(lambda: Image.open(filename))
# End of file # End of file

View File

@ -1,110 +1,114 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule
from PIL import Image from PIL import Image
from PIL import ImageFile from io import BytesIO
codecs = dir(Image.core) codecs = dir(Image.core)
if "jpeg2k_encoder" not in codecs or "jpeg2k_decoder" not in codecs:
skip('JPEG 2000 support not available')
# OpenJPEG 2.0.0 outputs this debugging message sometimes; we should
# ignore it---it doesn't represent a test failure.
ignore('Not enough memory to handle tile data')
test_card = Image.open('Tests/images/test-card.png') test_card = Image.open('Tests/images/test-card.png')
test_card.load() test_card.load()
def roundtrip(im, **options): # OpenJPEG 2.0.0 outputs this debugging message sometimes; we should
out = BytesIO() # ignore it---it doesn't represent a test failure.
im.save(out, "JPEG2000", **options) # 'Not enough memory to handle tile data'
bytes = out.tell()
out.seek(0)
im = Image.open(out)
im.bytes = bytes # for testing only
im.load()
return im
# ----------------------------------------------------------------------
def test_sanity(): class TestFileJpeg2k(PillowTestCase):
# Internal version number
assert_match(Image.core.jp2klib_version, '\d+\.\d+\.\d+$')
im = Image.open('Tests/images/test-card-lossless.jp2') def setUp(self):
im.load() if "jpeg2k_encoder" not in codecs or "jpeg2k_decoder" not in codecs:
assert_equal(im.mode, 'RGB') self.skipTest('JPEG 2000 support not available')
assert_equal(im.size, (640, 480))
assert_equal(im.format, 'JPEG2000')
# ----------------------------------------------------------------------
# These two test pre-written JPEG 2000 files that were not written with def roundtrip(self, im, **options):
# PIL (they were made using Adobe Photoshop) out = BytesIO()
im.save(out, "JPEG2000", **options)
bytes = out.tell()
out.seek(0)
im = Image.open(out)
im.bytes = bytes # for testing only
im.load()
return im
def test_lossless(): def test_sanity(self):
im = Image.open('Tests/images/test-card-lossless.jp2') # Internal version number
im.load() self.assertRegexpMatches(Image.core.jp2klib_version, '\d+\.\d+\.\d+$')
im.save('/tmp/test-card.png')
assert_image_similar(im, test_card, 1.0e-3)
def test_lossy_tiled(): im = Image.open('Tests/images/test-card-lossless.jp2')
im = Image.open('Tests/images/test-card-lossy-tiled.jp2') im.load()
im.load() self.assertEqual(im.mode, 'RGB')
assert_image_similar(im, test_card, 2.0) self.assertEqual(im.size, (640, 480))
self.assertEqual(im.format, 'JPEG2000')
# ---------------------------------------------------------------------- # These two test pre-written JPEG 2000 files that were not written with
# PIL (they were made using Adobe Photoshop)
def test_lossless_rt(): def test_lossless(self):
im = roundtrip(test_card) im = Image.open('Tests/images/test-card-lossless.jp2')
assert_image_equal(im, test_card) im.load()
im.save('/tmp/test-card.png')
self.assert_image_similar(im, test_card, 1.0e-3)
def test_lossy_rt(): def test_lossy_tiled(self):
im = roundtrip(test_card, quality_layers=[20]) im = Image.open('Tests/images/test-card-lossy-tiled.jp2')
assert_image_similar(im, test_card, 2.0) im.load()
self.assert_image_similar(im, test_card, 2.0)
def test_tiled_rt(): def test_lossless_rt(self):
im = roundtrip(test_card, tile_size=(128, 128)) im = self.roundtrip(test_card)
assert_image_equal(im, test_card) self.assert_image_equal(im, test_card)
def test_tiled_offset_rt(): def test_lossy_rt(self):
im = roundtrip(test_card, tile_size=(128, 128), tile_offset=(0, 0), im = self.roundtrip(test_card, quality_layers=[20])
offset=(32, 32)) self.assert_image_similar(im, test_card, 2.0)
assert_image_equal(im, test_card)
def test_irreversible_rt():
im = roundtrip(test_card, irreversible=True, quality_layers=[20])
assert_image_similar(im, test_card, 2.0)
def test_prog_qual_rt(): def test_tiled_rt(self):
im = roundtrip(test_card, quality_layers=[60, 40, 20], progression='LRCP') im = self.roundtrip(test_card, tile_size=(128, 128))
assert_image_similar(im, test_card, 2.0) self.assert_image_equal(im, test_card)
def test_prog_res_rt(): def test_tiled_offset_rt(self):
im = roundtrip(test_card, num_resolutions=8, progression='RLCP') im = self.roundtrip(
assert_image_equal(im, test_card) test_card, tile_size=(128, 128),
tile_offset=(0, 0), offset=(32, 32))
self.assert_image_equal(im, test_card)
# ---------------------------------------------------------------------- def test_irreversible_rt(self):
im = self.roundtrip(test_card, irreversible=True, quality_layers=[20])
self.assert_image_similar(im, test_card, 2.0)
def test_reduce(): def test_prog_qual_rt(self):
im = Image.open('Tests/images/test-card-lossless.jp2') im = self.roundtrip(
im.reduce = 2 test_card, quality_layers=[60, 40, 20], progression='LRCP')
im.load() self.assert_image_similar(im, test_card, 2.0)
assert_equal(im.size, (160, 120))
def test_layers(): def test_prog_res_rt(self):
out = BytesIO() im = self.roundtrip(test_card, num_resolutions=8, progression='RLCP')
test_card.save(out, 'JPEG2000', quality_layers=[100, 50, 10], self.assert_image_equal(im, test_card)
progression='LRCP')
out.seek(0)
im = Image.open(out)
im.layers = 1
im.load()
assert_image_similar(im, test_card, 13)
out.seek(0) def test_reduce(self):
im = Image.open(out) im = Image.open('Tests/images/test-card-lossless.jp2')
im.layers = 3 im.reduce = 2
im.load() im.load()
assert_image_similar(im, test_card, 0.4) self.assertEqual(im.size, (160, 120))
def test_layers(self):
out = BytesIO()
test_card.save(out, 'JPEG2000', quality_layers=[100, 50, 10],
progression='LRCP')
out.seek(0)
im = Image.open(out)
im.layers = 1
im.load()
self.assert_image_similar(im, test_card, 13)
out.seek(0)
im = Image.open(out)
im.layers = 3
im.load()
self.assert_image_similar(im, test_card, 0.4)
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,300 +1,318 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena, py3
import os import os
from PIL import Image, TiffImagePlugin from PIL import Image, TiffImagePlugin
codecs = dir(Image.core)
if "libtiff_encoder" not in codecs or "libtiff_decoder" not in codecs: class TestFileLibTiff(PillowTestCase):
skip("tiff support not available")
def _assert_noerr(im): def setUp(self):
"""Helper tests that assert basic sanity about the g4 tiff reading""" codecs = dir(Image.core)
#1 bit
assert_equal(im.mode, "1")
# Does the data actually load if "libtiff_encoder" not in codecs or "libtiff_decoder" not in codecs:
assert_no_exception(lambda: im.load()) self.skipTest("tiff support not available")
assert_no_exception(lambda: im.getdata())
try: def _assert_noerr(self, im):
assert_equal(im._compression, 'group4') """Helper tests that assert basic sanity about the g4 tiff reading"""
except: # 1 bit
print("No _compression") self.assertEqual(im.mode, "1")
print (dir(im))
# can we write it back out, in a different form. # Does the data actually load
out = tempfile("temp.png") im.load()
assert_no_exception(lambda: im.save(out)) im.getdata()
def test_g4_tiff(): try:
"""Test the ordinary file path load path""" self.assertEqual(im._compression, 'group4')
except:
print("No _compression")
print (dir(im))
file = "Tests/images/lena_g4_500.tif" # can we write it back out, in a different form.
im = Image.open(file) out = self.tempfile("temp.png")
im.save(out)
assert_equal(im.size, (500,500)) def test_g4_tiff(self):
_assert_noerr(im) """Test the ordinary file path load path"""
def test_g4_large(): file = "Tests/images/lena_g4_500.tif"
file = "Tests/images/pport_g4.tif" im = Image.open(file)
im = Image.open(file)
_assert_noerr(im)
def test_g4_tiff_file(): self.assertEqual(im.size, (500, 500))
"""Testing the string load path""" self._assert_noerr(im)
file = "Tests/images/lena_g4_500.tif" def test_g4_large(self):
with open(file,'rb') as f: file = "Tests/images/pport_g4.tif"
im = Image.open(f) im = Image.open(file)
self._assert_noerr(im)
assert_equal(im.size, (500,500)) def test_g4_tiff_file(self):
_assert_noerr(im) """Testing the string load path"""
def test_g4_tiff_bytesio(): file = "Tests/images/lena_g4_500.tif"
"""Testing the stringio loading code path""" with open(file, 'rb') as f:
from io import BytesIO im = Image.open(f)
file = "Tests/images/lena_g4_500.tif"
s = BytesIO()
with open(file,'rb') as f:
s.write(f.read())
s.seek(0)
im = Image.open(s)
assert_equal(im.size, (500,500)) self.assertEqual(im.size, (500, 500))
_assert_noerr(im) self._assert_noerr(im)
def test_g4_eq_png(): def test_g4_tiff_bytesio(self):
""" Checking that we're actually getting the data that we expect""" """Testing the stringio loading code path"""
png = Image.open('Tests/images/lena_bw_500.png') from io import BytesIO
g4 = Image.open('Tests/images/lena_g4_500.tif') file = "Tests/images/lena_g4_500.tif"
s = BytesIO()
with open(file, 'rb') as f:
s.write(f.read())
s.seek(0)
im = Image.open(s)
assert_image_equal(g4, png) self.assertEqual(im.size, (500, 500))
self._assert_noerr(im)
# see https://github.com/python-imaging/Pillow/issues/279 def test_g4_eq_png(self):
def test_g4_fillorder_eq_png(): """ Checking that we're actually getting the data that we expect"""
""" Checking that we're actually getting the data that we expect""" png = Image.open('Tests/images/lena_bw_500.png')
png = Image.open('Tests/images/g4-fillorder-test.png') g4 = Image.open('Tests/images/lena_g4_500.tif')
g4 = Image.open('Tests/images/g4-fillorder-test.tif')
assert_image_equal(g4, png) self.assert_image_equal(g4, png)
def test_g4_write(): # see https://github.com/python-pillow/Pillow/issues/279
"""Checking to see that the saved image is the same as what we wrote""" def test_g4_fillorder_eq_png(self):
file = "Tests/images/lena_g4_500.tif" """ Checking that we're actually getting the data that we expect"""
orig = Image.open(file) png = Image.open('Tests/images/g4-fillorder-test.png')
g4 = Image.open('Tests/images/g4-fillorder-test.tif')
out = tempfile("temp.tif") self.assert_image_equal(g4, png)
rot = orig.transpose(Image.ROTATE_90)
assert_equal(rot.size,(500,500))
rot.save(out)
reread = Image.open(out) def test_g4_write(self):
assert_equal(reread.size,(500,500)) """Checking to see that the saved image is the same as what we wrote"""
_assert_noerr(reread) file = "Tests/images/lena_g4_500.tif"
assert_image_equal(reread, rot) orig = Image.open(file)
assert_equal(reread.info['compression'], 'group4')
assert_equal(reread.info['compression'], orig.info['compression']) out = self.tempfile("temp.tif")
rot = orig.transpose(Image.ROTATE_90)
assert_false(orig.tobytes() == reread.tobytes()) self.assertEqual(rot.size, (500, 500))
rot.save(out)
def test_adobe_deflate_tiff(): reread = Image.open(out)
file = "Tests/images/tiff_adobe_deflate.tif" self.assertEqual(reread.size, (500, 500))
im = Image.open(file) self._assert_noerr(reread)
self.assert_image_equal(reread, rot)
self.assertEqual(reread.info['compression'], 'group4')
assert_equal(im.mode, "RGB") self.assertEqual(reread.info['compression'], orig.info['compression'])
assert_equal(im.size, (278, 374))
assert_equal(im.tile[0][:3], ('tiff_adobe_deflate', (0, 0, 278, 374), 0))
assert_no_exception(lambda: im.load())
def test_write_metadata(): self.assertNotEqual(orig.tobytes(), reread.tobytes())
""" Test metadata writing through libtiff """
img = Image.open('Tests/images/lena_g4.tif')
f = tempfile('temp.tiff')
img.save(f, tiffinfo = img.tag) def test_adobe_deflate_tiff(self):
file = "Tests/images/tiff_adobe_deflate.tif"
im = Image.open(file)
loaded = Image.open(f) self.assertEqual(im.mode, "RGB")
self.assertEqual(im.size, (278, 374))
self.assertEqual(
im.tile[0][:3], ('tiff_adobe_deflate', (0, 0, 278, 374), 0))
im.load()
original = img.tag.named() def test_write_metadata(self):
reloaded = loaded.tag.named() """ Test metadata writing through libtiff """
img = Image.open('Tests/images/lena_g4.tif')
f = self.tempfile('temp.tiff')
# PhotometricInterpretation is set from SAVE_INFO, not the original image. img.save(f, tiffinfo=img.tag)
ignored = ['StripByteCounts', 'RowsPerStrip', 'PageNumber', 'PhotometricInterpretation']
for tag, value in reloaded.items(): loaded = Image.open(f)
if tag not in ignored:
if tag.endswith('Resolution'):
val = original[tag]
assert_almost_equal(val[0][0]/val[0][1], value[0][0]/value[0][1],
msg="%s didn't roundtrip" % tag)
else:
assert_equal(original[tag], value, "%s didn't roundtrip" % tag)
for tag, value in original.items(): original = img.tag.named()
if tag not in ignored: reloaded = loaded.tag.named()
if tag.endswith('Resolution'):
val = reloaded[tag]
assert_almost_equal(val[0][0]/val[0][1], value[0][0]/value[0][1],
msg="%s didn't roundtrip" % tag)
else:
assert_equal(value, reloaded[tag], "%s didn't roundtrip" % tag)
# PhotometricInterpretation is set from SAVE_INFO,
# not the original image.
ignored = [
'StripByteCounts', 'RowsPerStrip',
'PageNumber', 'PhotometricInterpretation']
def test_g3_compression(): for tag, value in reloaded.items():
i = Image.open('Tests/images/lena_g4_500.tif') if tag not in ignored:
out = tempfile("temp.tif") if tag.endswith('Resolution'):
i.save(out, compression='group3') val = original[tag]
self.assert_almost_equal(
val[0][0]/val[0][1], value[0][0]/value[0][1],
msg="%s didn't roundtrip" % tag)
else:
self.assertEqual(
original[tag], value, "%s didn't roundtrip" % tag)
reread = Image.open(out) for tag, value in original.items():
assert_equal(reread.info['compression'], 'group3') if tag not in ignored:
assert_image_equal(reread, i) if tag.endswith('Resolution'):
val = reloaded[tag]
self.assert_almost_equal(
val[0][0]/val[0][1], value[0][0]/value[0][1],
msg="%s didn't roundtrip" % tag)
else:
self.assertEqual(
value, reloaded[tag], "%s didn't roundtrip" % tag)
def test_little_endian(): def test_g3_compression(self):
im = Image.open('Tests/images/16bit.deflate.tif') i = Image.open('Tests/images/lena_g4_500.tif')
assert_equal(im.getpixel((0,0)), 480) out = self.tempfile("temp.tif")
assert_equal(im.mode, 'I;16') i.save(out, compression='group3')
b = im.tobytes() reread = Image.open(out)
# Bytes are in image native order (little endian) self.assertEqual(reread.info['compression'], 'group3')
if py3: self.assert_image_equal(reread, i)
assert_equal(b[0], ord(b'\xe0'))
assert_equal(b[1], ord(b'\x01'))
else:
assert_equal(b[0], b'\xe0')
assert_equal(b[1], b'\x01')
out = tempfile("temp.tif") def test_little_endian(self):
#out = "temp.le.tif" im = Image.open('Tests/images/16bit.deflate.tif')
im.save(out) self.assertEqual(im.getpixel((0, 0)), 480)
reread = Image.open(out) self.assertEqual(im.mode, 'I;16')
assert_equal(reread.info['compression'], im.info['compression']) b = im.tobytes()
assert_equal(reread.getpixel((0,0)), 480) # Bytes are in image native order (little endian)
# UNDONE - libtiff defaults to writing in native endian, so if py3:
# on big endian, we'll get back mode = 'I;16B' here. self.assertEqual(b[0], ord(b'\xe0'))
self.assertEqual(b[1], ord(b'\x01'))
def test_big_endian(): else:
im = Image.open('Tests/images/16bit.MM.deflate.tif') self.assertEqual(b[0], b'\xe0')
self.assertEqual(b[1], b'\x01')
assert_equal(im.getpixel((0,0)), 480) out = self.tempfile("temp.tif")
assert_equal(im.mode, 'I;16B') # out = "temp.le.tif"
im.save(out)
reread = Image.open(out)
b = im.tobytes() self.assertEqual(reread.info['compression'], im.info['compression'])
self.assertEqual(reread.getpixel((0, 0)), 480)
# UNDONE - libtiff defaults to writing in native endian, so
# on big endian, we'll get back mode = 'I;16B' here.
# Bytes are in image native order (big endian) def test_big_endian(self):
if py3: im = Image.open('Tests/images/16bit.MM.deflate.tif')
assert_equal(b[0], ord(b'\x01'))
assert_equal(b[1], ord(b'\xe0'))
else:
assert_equal(b[0], b'\x01')
assert_equal(b[1], b'\xe0')
out = tempfile("temp.tif")
im.save(out)
reread = Image.open(out)
assert_equal(reread.info['compression'], im.info['compression']) self.assertEqual(im.getpixel((0, 0)), 480)
assert_equal(reread.getpixel((0,0)), 480) self.assertEqual(im.mode, 'I;16B')
def test_g4_string_info(): b = im.tobytes()
"""Tests String data in info directory"""
file = "Tests/images/lena_g4_500.tif"
orig = Image.open(file)
out = tempfile("temp.tif")
orig.tag[269] = 'temp.tif' # Bytes are in image native order (big endian)
orig.save(out) if py3:
self.assertEqual(b[0], ord(b'\x01'))
reread = Image.open(out) self.assertEqual(b[1], ord(b'\xe0'))
assert_equal('temp.tif', reread.tag[269]) else:
self.assertEqual(b[0], b'\x01')
self.assertEqual(b[1], b'\xe0')
def test_12bit_rawmode(): out = self.tempfile("temp.tif")
""" Are we generating the same interpretation of the image as Imagemagick is? """ im.save(out)
TiffImagePlugin.READ_LIBTIFF = True reread = Image.open(out)
#Image.DEBUG = True
im = Image.open('Tests/images/12bit.cropped.tif')
im.load()
TiffImagePlugin.READ_LIBTIFF = False
# to make the target --
# convert 12bit.cropped.tif -depth 16 tmp.tif
# convert tmp.tif -evaluate RightShift 4 12in16bit2.tif
# imagemagick will auto scale so that a 12bit FFF is 16bit FFF0,
# so we need to unshift so that the integer values are the same.
im2 = Image.open('Tests/images/12in16bit.tif')
if Image.DEBUG: self.assertEqual(reread.info['compression'], im.info['compression'])
print (im.getpixel((0,0))) self.assertEqual(reread.getpixel((0, 0)), 480)
print (im.getpixel((0,1)))
print (im.getpixel((0,2)))
print (im2.getpixel((0,0))) def test_g4_string_info(self):
print (im2.getpixel((0,1))) """Tests String data in info directory"""
print (im2.getpixel((0,2))) file = "Tests/images/lena_g4_500.tif"
orig = Image.open(file)
assert_image_equal(im, im2)
def test_blur(): out = self.tempfile("temp.tif")
# test case from irc, how to do blur on b/w image and save to compressed tif.
from PIL import ImageFilter
out = tempfile('temp.tif')
im = Image.open('Tests/images/pport_g4.tif')
im = im.convert('L')
im=im.filter(ImageFilter.GaussianBlur(4)) orig.tag[269] = 'temp.tif'
im.save(out, compression='tiff_adobe_deflate') orig.save(out)
im2 = Image.open(out) reread = Image.open(out)
im2.load() self.assertEqual('temp.tif', reread.tag[269])
assert_image_equal(im, im2) def test_12bit_rawmode(self):
""" Are we generating the same interpretation
of the image as Imagemagick is? """
TiffImagePlugin.READ_LIBTIFF = True
# Image.DEBUG = True
im = Image.open('Tests/images/12bit.cropped.tif')
im.load()
TiffImagePlugin.READ_LIBTIFF = False
# to make the target --
# convert 12bit.cropped.tif -depth 16 tmp.tif
# convert tmp.tif -evaluate RightShift 4 12in16bit2.tif
# imagemagick will auto scale so that a 12bit FFF is 16bit FFF0,
# so we need to unshift so that the integer values are the same.
im2 = Image.open('Tests/images/12in16bit.tif')
def test_compressions(): if Image.DEBUG:
im = lena('RGB') print (im.getpixel((0, 0)))
out = tempfile('temp.tif') print (im.getpixel((0, 1)))
print (im.getpixel((0, 2)))
print (im2.getpixel((0, 0)))
print (im2.getpixel((0, 1)))
print (im2.getpixel((0, 2)))
self.assert_image_equal(im, im2)
def test_blur(self):
# test case from irc, how to do blur on b/w image
# and save to compressed tif.
from PIL import ImageFilter
out = self.tempfile('temp.tif')
im = Image.open('Tests/images/pport_g4.tif')
im = im.convert('L')
im = im.filter(ImageFilter.GaussianBlur(4))
im.save(out, compression='tiff_adobe_deflate')
for compression in ('packbits', 'tiff_lzw'):
im.save(out, compression=compression)
im2 = Image.open(out) im2 = Image.open(out)
assert_image_equal(im, im2) im2.load()
im.save(out, compression='jpeg') self.assert_image_equal(im, im2)
im2 = Image.open(out)
assert_image_similar(im, im2, 30)
def test_cmyk_save(): def test_compressions(self):
im = lena('CMYK') im = lena('RGB')
out = tempfile('temp.tif') out = self.tempfile('temp.tif')
im.save(out, compression='tiff_adobe_deflate') for compression in ('packbits', 'tiff_lzw'):
im2 = Image.open(out) im.save(out, compression=compression)
assert_image_equal(im, im2) im2 = Image.open(out)
self.assert_image_equal(im, im2)
def xtest_bw_compression_wRGB(): im.save(out, compression='jpeg')
""" This test passes, but when running all tests causes a failure due to im2 = Image.open(out)
output on stderr from the error thrown by libtiff. We need to capture that self.assert_image_similar(im, im2, 30)
but not now"""
im = lena('RGB')
out = tempfile('temp.tif')
assert_exception(IOError, lambda: im.save(out, compression='tiff_ccitt')) def test_cmyk_save(self):
assert_exception(IOError, lambda: im.save(out, compression='group3')) im = lena('CMYK')
assert_exception(IOError, lambda: im.save(out, compression='group4')) out = self.tempfile('temp.tif')
def test_fp_leak(): im.save(out, compression='tiff_adobe_deflate')
im = Image.open("Tests/images/lena_g4_500.tif") im2 = Image.open(out)
fn = im.fp.fileno() self.assert_image_equal(im, im2)
assert_no_exception(lambda: os.fstat(fn)) def xtest_bw_compression_wRGB(self):
im.load() # this should close it. """ This test passes, but when running all tests causes a failure due
assert_exception(OSError, lambda: os.fstat(fn)) to output on stderr from the error thrown by libtiff. We need to
im = None # this should force even more closed. capture that but not now"""
assert_exception(OSError, lambda: os.fstat(fn))
assert_exception(OSError, lambda: os.close(fn)) im = lena('RGB')
out = self.tempfile('temp.tif')
self.assertRaises(
IOError, lambda: im.save(out, compression='tiff_ccitt'))
self.assertRaises(IOError, lambda: im.save(out, compression='group3'))
self.assertRaises(IOError, lambda: im.save(out, compression='group4'))
def test_fp_leak(self):
im = Image.open("Tests/images/lena_g4_500.tif")
fn = im.fp.fileno()
os.fstat(fn)
im.load() # this should close it.
self.assertRaises(OSError, lambda: os.fstat(fn))
im = None # this should force even more closed.
self.assertRaises(OSError, lambda: os.fstat(fn))
self.assertRaises(OSError, lambda: os.close(fn))
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,52 +1,56 @@
from tester import * from helper import unittest, tearDownModule
from PIL import Image from PIL import Image
from test_file_libtiff import _assert_noerr from test_file_libtiff import TestFileLibTiff
codecs = dir(Image.core)
if "libtiff_encoder" not in codecs or "libtiff_decoder" not in codecs:
skip("tiff support not available")
""" The small lena image was failing on open in the libtiff
decoder because the file pointer was set to the wrong place
by a spurious seek. It wasn't failing with the byteio method.
It was fixed by forcing an lseek to the beginning of the
file just before reading in libtiff. These tests remain
to ensure that it stays fixed. """
def test_g4_lena_file(): class TestFileLibTiffSmall(TestFileLibTiff):
"""Testing the open file load path"""
file = "Tests/images/lena_g4.tif" # Inherits TestFileLibTiff's setUp() and self._assert_noerr()
with open(file,'rb') as f:
im = Image.open(f)
assert_equal(im.size, (128,128)) """ The small lena image was failing on open in the libtiff
_assert_noerr(im) decoder because the file pointer was set to the wrong place
by a spurious seek. It wasn't failing with the byteio method.
def test_g4_lena_bytesio(): It was fixed by forcing an lseek to the beginning of the
"""Testing the bytesio loading code path""" file just before reading in libtiff. These tests remain
from io import BytesIO to ensure that it stays fixed. """
file = "Tests/images/lena_g4.tif"
s = BytesIO()
with open(file,'rb') as f:
s.write(f.read())
s.seek(0)
im = Image.open(s)
assert_equal(im.size, (128,128)) def test_g4_lena_file(self):
_assert_noerr(im) """Testing the open file load path"""
def test_g4_lena(): file = "Tests/images/lena_g4.tif"
"""The 128x128 lena image fails for some reason. Investigating""" with open(file, 'rb') as f:
im = Image.open(f)
file = "Tests/images/lena_g4.tif" self.assertEqual(im.size, (128, 128))
im = Image.open(file) self._assert_noerr(im)
assert_equal(im.size, (128,128)) def test_g4_lena_bytesio(self):
_assert_noerr(im) """Testing the bytesio loading code path"""
from io import BytesIO
file = "Tests/images/lena_g4.tif"
s = BytesIO()
with open(file, 'rb') as f:
s.write(f.read())
s.seek(0)
im = Image.open(s)
self.assertEqual(im.size, (128, 128))
self._assert_noerr(im)
def test_g4_lena(self):
"""The 128x128 lena image fails for some reason. Investigating"""
file = "Tests/images/lena_g4.tif"
im = Image.open(file)
self.assertEqual(im.size, (128, 128))
self._assert_noerr(im)
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,15 +1,24 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image from PIL import Image
def test_sanity():
file = tempfile("temp.msp") class TestFileMsp(PillowTestCase):
lena("1").save(file) def test_sanity(self):
im = Image.open(file) file = self.tempfile("temp.msp")
im.load()
assert_equal(im.mode, "1") lena("1").save(file)
assert_equal(im.size, (128, 128))
assert_equal(im.format, "MSP") im = Image.open(file)
im.load()
self.assertEqual(im.mode, "1")
self.assertEqual(im.size, (128, 128))
self.assertEqual(im.format, "MSP")
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,40 +1,47 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image from PIL import Image
def _roundtrip(im): class TestFilePcx(PillowTestCase):
f = tempfile("temp.pcx")
im.save(f)
im2 = Image.open(f)
assert_equal(im2.mode, im.mode) def _roundtrip(self, im):
assert_equal(im2.size, im.size) f = self.tempfile("temp.pcx")
assert_equal(im2.format, "PCX") im.save(f)
assert_image_equal(im2, im) im2 = Image.open(f)
def test_sanity():
for mode in ('1', 'L', 'P', 'RGB'):
_roundtrip(lena(mode))
def test_odd(): self.assertEqual(im2.mode, im.mode)
# see issue #523, odd sized images should have a stride that's even. self.assertEqual(im2.size, im.size)
# not that imagemagick or gimp write pcx that way. self.assertEqual(im2.format, "PCX")
# we were not handling properly. self.assert_image_equal(im2, im)
for mode in ('1', 'L', 'P', 'RGB'):
# larger, odd sized images are better here to ensure that
# we handle interrupted scan lines properly.
_roundtrip(lena(mode).resize((511,511)))
def test_pil184(): def test_sanity(self):
# Check reading of files where xmin/xmax is not zero. for mode in ('1', 'L', 'P', 'RGB'):
self._roundtrip(lena(mode))
file = "Tests/images/pil184.pcx" def test_odd(self):
im = Image.open(file) # see issue #523, odd sized images should have a stride that's even.
# not that imagemagick or gimp write pcx that way.
# we were not handling properly.
for mode in ('1', 'L', 'P', 'RGB'):
# larger, odd sized images are better here to ensure that
# we handle interrupted scan lines properly.
self._roundtrip(lena(mode).resize((511, 511)))
assert_equal(im.size, (447, 144)) def test_pil184(self):
assert_equal(im.tile[0][1], (0, 0, 447, 144)) # Check reading of files where xmin/xmax is not zero.
# Make sure all pixels are either 0 or 255. file = "Tests/images/pil184.pcx"
assert_equal(im.histogram()[0] + im.histogram()[255], 447*144) im = Image.open(file)
self.assertEqual(im.size, (447, 144))
self.assertEqual(im.tile[0][1], (0, 0, 447, 144))
# Make sure all pixels are either 0 or 255.
self.assertEqual(im.histogram()[0] + im.histogram()[255], 447*144)
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,58 +1,59 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
import os.path import os.path
def helper_save_as_pdf(mode): class TestFilePdf(PillowTestCase):
# Arrange
im = lena(mode)
outfile = tempfile("temp_" + mode + ".pdf")
# Act def helper_save_as_pdf(self, mode):
im.save(outfile) # Arrange
im = lena(mode)
outfile = self.tempfile("temp_" + mode + ".pdf")
# Assert # Act
assert_true(os.path.isfile(outfile)) im.save(outfile)
assert_greater(os.path.getsize(outfile), 0)
# Assert
self.assertTrue(os.path.isfile(outfile))
self.assertGreater(os.path.getsize(outfile), 0)
def test_monochrome(self):
# Arrange
mode = "1"
# Act / Assert
self.helper_save_as_pdf(mode)
def test_greyscale(self):
# Arrange
mode = "L"
# Act / Assert
self.helper_save_as_pdf(mode)
def test_rgb(self):
# Arrange
mode = "RGB"
# Act / Assert
self.helper_save_as_pdf(mode)
def test_p_mode(self):
# Arrange
mode = "P"
# Act / Assert
self.helper_save_as_pdf(mode)
def test_cmyk_mode(self):
# Arrange
mode = "CMYK"
# Act / Assert
self.helper_save_as_pdf(mode)
def test_monochrome(): if __name__ == '__main__':
# Arrange unittest.main()
mode = "1"
# Act / Assert
helper_save_as_pdf(mode)
def test_greyscale():
# Arrange
mode = "L"
# Act / Assert
helper_save_as_pdf(mode)
def test_rgb():
# Arrange
mode = "RGB"
# Act / Assert
helper_save_as_pdf(mode)
def test_p_mode():
# Arrange
mode = "P"
# Act / Assert
helper_save_as_pdf(mode)
def test_cmyk_mode():
# Arrange
mode = "CMYK"
# Act / Assert
helper_save_as_pdf(mode)
# End of file # End of file

View File

@ -1,4 +1,6 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from io import BytesIO
from PIL import Image from PIL import Image
from PIL import PngImagePlugin from PIL import PngImagePlugin
@ -6,9 +8,6 @@ import zlib
codecs = dir(Image.core) codecs = dir(Image.core)
if "zip_encoder" not in codecs or "zip_decoder" not in codecs:
skip("zip/deflate support not available")
# sample png stream # sample png stream
file = "Images/lena.png" file = "Images/lena.png"
@ -18,6 +17,7 @@ data = open(file, "rb").read()
MAGIC = PngImagePlugin._MAGIC MAGIC = PngImagePlugin._MAGIC
def chunk(cid, *data): def chunk(cid, *data):
file = BytesIO() file = BytesIO()
PngImagePlugin.putchunk(*(file, cid) + data) PngImagePlugin.putchunk(*(file, cid) + data)
@ -32,256 +32,268 @@ IEND = chunk(b"IEND")
HEAD = MAGIC + IHDR HEAD = MAGIC + IHDR
TAIL = IDAT + IEND TAIL = IDAT + IEND
def load(data): def load(data):
return Image.open(BytesIO(data)) return Image.open(BytesIO(data))
def roundtrip(im, **options): def roundtrip(im, **options):
out = BytesIO() out = BytesIO()
im.save(out, "PNG", **options) im.save(out, "PNG", **options)
out.seek(0) out.seek(0)
return Image.open(out) return Image.open(out)
# --------------------------------------------------------------------
def test_sanity(): class TestFilePng(PillowTestCase):
# internal version number def setUp(self):
assert_match(Image.core.zlib_version, "\d+\.\d+\.\d+(\.\d+)?$") if "zip_encoder" not in codecs or "zip_decoder" not in codecs:
self.skipTest("zip/deflate support not available")
file = tempfile("temp.png") def test_sanity(self):
lena("RGB").save(file) # internal version number
self.assertRegexpMatches(
Image.core.zlib_version, "\d+\.\d+\.\d+(\.\d+)?$")
im = Image.open(file) file = self.tempfile("temp.png")
im.load()
assert_equal(im.mode, "RGB")
assert_equal(im.size, (128, 128))
assert_equal(im.format, "PNG")
lena("1").save(file) lena("RGB").save(file)
im = Image.open(file)
lena("L").save(file) im = Image.open(file)
im = Image.open(file) im.load()
self.assertEqual(im.mode, "RGB")
self.assertEqual(im.size, (128, 128))
self.assertEqual(im.format, "PNG")
lena("P").save(file) lena("1").save(file)
im = Image.open(file) im = Image.open(file)
lena("RGB").save(file) lena("L").save(file)
im = Image.open(file) im = Image.open(file)
lena("I").save(file) lena("P").save(file)
im = Image.open(file) im = Image.open(file)
# -------------------------------------------------------------------- lena("RGB").save(file)
im = Image.open(file)
def test_broken(): lena("I").save(file)
# Check reading of totally broken files. In this case, the test im = Image.open(file)
# file was checked into Subversion as a text file.
file = "Tests/images/broken.png" def test_broken(self):
assert_exception(IOError, lambda: Image.open(file)) # Check reading of totally broken files. In this case, the test
# file was checked into Subversion as a text file.
def test_bad_text(): file = "Tests/images/broken.png"
# Make sure PIL can read malformed tEXt chunks (@PIL152) self.assertRaises(IOError, lambda: Image.open(file))
im = load(HEAD + chunk(b'tEXt') + TAIL) def test_bad_text(self):
assert_equal(im.info, {}) # Make sure PIL can read malformed tEXt chunks (@PIL152)
im = load(HEAD + chunk(b'tEXt', b'spam') + TAIL) im = load(HEAD + chunk(b'tEXt') + TAIL)
assert_equal(im.info, {'spam': ''}) self.assertEqual(im.info, {})
im = load(HEAD + chunk(b'tEXt', b'spam\0') + TAIL) im = load(HEAD + chunk(b'tEXt', b'spam') + TAIL)
assert_equal(im.info, {'spam': ''}) self.assertEqual(im.info, {'spam': ''})
im = load(HEAD + chunk(b'tEXt', b'spam\0egg') + TAIL) im = load(HEAD + chunk(b'tEXt', b'spam\0') + TAIL)
assert_equal(im.info, {'spam': 'egg'}) self.assertEqual(im.info, {'spam': ''})
im = load(HEAD + chunk(b'tEXt', b'spam\0egg\0') + TAIL) im = load(HEAD + chunk(b'tEXt', b'spam\0egg') + TAIL)
assert_equal(im.info, {'spam': 'egg\x00'}) self.assertEqual(im.info, {'spam': 'egg'})
def test_bad_ztxt(): im = load(HEAD + chunk(b'tEXt', b'spam\0egg\0') + TAIL)
# Test reading malformed zTXt chunks (python-imaging/Pillow#318) self.assertEqual(im.info, {'spam': 'egg\x00'})
im = load(HEAD + chunk(b'zTXt') + TAIL) def test_bad_ztxt(self):
assert_equal(im.info, {}) # Test reading malformed zTXt chunks (python-pillow/Pillow#318)
im = load(HEAD + chunk(b'zTXt', b'spam') + TAIL) im = load(HEAD + chunk(b'zTXt') + TAIL)
assert_equal(im.info, {'spam': ''}) self.assertEqual(im.info, {})
im = load(HEAD + chunk(b'zTXt', b'spam\0') + TAIL) im = load(HEAD + chunk(b'zTXt', b'spam') + TAIL)
assert_equal(im.info, {'spam': ''}) self.assertEqual(im.info, {'spam': ''})
im = load(HEAD + chunk(b'zTXt', b'spam\0\0') + TAIL) im = load(HEAD + chunk(b'zTXt', b'spam\0') + TAIL)
assert_equal(im.info, {'spam': ''}) self.assertEqual(im.info, {'spam': ''})
im = load(HEAD + chunk(b'zTXt', b'spam\0\0' + zlib.compress(b'egg')[:1]) + TAIL) im = load(HEAD + chunk(b'zTXt', b'spam\0\0') + TAIL)
assert_equal(im.info, {'spam': ''}) self.assertEqual(im.info, {'spam': ''})
im = load(HEAD + chunk(b'zTXt', b'spam\0\0' + zlib.compress(b'egg')) + TAIL) im = load(HEAD + chunk(
assert_equal(im.info, {'spam': 'egg'}) b'zTXt', b'spam\0\0' + zlib.compress(b'egg')[:1]) + TAIL)
self.assertEqual(im.info, {'spam': ''})
def test_interlace(): im = load(
HEAD + chunk(b'zTXt', b'spam\0\0' + zlib.compress(b'egg')) + TAIL)
self.assertEqual(im.info, {'spam': 'egg'})
file = "Tests/images/pil123p.png" def test_interlace(self):
im = Image.open(file)
assert_image(im, "P", (162, 150)) file = "Tests/images/pil123p.png"
assert_true(im.info.get("interlace")) im = Image.open(file)
assert_no_exception(lambda: im.load()) self.assert_image(im, "P", (162, 150))
self.assertTrue(im.info.get("interlace"))
file = "Tests/images/pil123rgba.png" im.load()
im = Image.open(file)
assert_image(im, "RGBA", (162, 150)) file = "Tests/images/pil123rgba.png"
assert_true(im.info.get("interlace")) im = Image.open(file)
assert_no_exception(lambda: im.load()) self.assert_image(im, "RGBA", (162, 150))
self.assertTrue(im.info.get("interlace"))
def test_load_transparent_p(): im.load()
file = "Tests/images/pil123p.png"
im = Image.open(file)
assert_image(im, "P", (162, 150)) def test_load_transparent_p(self):
im = im.convert("RGBA") file = "Tests/images/pil123p.png"
assert_image(im, "RGBA", (162, 150)) im = Image.open(file)
# image has 124 uniqe qlpha values self.assert_image(im, "P", (162, 150))
assert_equal(len(im.split()[3].getcolors()), 124) im = im.convert("RGBA")
self.assert_image(im, "RGBA", (162, 150))
def test_load_transparent_rgb(): # image has 124 uniqe qlpha values
file = "Tests/images/rgb_trns.png" self.assertEqual(len(im.split()[3].getcolors()), 124)
im = Image.open(file)
assert_image(im, "RGB", (64, 64)) def test_load_transparent_rgb(self):
im = im.convert("RGBA") file = "Tests/images/rgb_trns.png"
assert_image(im, "RGBA", (64, 64)) im = Image.open(file)
# image has 876 transparent pixels self.assert_image(im, "RGB", (64, 64))
assert_equal(im.split()[3].getcolors()[0][0], 876) im = im.convert("RGBA")
self.assert_image(im, "RGBA", (64, 64))
def test_save_p_transparent_palette(): # image has 876 transparent pixels
in_file = "Tests/images/pil123p.png" self.assertEqual(im.split()[3].getcolors()[0][0], 876)
im = Image.open(in_file)
file = tempfile("temp.png") def test_save_p_transparent_palette(self):
assert_no_exception(lambda: im.save(file)) in_file = "Tests/images/pil123p.png"
im = Image.open(in_file)
def test_save_p_single_transparency(): file = self.tempfile("temp.png")
in_file = "Tests/images/p_trns_single.png" im.save(file)
im = Image.open(in_file)
file = tempfile("temp.png") def test_save_p_single_transparency(self):
assert_no_exception(lambda: im.save(file)) in_file = "Tests/images/p_trns_single.png"
im = Image.open(in_file)
def test_save_l_transparency(): file = self.tempfile("temp.png")
in_file = "Tests/images/l_trns.png" im.save(file)
im = Image.open(in_file)
file = tempfile("temp.png") def test_save_l_transparency(self):
assert_no_exception(lambda: im.save(file)) in_file = "Tests/images/l_trns.png"
im = Image.open(in_file)
# There are 559 transparent pixels. file = self.tempfile("temp.png")
im = im.convert('RGBA') im.save(file)
assert_equal(im.split()[3].getcolors()[0][0], 559)
def test_save_rgb_single_transparency(): # There are 559 transparent pixels.
in_file = "Tests/images/caption_6_33_22.png" im = im.convert('RGBA')
im = Image.open(in_file) self.assertEqual(im.split()[3].getcolors()[0][0], 559)
file = tempfile("temp.png") def test_save_rgb_single_transparency(self):
assert_no_exception(lambda: im.save(file)) in_file = "Tests/images/caption_6_33_22.png"
im = Image.open(in_file)
def test_load_verify(): file = self.tempfile("temp.png")
# Check open/load/verify exception (@PIL150) im.save(file)
im = Image.open("Images/lena.png") def test_load_verify(self):
assert_no_exception(lambda: im.verify()) # Check open/load/verify exception (@PIL150)
im = Image.open("Images/lena.png") im = Image.open("Images/lena.png")
im.load() im.verify()
assert_exception(RuntimeError, lambda: im.verify())
def test_roundtrip_dpi(): im = Image.open("Images/lena.png")
# Check dpi roundtripping im.load()
self.assertRaises(RuntimeError, lambda: im.verify())
im = Image.open(file) def test_roundtrip_dpi(self):
# Check dpi roundtripping
im = roundtrip(im, dpi=(100, 100)) im = Image.open(file)
assert_equal(im.info["dpi"], (100, 100))
def test_roundtrip_text(): im = roundtrip(im, dpi=(100, 100))
# Check text roundtripping self.assertEqual(im.info["dpi"], (100, 100))
im = Image.open(file) def test_roundtrip_text(self):
# Check text roundtripping
info = PngImagePlugin.PngInfo() im = Image.open(file)
info.add_text("TXT", "VALUE")
info.add_text("ZIP", "VALUE", 1)
im = roundtrip(im, pnginfo=info) info = PngImagePlugin.PngInfo()
assert_equal(im.info, {'TXT': 'VALUE', 'ZIP': 'VALUE'}) info.add_text("TXT", "VALUE")
assert_equal(im.text, {'TXT': 'VALUE', 'ZIP': 'VALUE'}) info.add_text("ZIP", "VALUE", 1)
def test_scary(): im = roundtrip(im, pnginfo=info)
# Check reading of evil PNG file. For information, see: self.assertEqual(im.info, {'TXT': 'VALUE', 'ZIP': 'VALUE'})
# http://scary.beasts.org/security/CESA-2004-001.txt self.assertEqual(im.text, {'TXT': 'VALUE', 'ZIP': 'VALUE'})
# The first byte is removed from pngtest_bad.png
# to avoid classification as malware.
with open("Tests/images/pngtest_bad.png.bin", 'rb') as fd: def test_scary(self):
data = b'\x89' + fd.read() # Check reading of evil PNG file. For information, see:
# http://scary.beasts.org/security/CESA-2004-001.txt
# The first byte is removed from pngtest_bad.png
# to avoid classification as malware.
pngfile = BytesIO(data) with open("Tests/images/pngtest_bad.png.bin", 'rb') as fd:
assert_exception(IOError, lambda: Image.open(pngfile)) data = b'\x89' + fd.read()
def test_trns_rgb(): pngfile = BytesIO(data)
# Check writing and reading of tRNS chunks for RGB images. self.assertRaises(IOError, lambda: Image.open(pngfile))
# Independent file sample provided by Sebastian Spaeth.
file = "Tests/images/caption_6_33_22.png" def test_trns_rgb(self):
im = Image.open(file) # Check writing and reading of tRNS chunks for RGB images.
assert_equal(im.info["transparency"], (248, 248, 248)) # Independent file sample provided by Sebastian Spaeth.
# check saving transparency by default file = "Tests/images/caption_6_33_22.png"
im = roundtrip(im) im = Image.open(file)
assert_equal(im.info["transparency"], (248, 248, 248)) self.assertEqual(im.info["transparency"], (248, 248, 248))
im = roundtrip(im, transparency=(0, 1, 2)) # check saving transparency by default
assert_equal(im.info["transparency"], (0, 1, 2)) im = roundtrip(im)
self.assertEqual(im.info["transparency"], (248, 248, 248))
def test_trns_p(): im = roundtrip(im, transparency=(0, 1, 2))
# Check writing a transparency of 0, issue #528 self.assertEqual(im.info["transparency"], (0, 1, 2))
im = lena('P')
im.info['transparency']=0
f = tempfile("temp.png")
im.save(f)
im2 = Image.open(f) def test_trns_p(self):
assert_true('transparency' in im2.info) # Check writing a transparency of 0, issue #528
im = lena('P')
im.info['transparency'] = 0
assert_image_equal(im2.convert('RGBA'), im.convert('RGBA')) f = self.tempfile("temp.png")
im.save(f)
def test_save_icc_profile_none():
# check saving files with an ICC profile set to None (omit profile)
in_file = "Tests/images/icc_profile_none.png"
im = Image.open(in_file)
assert_equal(im.info['icc_profile'], None)
im = roundtrip(im) im2 = Image.open(f)
assert_false('icc_profile' in im.info) self.assertIn('transparency', im2.info)
def test_roundtrip_icc_profile(): self.assert_image_equal(im2.convert('RGBA'), im.convert('RGBA'))
# check that we can roundtrip the icc profile
im = lena('RGB')
jpeg_image = Image.open('Tests/images/flower2.jpg') def test_save_icc_profile_none(self):
expected_icc = jpeg_image.info['icc_profile'] # check saving files with an ICC profile set to None (omit profile)
in_file = "Tests/images/icc_profile_none.png"
im = Image.open(in_file)
self.assertEqual(im.info['icc_profile'], None)
im.info['icc_profile'] = expected_icc im = roundtrip(im)
im = roundtrip(im) self.assertNotIn('icc_profile', im.info)
assert_equal(im.info['icc_profile'], expected_icc)
def test_roundtrip_icc_profile(self):
# check that we can roundtrip the icc profile
im = lena('RGB')
jpeg_image = Image.open('Tests/images/flower2.jpg')
expected_icc = jpeg_image.info['icc_profile']
im.info['icc_profile'] = expected_icc
im = roundtrip(im)
self.assertEqual(im.info['icc_profile'], expected_icc)
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,4 +1,4 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule
from PIL import Image from PIL import Image
@ -6,31 +6,37 @@ from PIL import Image
file = "Images/lena.ppm" file = "Images/lena.ppm"
data = open(file, "rb").read() data = open(file, "rb").read()
def test_sanity():
im = Image.open(file)
im.load()
assert_equal(im.mode, "RGB")
assert_equal(im.size, (128, 128))
assert_equal(im.format, "PPM")
def test_16bit_pgm(): class TestFilePpm(PillowTestCase):
im = Image.open('Tests/images/16_bit_binary.pgm')
im.load()
assert_equal(im.mode, 'I')
assert_equal(im.size, (20,100))
tgt = Image.open('Tests/images/16_bit_binary_pgm.png') def test_sanity(self):
assert_image_equal(im, tgt) im = Image.open(file)
im.load()
self.assertEqual(im.mode, "RGB")
self.assertEqual(im.size, (128, 128))
self.assertEqual(im.format, "PPM")
def test_16bit_pgm(self):
im = Image.open('Tests/images/16_bit_binary.pgm')
im.load()
self.assertEqual(im.mode, 'I')
self.assertEqual(im.size, (20, 100))
tgt = Image.open('Tests/images/16_bit_binary_pgm.png')
self.assert_image_equal(im, tgt)
def test_16bit_pgm_write(self):
im = Image.open('Tests/images/16_bit_binary.pgm')
im.load()
f = self.tempfile('temp.pgm')
im.save(f, 'PPM')
reloaded = Image.open(f)
self.assert_image_equal(im, reloaded)
def test_16bit_pgm_write(): if __name__ == '__main__':
im = Image.open('Tests/images/16_bit_binary.pgm') unittest.main()
im.load()
f = tempfile('temp.pgm')
assert_no_exception(lambda: im.save(f, 'PPM'))
reloaded = Image.open(f)
assert_image_equal(im, reloaded)
# End of file

View File

@ -1,4 +1,4 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule
from PIL import Image from PIL import Image
@ -6,9 +6,18 @@ from PIL import Image
file = "Images/lena.psd" file = "Images/lena.psd"
data = open(file, "rb").read() data = open(file, "rb").read()
def test_sanity():
im = Image.open(file) class TestImagePsd(PillowTestCase):
im.load()
assert_equal(im.mode, "RGB") def test_sanity(self):
assert_equal(im.size, (128, 128)) im = Image.open(file)
assert_equal(im.format, "PSD") im.load()
self.assertEqual(im.mode, "RGB")
self.assertEqual(im.size, (128, 128))
self.assertEqual(im.format, "PSD")
if __name__ == '__main__':
unittest.main()
# End of file

39
Tests/test_file_spider.py Normal file
View File

@ -0,0 +1,39 @@
from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image
from PIL import SpiderImagePlugin
test_file = "Tests/images/lena.spider"
class TestImageSpider(PillowTestCase):
def test_sanity(self):
im = Image.open(test_file)
im.load()
self.assertEqual(im.mode, "F")
self.assertEqual(im.size, (128, 128))
self.assertEqual(im.format, "SPIDER")
def test_save(self):
# Arrange
temp = self.tempfile('temp.spider')
im = lena()
# Act
im.save(temp, "SPIDER")
# Assert
im2 = Image.open(temp)
self.assertEqual(im2.mode, "F")
self.assertEqual(im2.size, (128, 128))
self.assertEqual(im2.format, "SPIDER")
def test_isSpiderImage(self):
self.assertTrue(SpiderImagePlugin.isSpiderImage(test_file))
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,28 +1,38 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule
from PIL import Image, TarIO from PIL import Image, TarIO
codecs = dir(Image.core) codecs = dir(Image.core)
if "zip_decoder" not in codecs and "jpeg_decoder" not in codecs:
skip("neither jpeg nor zip support not available")
# sample ppm stream # sample ppm stream
tarfile = "Images/lena.tar" tarfile = "Images/lena.tar"
def test_sanity():
if "zip_decoder" in codecs:
tar = TarIO.TarIO(tarfile, 'lena.png')
im = Image.open(tar)
im.load()
assert_equal(im.mode, "RGB")
assert_equal(im.size, (128, 128))
assert_equal(im.format, "PNG")
if "jpeg_decoder" in codecs: class TestFileTar(PillowTestCase):
tar = TarIO.TarIO(tarfile, 'lena.jpg')
im = Image.open(tar)
im.load()
assert_equal(im.mode, "RGB")
assert_equal(im.size, (128, 128))
assert_equal(im.format, "JPEG")
def setUp(self):
if "zip_decoder" not in codecs and "jpeg_decoder" not in codecs:
self.skipTest("neither jpeg nor zip support not available")
def test_sanity(self):
if "zip_decoder" in codecs:
tar = TarIO.TarIO(tarfile, 'lena.png')
im = Image.open(tar)
im.load()
self.assertEqual(im.mode, "RGB")
self.assertEqual(im.size, (128, 128))
self.assertEqual(im.format, "PNG")
if "jpeg_decoder" in codecs:
tar = TarIO.TarIO(tarfile, 'lena.jpg')
im = Image.open(tar)
im.load()
self.assertEqual(im.mode, "RGB")
self.assertEqual(im.size, (128, 128))
self.assertEqual(im.format, "JPEG")
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,141 +1,148 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena, py3
from PIL import Image from PIL import Image
def test_sanity():
file = tempfile("temp.tif") class TestFileTiff(PillowTestCase):
lena("RGB").save(file) def test_sanity(self):
im = Image.open(file) file = self.tempfile("temp.tif")
im.load()
assert_equal(im.mode, "RGB")
assert_equal(im.size, (128, 128))
assert_equal(im.format, "TIFF")
lena("1").save(file) lena("RGB").save(file)
im = Image.open(file)
lena("L").save(file) im = Image.open(file)
im = Image.open(file) im.load()
self.assertEqual(im.mode, "RGB")
self.assertEqual(im.size, (128, 128))
self.assertEqual(im.format, "TIFF")
lena("P").save(file) lena("1").save(file)
im = Image.open(file) im = Image.open(file)
lena("RGB").save(file) lena("L").save(file)
im = Image.open(file) im = Image.open(file)
lena("I").save(file) lena("P").save(file)
im = Image.open(file) im = Image.open(file)
def test_mac_tiff(): lena("RGB").save(file)
# Read RGBa images from Mac OS X [@PIL136] im = Image.open(file)
file = "Tests/images/pil136.tiff" lena("I").save(file)
im = Image.open(file) im = Image.open(file)
assert_equal(im.mode, "RGBA") def test_mac_tiff(self):
assert_equal(im.size, (55, 43)) # Read RGBa images from Mac OS X [@PIL136]
assert_equal(im.tile, [('raw', (0, 0, 55, 43), 8, ('RGBa', 0, 1))])
assert_no_exception(lambda: im.load())
def test_gimp_tiff(): file = "Tests/images/pil136.tiff"
# Read TIFF JPEG images from GIMP [@PIL168] im = Image.open(file)
codecs = dir(Image.core) self.assertEqual(im.mode, "RGBA")
if "jpeg_decoder" not in codecs: self.assertEqual(im.size, (55, 43))
skip("jpeg support not available") self.assertEqual(im.tile, [('raw', (0, 0, 55, 43), 8, ('RGBa', 0, 1))])
im.load()
file = "Tests/images/pil168.tif" def test_gimp_tiff(self):
im = Image.open(file) # Read TIFF JPEG images from GIMP [@PIL168]
assert_equal(im.mode, "RGB") codecs = dir(Image.core)
assert_equal(im.size, (256, 256)) if "jpeg_decoder" not in codecs:
assert_equal(im.tile, [ self.skipTest("jpeg support not available")
('jpeg', (0, 0, 256, 64), 8, ('RGB', '')),
('jpeg', (0, 64, 256, 128), 1215, ('RGB', '')),
('jpeg', (0, 128, 256, 192), 2550, ('RGB', '')),
('jpeg', (0, 192, 256, 256), 3890, ('RGB', '')),
])
assert_no_exception(lambda: im.load())
def test_xyres_tiff(): file = "Tests/images/pil168.tif"
from PIL.TiffImagePlugin import X_RESOLUTION, Y_RESOLUTION im = Image.open(file)
file = "Tests/images/pil168.tif"
im = Image.open(file) self.assertEqual(im.mode, "RGB")
assert isinstance(im.tag.tags[X_RESOLUTION][0], tuple) self.assertEqual(im.size, (256, 256))
assert isinstance(im.tag.tags[Y_RESOLUTION][0], tuple) self.assertEqual(
#Try to read a file where X,Y_RESOLUTION are ints im.tile, [
im.tag.tags[X_RESOLUTION] = (72,) ('jpeg', (0, 0, 256, 64), 8, ('RGB', '')),
im.tag.tags[Y_RESOLUTION] = (72,) ('jpeg', (0, 64, 256, 128), 1215, ('RGB', '')),
im._setup() ('jpeg', (0, 128, 256, 192), 2550, ('RGB', '')),
assert_equal(im.info['dpi'], (72., 72.)) ('jpeg', (0, 192, 256, 256), 3890, ('RGB', '')),
])
im.load()
def test_xyres_tiff(self):
from PIL.TiffImagePlugin import X_RESOLUTION, Y_RESOLUTION
file = "Tests/images/pil168.tif"
im = Image.open(file)
assert isinstance(im.tag.tags[X_RESOLUTION][0], tuple)
assert isinstance(im.tag.tags[Y_RESOLUTION][0], tuple)
# Try to read a file where X,Y_RESOLUTION are ints
im.tag.tags[X_RESOLUTION] = (72,)
im.tag.tags[Y_RESOLUTION] = (72,)
im._setup()
self.assertEqual(im.info['dpi'], (72., 72.))
def test_little_endian(self):
im = Image.open('Tests/images/16bit.cropped.tif')
self.assertEqual(im.getpixel((0, 0)), 480)
self.assertEqual(im.mode, 'I;16')
b = im.tobytes()
# Bytes are in image native order (little endian)
if py3:
self.assertEqual(b[0], ord(b'\xe0'))
self.assertEqual(b[1], ord(b'\x01'))
else:
self.assertEqual(b[0], b'\xe0')
self.assertEqual(b[1], b'\x01')
def test_big_endian(self):
im = Image.open('Tests/images/16bit.MM.cropped.tif')
self.assertEqual(im.getpixel((0, 0)), 480)
self.assertEqual(im.mode, 'I;16B')
b = im.tobytes()
# Bytes are in image native order (big endian)
if py3:
self.assertEqual(b[0], ord(b'\x01'))
self.assertEqual(b[1], ord(b'\xe0'))
else:
self.assertEqual(b[0], b'\x01')
self.assertEqual(b[1], b'\xe0')
def test_12bit_rawmode(self):
""" Are we generating the same interpretation
of the image as Imagemagick is? """
# Image.DEBUG = True
im = Image.open('Tests/images/12bit.cropped.tif')
# to make the target --
# convert 12bit.cropped.tif -depth 16 tmp.tif
# convert tmp.tif -evaluate RightShift 4 12in16bit2.tif
# imagemagick will auto scale so that a 12bit FFF is 16bit FFF0,
# so we need to unshift so that the integer values are the same.
im2 = Image.open('Tests/images/12in16bit.tif')
if Image.DEBUG:
print (im.getpixel((0, 0)))
print (im.getpixel((0, 1)))
print (im.getpixel((0, 2)))
print (im2.getpixel((0, 0)))
print (im2.getpixel((0, 1)))
print (im2.getpixel((0, 2)))
self.assert_image_equal(im, im2)
def test_32bit_float(self):
# Issue 614, specific 32 bit float format
path = 'Tests/images/10ct_32bit_128.tiff'
im = Image.open(path)
im.load()
self.assertEqual(im.getpixel((0, 0)), -0.4526388943195343)
self.assertEqual(
im.getextrema(), (-3.140936851501465, 3.140684127807617))
def test_little_endian(): if __name__ == '__main__':
im = Image.open('Tests/images/16bit.cropped.tif') unittest.main()
assert_equal(im.getpixel((0,0)), 480)
assert_equal(im.mode, 'I;16')
b = im.tobytes() # End of file
# Bytes are in image native order (little endian)
if py3:
assert_equal(b[0], ord(b'\xe0'))
assert_equal(b[1], ord(b'\x01'))
else:
assert_equal(b[0], b'\xe0')
assert_equal(b[1], b'\x01')
def test_big_endian():
im = Image.open('Tests/images/16bit.MM.cropped.tif')
assert_equal(im.getpixel((0,0)), 480)
assert_equal(im.mode, 'I;16B')
b = im.tobytes()
# Bytes are in image native order (big endian)
if py3:
assert_equal(b[0], ord(b'\x01'))
assert_equal(b[1], ord(b'\xe0'))
else:
assert_equal(b[0], b'\x01')
assert_equal(b[1], b'\xe0')
def test_12bit_rawmode():
""" Are we generating the same interpretation of the image as Imagemagick is? """
#Image.DEBUG = True
im = Image.open('Tests/images/12bit.cropped.tif')
# to make the target --
# convert 12bit.cropped.tif -depth 16 tmp.tif
# convert tmp.tif -evaluate RightShift 4 12in16bit2.tif
# imagemagick will auto scale so that a 12bit FFF is 16bit FFF0,
# so we need to unshift so that the integer values are the same.
im2 = Image.open('Tests/images/12in16bit.tif')
if Image.DEBUG:
print (im.getpixel((0,0)))
print (im.getpixel((0,1)))
print (im.getpixel((0,2)))
print (im2.getpixel((0,0)))
print (im2.getpixel((0,1)))
print (im2.getpixel((0,2)))
assert_image_equal(im, im2)
def test_32bit_float():
# Issue 614, specific 32 bit float format
path = 'Tests/images/10ct_32bit_128.tiff'
im = Image.open(path)
im.load()
assert_equal(im.getpixel((0,0)), -0.4526388943195343)
assert_equal(im.getextrema(), (-3.140936851501465, 3.140684127807617))

View File

@ -1,80 +1,93 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image, TiffImagePlugin, TiffTags from PIL import Image, TiffImagePlugin, TiffTags
tag_ids = dict(zip(TiffTags.TAGS.values(), TiffTags.TAGS.keys())) tag_ids = dict(zip(TiffTags.TAGS.values(), TiffTags.TAGS.keys()))
def test_rt_metadata():
""" Test writing arbitray metadata into the tiff image directory
Use case is ImageJ private tags, one numeric, one arbitrary
data. https://github.com/python-imaging/Pillow/issues/291
"""
img = lena()
textdata = "This is some arbitrary metadata for a text field" class TestFileTiffMetadata(PillowTestCase):
info = TiffImagePlugin.ImageFileDirectory()
info[tag_ids['ImageJMetaDataByteCounts']] = len(textdata) def test_rt_metadata(self):
info[tag_ids['ImageJMetaData']] = textdata """ Test writing arbitray metadata into the tiff image directory
Use case is ImageJ private tags, one numeric, one arbitrary
data. https://github.com/python-pillow/Pillow/issues/291
"""
f = tempfile("temp.tif") img = lena()
img.save(f, tiffinfo=info) textdata = "This is some arbitrary metadata for a text field"
info = TiffImagePlugin.ImageFileDirectory()
loaded = Image.open(f)
assert_equal(loaded.tag[50838], (len(textdata),)) info[tag_ids['ImageJMetaDataByteCounts']] = len(textdata)
assert_equal(loaded.tag[50839], textdata) info[tag_ids['ImageJMetaData']] = textdata
def test_read_metadata():
img = Image.open('Tests/images/lena_g4.tif')
known = {'YResolution': ((1207959552, 16777216),),
'PlanarConfiguration': (1,),
'BitsPerSample': (1,),
'ImageLength': (128,),
'Compression': (4,),
'FillOrder': (1,),
'DocumentName': 'lena.g4.tif',
'RowsPerStrip': (128,),
'ResolutionUnit': (1,),
'PhotometricInterpretation': (0,),
'PageNumber': (0, 1),
'XResolution': ((1207959552, 16777216),),
'ImageWidth': (128,),
'Orientation': (1,),
'StripByteCounts': (1796,),
'SamplesPerPixel': (1,),
'StripOffsets': (8,),
'Software': 'ImageMagick 6.5.7-8 2012-08-17 Q16 http://www.imagemagick.org'}
# assert_equal is equivalent, but less helpful in telling what's wrong. f = self.tempfile("temp.tif")
named = img.tag.named()
for tag, value in named.items():
assert_equal(known[tag], value)
for tag, value in known.items(): img.save(f, tiffinfo=info)
assert_equal(value, named[tag])
loaded = Image.open(f)
self.assertEqual(loaded.tag[50838], (len(textdata),))
self.assertEqual(loaded.tag[50839], textdata)
def test_read_metadata(self):
img = Image.open('Tests/images/lena_g4.tif')
known = {'YResolution': ((1207959552, 16777216),),
'PlanarConfiguration': (1,),
'BitsPerSample': (1,),
'ImageLength': (128,),
'Compression': (4,),
'FillOrder': (1,),
'DocumentName': 'lena.g4.tif',
'RowsPerStrip': (128,),
'ResolutionUnit': (1,),
'PhotometricInterpretation': (0,),
'PageNumber': (0, 1),
'XResolution': ((1207959552, 16777216),),
'ImageWidth': (128,),
'Orientation': (1,),
'StripByteCounts': (1796,),
'SamplesPerPixel': (1,),
'StripOffsets': (8,),
'Software': 'ImageMagick 6.5.7-8 2012-08-17 Q16 http://www.imagemagick.org'}
# self.assertEqual is equivalent,
# but less helpful in telling what's wrong.
named = img.tag.named()
for tag, value in named.items():
self.assertEqual(known[tag], value)
for tag, value in known.items():
self.assertEqual(value, named[tag])
def test_write_metadata(self):
""" Test metadata writing through the python code """
img = Image.open('Tests/images/lena.tif')
f = self.tempfile('temp.tiff')
img.save(f, tiffinfo=img.tag)
loaded = Image.open(f)
original = img.tag.named()
reloaded = loaded.tag.named()
ignored = [
'StripByteCounts', 'RowsPerStrip', 'PageNumber', 'StripOffsets']
for tag, value in reloaded.items():
if tag not in ignored:
self.assertEqual(
original[tag], value, "%s didn't roundtrip" % tag)
for tag, value in original.items():
if tag not in ignored:
self.assertEqual(
value, reloaded[tag], "%s didn't roundtrip" % tag)
def test_write_metadata(): if __name__ == '__main__':
""" Test metadata writing through the python code """ unittest.main()
img = Image.open('Tests/images/lena.tif')
f = tempfile('temp.tiff') # End of file
img.save(f, tiffinfo = img.tag)
loaded = Image.open(f)
original = img.tag.named()
reloaded = loaded.tag.named()
ignored = ['StripByteCounts', 'RowsPerStrip', 'PageNumber', 'StripOffsets']
for tag, value in reloaded.items():
if tag not in ignored:
assert_equal(original[tag], value, "%s didn't roundtrip" % tag)
for tag, value in original.items():
if tag not in ignored:
assert_equal(value, reloaded[tag], "%s didn't roundtrip" % tag)

View File

@ -1,68 +1,79 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image from PIL import Image
try: try:
from PIL import _webp from PIL import _webp
except: except:
skip('webp support not installed') # Skip in setUp()
pass
def test_version(): class TestFileWebp(PillowTestCase):
assert_no_exception(lambda: _webp.WebPDecoderVersion())
assert_no_exception(lambda: _webp.WebPDecoderBuggyAlpha())
def test_read_rgb(): def setUp(self):
try:
from PIL import _webp
except:
self.skipTest('WebP support not installed')
file_path = "Images/lena.webp" def test_version(self):
image = Image.open(file_path) _webp.WebPDecoderVersion()
_webp.WebPDecoderBuggyAlpha()
assert_equal(image.mode, "RGB") def test_read_rgb(self):
assert_equal(image.size, (128, 128))
assert_equal(image.format, "WEBP")
assert_no_exception(lambda: image.load())
assert_no_exception(lambda: image.getdata())
# generated with: dwebp -ppm ../../Images/lena.webp -o lena_webp_bits.ppm
target = Image.open('Tests/images/lena_webp_bits.ppm')
assert_image_similar(image, target, 20.0)
def test_write_rgb():
"""
Can we write a RGB mode file to webp without error. Does it have the bits we
expect?
"""
temp_file = tempfile("temp.webp")
lena("RGB").save(temp_file)
image = Image.open(temp_file)
image.load()
assert_equal(image.mode, "RGB")
assert_equal(image.size, (128, 128))
assert_equal(image.format, "WEBP")
assert_no_exception(lambda: image.load())
assert_no_exception(lambda: image.getdata())
# If we're using the exact same version of webp, this test should pass.
# but it doesn't if the webp is generated on Ubuntu and tested on Fedora.
# generated with: dwebp -ppm temp.webp -o lena_webp_write.ppm
#target = Image.open('Tests/images/lena_webp_write.ppm')
#assert_image_equal(image, target)
# This test asserts that the images are similar. If the average pixel difference
# between the two images is less than the epsilon value, then we're going to
# accept that it's a reasonable lossy version of the image. The included lena images
# for webp are showing ~16 on Ubuntu, the jpegs are showing ~18.
target = lena("RGB")
assert_image_similar(image, target, 20.0)
file_path = "Images/lena.webp"
image = Image.open(file_path)
self.assertEqual(image.mode, "RGB")
self.assertEqual(image.size, (128, 128))
self.assertEqual(image.format, "WEBP")
image.load()
image.getdata()
# generated with:
# dwebp -ppm ../../Images/lena.webp -o lena_webp_bits.ppm
target = Image.open('Tests/images/lena_webp_bits.ppm')
self.assert_image_similar(image, target, 20.0)
def test_write_rgb(self):
"""
Can we write a RGB mode file to webp without error.
Does it have the bits we expect?
"""
temp_file = self.tempfile("temp.webp")
lena("RGB").save(temp_file)
image = Image.open(temp_file)
image.load()
self.assertEqual(image.mode, "RGB")
self.assertEqual(image.size, (128, 128))
self.assertEqual(image.format, "WEBP")
image.load()
image.getdata()
# If we're using the exact same version of WebP, this test should pass.
# but it doesn't if the WebP is generated on Ubuntu and tested on
# Fedora.
# generated with: dwebp -ppm temp.webp -o lena_webp_write.ppm
# target = Image.open('Tests/images/lena_webp_write.ppm')
# self.assert_image_equal(image, target)
# This test asserts that the images are similar. If the average pixel
# difference between the two images is less than the epsilon value,
# then we're going to accept that it's a reasonable lossy version of
# the image. The included lena images for WebP are showing ~16 on
# Ubuntu, the jpegs are showing ~18.
target = lena("RGB")
self.assert_image_similar(image, target, 20.0)
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,82 +1,91 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image from PIL import Image
try: try:
from PIL import _webp from PIL import _webp
except: except:
skip('webp support not installed') pass
# Skip in setUp()
if _webp.WebPDecoderBuggyAlpha(): class TestFileWebpAlpha(PillowTestCase):
skip("Buggy early version of webp installed, not testing transparency")
def test_read_rgba(): def setUp(self):
# Generated with `cwebp transparent.png -o transparent.webp` try:
file_path = "Images/transparent.webp" from PIL import _webp
image = Image.open(file_path) except:
self.skipTest('WebP support not installed')
assert_equal(image.mode, "RGBA") if _webp.WebPDecoderBuggyAlpha(self):
assert_equal(image.size, (200, 150)) self.skipTest("Buggy early version of WebP installed, not testing transparency")
assert_equal(image.format, "WEBP")
assert_no_exception(lambda: image.load())
assert_no_exception(lambda: image.getdata())
orig_bytes = image.tobytes() def test_read_rgba(self):
# Generated with `cwebp transparent.png -o transparent.webp`
target = Image.open('Images/transparent.png') file_path = "Images/transparent.webp"
assert_image_similar(image, target, 20.0) image = Image.open(file_path)
def test_write_lossless_rgb():
temp_file = tempfile("temp.webp")
#temp_file = "temp.webp"
pil_image = lena('RGBA')
mask = Image.new("RGBA", (64, 64), (128,128,128,128))
pil_image.paste(mask, (0,0), mask) # add some partially transparent bits.
pil_image.save(temp_file, lossless=True)
image = Image.open(temp_file)
image.load()
assert_equal(image.mode, "RGBA")
assert_equal(image.size, pil_image.size)
assert_equal(image.format, "WEBP")
assert_no_exception(lambda: image.load())
assert_no_exception(lambda: image.getdata())
assert_image_equal(image, pil_image)
def test_write_rgba():
"""
Can we write a RGBA mode file to webp without error. Does it have the bits we
expect?
"""
temp_file = tempfile("temp.webp")
pil_image = Image.new("RGBA", (10, 10), (255, 0, 0, 20))
pil_image.save(temp_file)
if _webp.WebPDecoderBuggyAlpha():
return
image = Image.open(temp_file)
image.load()
assert_equal(image.mode, "RGBA")
assert_equal(image.size, (10, 10))
assert_equal(image.format, "WEBP")
assert_no_exception(image.load)
assert_no_exception(image.getdata)
assert_image_similar(image, pil_image, 1.0)
self.assertEqual(image.mode, "RGBA")
self.assertEqual(image.size, (200, 150))
self.assertEqual(image.format, "WEBP")
image.load()
image.getdata()
image.tobytes()
target = Image.open('Images/transparent.png')
self.assert_image_similar(image, target, 20.0)
def test_write_lossless_rgb(self):
temp_file = self.tempfile("temp.webp")
# temp_file = "temp.webp"
pil_image = lena('RGBA')
mask = Image.new("RGBA", (64, 64), (128, 128, 128, 128))
# Add some partially transparent bits:
pil_image.paste(mask, (0, 0), mask)
pil_image.save(temp_file, lossless=True)
image = Image.open(temp_file)
image.load()
self.assertEqual(image.mode, "RGBA")
self.assertEqual(image.size, pil_image.size)
self.assertEqual(image.format, "WEBP")
image.load()
image.getdata()
self.assert_image_equal(image, pil_image)
def test_write_rgba(self):
"""
Can we write a RGBA mode file to webp without error.
Does it have the bits we expect?
"""
temp_file = self.tempfile("temp.webp")
pil_image = Image.new("RGBA", (10, 10), (255, 0, 0, 20))
pil_image.save(temp_file)
if _webp.WebPDecoderBuggyAlpha(self):
return
image = Image.open(temp_file)
image.load()
self.assertEqual(image.mode, "RGBA")
self.assertEqual(image.size, (10, 10))
self.assertEqual(image.format, "WEBP")
image.load
image.getdata
self.assert_image_similar(image, pil_image, 1.0)
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,33 +1,43 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image from PIL import Image
try: try:
from PIL import _webp from PIL import _webp
except: except:
skip('webp support not installed') pass
# Skip in setUp()
if (_webp.WebPDecoderVersion() < 0x0200): class TestFileWebpLossless(PillowTestCase):
skip('lossless not included')
def test_write_lossless_rgb(): def setUp(self):
temp_file = tempfile("temp.webp") try:
from PIL import _webp
except:
self.skipTest('WebP support not installed')
lena("RGB").save(temp_file, lossless=True) if (_webp.WebPDecoderVersion() < 0x0200):
self.skipTest('lossless not included')
image = Image.open(temp_file) def test_write_lossless_rgb(self):
image.load() temp_file = self.tempfile("temp.webp")
assert_equal(image.mode, "RGB") lena("RGB").save(temp_file, lossless=True)
assert_equal(image.size, (128, 128))
assert_equal(image.format, "WEBP") image = Image.open(temp_file)
assert_no_exception(lambda: image.load()) image.load()
assert_no_exception(lambda: image.getdata())
self.assertEqual(image.mode, "RGB")
self.assertEqual(image.size, (128, 128))
assert_image_equal(image, lena("RGB")) self.assertEqual(image.format, "WEBP")
image.load()
image.getdata()
self.assert_image_equal(image, lena("RGB"))
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,101 +1,112 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule
from PIL import Image from PIL import Image
try:
from PIL import _webp class TestFileWebpMetadata(PillowTestCase):
if not _webp.HAVE_WEBPMUX:
skip('webpmux support not installed') def setUp(self):
except: try:
skip('webp support not installed') from PIL import _webp
if not _webp.HAVE_WEBPMUX:
self.skipTest('webpmux support not installed')
except:
self.skipTest('WebP support not installed')
def test_read_exif_metadata(self):
file_path = "Images/flower.webp"
image = Image.open(file_path)
self.assertEqual(image.format, "WEBP")
exif_data = image.info.get("exif", None)
self.assertTrue(exif_data)
exif = image._getexif()
# camera make
self.assertEqual(exif[271], "Canon")
jpeg_image = Image.open('Tests/images/flower.jpg')
expected_exif = jpeg_image.info['exif']
self.assertEqual(exif_data, expected_exif)
def test_write_exif_metadata(self):
from io import BytesIO
file_path = "Tests/images/flower.jpg"
image = Image.open(file_path)
expected_exif = image.info['exif']
buffer = BytesIO()
image.save(buffer, "webp", exif=expected_exif)
buffer.seek(0)
webp_image = Image.open(buffer)
webp_exif = webp_image.info.get('exif', None)
self.assertTrue(webp_exif)
if webp_exif:
self.assertEqual(
webp_exif, expected_exif, "WebP EXIF didn't match")
def test_read_icc_profile(self):
file_path = "Images/flower2.webp"
image = Image.open(file_path)
self.assertEqual(image.format, "WEBP")
self.assertTrue(image.info.get("icc_profile", None))
icc = image.info['icc_profile']
jpeg_image = Image.open('Tests/images/flower2.jpg')
expected_icc = jpeg_image.info['icc_profile']
self.assertEqual(icc, expected_icc)
def test_write_icc_metadata(self):
from io import BytesIO
file_path = "Tests/images/flower2.jpg"
image = Image.open(file_path)
expected_icc_profile = image.info['icc_profile']
buffer = BytesIO()
image.save(buffer, "webp", icc_profile=expected_icc_profile)
buffer.seek(0)
webp_image = Image.open(buffer)
webp_icc_profile = webp_image.info.get('icc_profile', None)
self.assertTrue(webp_icc_profile)
if webp_icc_profile:
self.assertEqual(
webp_icc_profile, expected_icc_profile,
"Webp ICC didn't match")
def test_read_no_exif(self):
from io import BytesIO
file_path = "Tests/images/flower.jpg"
image = Image.open(file_path)
image.info['exif']
buffer = BytesIO()
image.save(buffer, "webp")
buffer.seek(0)
webp_image = Image.open(buffer)
self.assertFalse(webp_image._getexif())
if __name__ == '__main__':
unittest.main()
def test_read_exif_metadata(): # End of file
file_path = "Images/flower.webp"
image = Image.open(file_path)
assert_equal(image.format, "WEBP")
exif_data = image.info.get("exif", None)
assert_true(exif_data)
exif = image._getexif()
#camera make
assert_equal(exif[271], "Canon")
jpeg_image = Image.open('Tests/images/flower.jpg')
expected_exif = jpeg_image.info['exif']
assert_equal(exif_data, expected_exif)
def test_write_exif_metadata():
file_path = "Tests/images/flower.jpg"
image = Image.open(file_path)
expected_exif = image.info['exif']
buffer = BytesIO()
image.save(buffer, "webp", exif=expected_exif)
buffer.seek(0)
webp_image = Image.open(buffer)
webp_exif = webp_image.info.get('exif', None)
assert_true(webp_exif)
if webp_exif:
assert_equal(webp_exif, expected_exif, "Webp Exif didn't match")
def test_read_icc_profile():
file_path = "Images/flower2.webp"
image = Image.open(file_path)
assert_equal(image.format, "WEBP")
assert_true(image.info.get("icc_profile", None))
icc = image.info['icc_profile']
jpeg_image = Image.open('Tests/images/flower2.jpg')
expected_icc = jpeg_image.info['icc_profile']
assert_equal(icc, expected_icc)
def test_write_icc_metadata():
file_path = "Tests/images/flower2.jpg"
image = Image.open(file_path)
expected_icc_profile = image.info['icc_profile']
buffer = BytesIO()
image.save(buffer, "webp", icc_profile=expected_icc_profile)
buffer.seek(0)
webp_image = Image.open(buffer)
webp_icc_profile = webp_image.info.get('icc_profile', None)
assert_true(webp_icc_profile)
if webp_icc_profile:
assert_equal(webp_icc_profile, expected_icc_profile, "Webp ICC didn't match")
def test_read_no_exif():
file_path = "Tests/images/flower.jpg"
image = Image.open(file_path)
expected_exif = image.info['exif']
buffer = BytesIO()
image.save(buffer, "webp")
buffer.seek(0)
webp_image = Image.open(buffer)
assert_false(webp_image._getexif())

View File

@ -1,4 +1,4 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule
from PIL import Image from PIL import Image
@ -25,10 +25,20 @@ static char basic_bits[] = {
}; };
""" """
def test_pil151():
im = Image.open(BytesIO(PIL151)) class TestFileXbm(PillowTestCase):
assert_no_exception(lambda: im.load()) def test_pil151(self):
assert_equal(im.mode, '1') from io import BytesIO
assert_equal(im.size, (32, 32))
im = Image.open(BytesIO(PIL151))
im.load()
self.assertEqual(im.mode, '1')
self.assertEqual(im.size, (32, 32))
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,4 +1,4 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule
from PIL import Image from PIL import Image
@ -6,9 +6,18 @@ from PIL import Image
file = "Images/lena.xpm" file = "Images/lena.xpm"
data = open(file, "rb").read() data = open(file, "rb").read()
def test_sanity():
im = Image.open(file) class TestFileXpm(PillowTestCase):
im.load()
assert_equal(im.mode, "P") def test_sanity(self):
assert_equal(im.size, (128, 128)) im = Image.open(file)
assert_equal(im.format, "XPM") im.load()
self.assertEqual(im.mode, "P")
self.assertEqual(im.size, (128, 128))
self.assertEqual(im.format, "XPM")
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,13 +1,22 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule
from PIL import Image, FontFile, BdfFontFile from PIL import FontFile, BdfFontFile
filename = "Images/courB08.bdf" filename = "Images/courB08.bdf"
def test_sanity():
file = open(filename, "rb") class TestFontBdf(PillowTestCase):
font = BdfFontFile.BdfFontFile(file)
assert_true(isinstance(font, FontFile.FontFile)) def test_sanity(self):
assert_equal(len([_f for _f in font.glyph if _f]), 190)
file = open(filename, "rb")
font = BdfFontFile.BdfFontFile(file)
self.assertIsInstance(font, FontFile.FontFile)
self.assertEqual(len([_f for _f in font.glyph if _f]), 190)
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,49 +1,63 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule
from PIL import Image, FontFile, PcfFontFile from PIL import Image, FontFile, PcfFontFile
from PIL import ImageFont, ImageDraw from PIL import ImageFont, ImageDraw
codecs = dir(Image.core) codecs = dir(Image.core)
if "zip_encoder" not in codecs or "zip_decoder" not in codecs:
skip("zlib support not available")
fontname = "Tests/fonts/helvO18.pcf" fontname = "Tests/fonts/helvO18.pcf"
tempname = tempfile("temp.pil", "temp.pbm")
message = "hello, world" message = "hello, world"
def test_sanity():
file = open(fontname, "rb") class TestFontPcf(PillowTestCase):
font = PcfFontFile.PcfFontFile(file)
assert_true(isinstance(font, FontFile.FontFile))
assert_equal(len([_f for _f in font.glyph if _f]), 192)
font.save(tempname) def setUp(self):
if "zip_encoder" not in codecs or "zip_decoder" not in codecs:
self.skipTest("zlib support not available")
def xtest_draw(): def save_font(self):
file = open(fontname, "rb")
font = PcfFontFile.PcfFontFile(file)
self.assertIsInstance(font, FontFile.FontFile)
self.assertEqual(len([_f for _f in font.glyph if _f]), 192)
font = ImageFont.load(tempname) tempname = self.tempfile("temp.pil", "temp.pbm")
image = Image.new("L", font.getsize(message), "white") font.save(tempname)
draw = ImageDraw.Draw(image) return tempname
draw.text((0, 0), message, font=font)
# assert_signature(image, "7216c60f988dea43a46bb68321e3c1b03ec62aee")
def _test_high_characters(message): def test_sanity(self):
self.save_font()
font = ImageFont.load(tempname) def xtest_draw(self):
image = Image.new("L", font.getsize(message), "white")
draw = ImageDraw.Draw(image)
draw.text((0, 0), message, font=font)
compare = Image.open('Tests/images/high_ascii_chars.png') tempname = self.save_font()
assert_image_equal(image, compare) font = ImageFont.load(tempname)
image = Image.new("L", font.getsize(message), "white")
draw = ImageDraw.Draw(image)
draw.text((0, 0), message, font=font)
# assert_signature(image, "7216c60f988dea43a46bb68321e3c1b03ec62aee")
def test_high_characters(): def _test_high_characters(self, message):
message = "".join([chr(i+1) for i in range(140,232)])
_test_high_characters(message)
# accept bytes instances in Py3.
if bytes is not str:
_test_high_characters(message.encode('latin1'))
tempname = self.save_font()
font = ImageFont.load(tempname)
image = Image.new("L", font.getsize(message), "white")
draw = ImageDraw.Draw(image)
draw.text((0, 0), message, font=font)
compare = Image.open('Tests/images/high_ascii_chars.png')
self.assert_image_equal(image, compare)
def test_high_characters(self):
message = "".join([chr(i+1) for i in range(140, 232)])
self._test_high_characters(message)
# accept bytes instances in Py3.
if bytes is not str:
self._test_high_characters(message.encode('latin1'))
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,41 +1,48 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule
from PIL import Image from PIL import Image
def test_white():
i = Image.open('Tests/images/lab.tif')
bits = i.load() class TestFormatLab(PillowTestCase):
assert_equal(i.mode, 'LAB')
assert_equal(i.getbands(), ('L','A', 'B')) def test_white(self):
i = Image.open('Tests/images/lab.tif')
k = i.getpixel((0,0)) i.load()
assert_equal(k, (255,128,128))
L = i.getdata(0) self.assertEqual(i.mode, 'LAB')
a = i.getdata(1)
b = i.getdata(2)
assert_equal(list(L), [255]*100) self.assertEqual(i.getbands(), ('L', 'A', 'B'))
assert_equal(list(a), [128]*100)
assert_equal(list(b), [128]*100)
def test_green(): k = i.getpixel((0, 0))
# l= 50 (/100), a = -100 (-128 .. 128) b=0 in PS self.assertEqual(k, (255, 128, 128))
# == RGB: 0, 152, 117
i = Image.open('Tests/images/lab-green.tif')
k = i.getpixel((0,0)) L = i.getdata(0)
assert_equal(k, (128,28,128)) a = i.getdata(1)
b = i.getdata(2)
self.assertEqual(list(L), [255]*100)
self.assertEqual(list(a), [128]*100)
self.assertEqual(list(b), [128]*100)
def test_green(self):
# l= 50 (/100), a = -100 (-128 .. 128) b=0 in PS
# == RGB: 0, 152, 117
i = Image.open('Tests/images/lab-green.tif')
k = i.getpixel((0, 0))
self.assertEqual(k, (128, 28, 128))
def test_red(self):
# l= 50 (/100), a = 100 (-128 .. 128) b=0 in PS
# == RGB: 255, 0, 124
i = Image.open('Tests/images/lab-red.tif')
k = i.getpixel((0, 0))
self.assertEqual(k, (128, 228, 128))
def test_red(): if __name__ == '__main__':
# l= 50 (/100), a = 100 (-128 .. 128) b=0 in PS unittest.main()
# == RGB: 255, 0, 124
i = Image.open('Tests/images/lab-red.tif')
k = i.getpixel((0,0)) # End of file
assert_equal(k, (128,228,128))

View File

@ -1,39 +1,51 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule
from PIL import Image from PIL import Image
def test_sanity():
im = Image.new("L", (100, 100)) class TestImage(PillowTestCase):
assert_equal(repr(im)[:45], "<PIL.Image.Image image mode=L size=100x100 at")
assert_equal(im.mode, "L")
assert_equal(im.size, (100, 100))
im = Image.new("RGB", (100, 100)) def test_sanity(self):
assert_equal(repr(im)[:45], "<PIL.Image.Image image mode=RGB size=100x100 ")
assert_equal(im.mode, "RGB")
assert_equal(im.size, (100, 100))
im1 = Image.new("L", (100, 100), None) im = Image.new("L", (100, 100))
im2 = Image.new("L", (100, 100), 0) self.assertEqual(
im3 = Image.new("L", (100, 100), "black") repr(im)[:45], "<PIL.Image.Image image mode=L size=100x100 at")
self.assertEqual(im.mode, "L")
self.assertEqual(im.size, (100, 100))
assert_equal(im2.getcolors(), [(10000, 0)]) im = Image.new("RGB", (100, 100))
assert_equal(im3.getcolors(), [(10000, 0)]) self.assertEqual(
repr(im)[:45], "<PIL.Image.Image image mode=RGB size=100x100 ")
self.assertEqual(im.mode, "RGB")
self.assertEqual(im.size, (100, 100))
assert_exception(ValueError, lambda: Image.new("X", (100, 100))) Image.new("L", (100, 100), None)
# assert_exception(MemoryError, lambda: Image.new("L", (1000000, 1000000))) im2 = Image.new("L", (100, 100), 0)
im3 = Image.new("L", (100, 100), "black")
def test_internals(): self.assertEqual(im2.getcolors(), [(10000, 0)])
self.assertEqual(im3.getcolors(), [(10000, 0)])
im = Image.new("L", (100, 100)) self.assertRaises(ValueError, lambda: Image.new("X", (100, 100)))
im.readonly = 1 # self.assertRaises(
im._copy() # MemoryError, lambda: Image.new("L", (1000000, 1000000)))
assert_false(im.readonly)
im.readonly = 1 def test_internals(self):
im.paste(0, (0, 0, 100, 100))
assert_false(im.readonly)
file = tempfile("temp.ppm") im = Image.new("L", (100, 100))
im._dump(file) im.readonly = 1
im._copy()
self.assertFalse(im.readonly)
im.readonly = 1
im.paste(0, (0, 0, 100, 100))
self.assertFalse(im.readonly)
file = self.tempfile("temp.ppm")
im._dump(file)
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,33 +1,46 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image from PIL import Image
im = lena().resize((128, 100)) im = lena().resize((128, 100))
def test_toarray():
def test(mode):
ai = im.convert(mode).__array_interface__
return ai["shape"], ai["typestr"], len(ai["data"])
# assert_equal(test("1"), ((100, 128), '|b1', 1600))
assert_equal(test("L"), ((100, 128), '|u1', 12800))
assert_equal(test("I"), ((100, 128), Image._ENDIAN + 'i4', 51200)) # FIXME: wrong?
assert_equal(test("F"), ((100, 128), Image._ENDIAN + 'f4', 51200)) # FIXME: wrong?
assert_equal(test("RGB"), ((100, 128, 3), '|u1', 38400))
assert_equal(test("RGBA"), ((100, 128, 4), '|u1', 51200))
assert_equal(test("RGBX"), ((100, 128, 4), '|u1', 51200))
def test_fromarray(): class TestImageCrop(PillowTestCase):
def test(mode):
i = im.convert(mode) def test_toarray(self):
a = i.__array_interface__ def test(mode):
a["strides"] = 1 # pretend it's non-contigous ai = im.convert(mode).__array_interface__
i.__array_interface__ = a # patch in new version of attribute return ai["shape"], ai["typestr"], len(ai["data"])
out = Image.fromarray(i) # self.assertEqual(test("1"), ((100, 128), '|b1', 1600))
return out.mode, out.size, list(i.getdata()) == list(out.getdata()) self.assertEqual(test("L"), ((100, 128), '|u1', 12800))
# assert_equal(test("1"), ("1", (128, 100), True))
assert_equal(test("L"), ("L", (128, 100), True)) # FIXME: wrong?
assert_equal(test("I"), ("I", (128, 100), True)) self.assertEqual(test("I"), ((100, 128), Image._ENDIAN + 'i4', 51200))
assert_equal(test("F"), ("F", (128, 100), True)) # FIXME: wrong?
assert_equal(test("RGB"), ("RGB", (128, 100), True)) self.assertEqual(test("F"), ((100, 128), Image._ENDIAN + 'f4', 51200))
assert_equal(test("RGBA"), ("RGBA", (128, 100), True))
assert_equal(test("RGBX"), ("RGBA", (128, 100), True)) self.assertEqual(test("RGB"), ((100, 128, 3), '|u1', 38400))
self.assertEqual(test("RGBA"), ((100, 128, 4), '|u1', 51200))
self.assertEqual(test("RGBX"), ((100, 128, 4), '|u1', 51200))
def test_fromarray(self):
def test(mode):
i = im.convert(mode)
a = i.__array_interface__
a["strides"] = 1 # pretend it's non-contigous
i.__array_interface__ = a # patch in new version of attribute
out = Image.fromarray(i)
return out.mode, out.size, list(i.getdata()) == list(out.getdata())
# self.assertEqual(test("1"), ("1", (128, 100), True))
self.assertEqual(test("L"), ("L", (128, 100), True))
self.assertEqual(test("I"), ("I", (128, 100), True))
self.assertEqual(test("F"), ("F", (128, 100), True))
self.assertEqual(test("RGB"), ("RGB", (128, 100), True))
self.assertEqual(test("RGBA"), ("RGBA", (128, 100), True))
self.assertEqual(test("RGBX"), ("RGBA", (128, 100), True))
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,130 +1,130 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image from PIL import Image
def test_sanity(): class TestImageConvert(PillowTestCase):
def convert(im, mode): def test_sanity(self):
out = im.convert(mode)
assert_equal(out.mode, mode)
assert_equal(out.size, im.size)
modes = "1", "L", "I", "F", "RGB", "RGBA", "RGBX", "CMYK", "YCbCr" def convert(im, mode):
out = im.convert(mode)
self.assertEqual(out.mode, mode)
self.assertEqual(out.size, im.size)
modes = "1", "L", "I", "F", "RGB", "RGBA", "RGBX", "CMYK", "YCbCr"
for mode in modes:
im = lena(mode)
for mode in modes: for mode in modes:
yield_test(convert, im, mode) im = lena(mode)
for mode in modes:
convert(im, mode)
def test_default(self):
im = lena("P")
self.assert_image(im, "P", im.size)
im = im.convert()
self.assert_image(im, "RGB", im.size)
im = im.convert()
self.assert_image(im, "RGB", im.size)
# ref https://github.com/python-pillow/Pillow/issues/274
def _test_float_conversion(self, im):
orig = im.getpixel((5, 5))
converted = im.convert('F').getpixel((5, 5))
self.assertEqual(orig, converted)
def test_8bit(self):
im = Image.open('Images/lena.jpg')
self._test_float_conversion(im.convert('L'))
def test_16bit(self):
im = Image.open('Tests/images/16bit.cropped.tif')
self._test_float_conversion(im)
def test_16bit_workaround(self):
im = Image.open('Tests/images/16bit.cropped.tif')
self._test_float_conversion(im.convert('I'))
def test_rgba_p(self):
im = lena('RGBA')
im.putalpha(lena('L'))
converted = im.convert('P')
comparable = converted.convert('RGBA')
self.assert_image_similar(im, comparable, 20)
def test_trns_p(self):
im = lena('P')
im.info['transparency'] = 0
f = self.tempfile('temp.png')
l = im.convert('L')
self.assertEqual(l.info['transparency'], 0) # undone
l.save(f)
rgb = im.convert('RGB')
self.assertEqual(rgb.info['transparency'], (0, 0, 0)) # undone
rgb.save(f)
# ref https://github.com/python-pillow/Pillow/issues/664
def test_trns_p_rgba(self):
# Arrange
im = lena('P')
im.info['transparency'] = 128
# Act
rgba = im.convert('RGBA')
# Assert
self.assertNotIn('transparency', rgba.info)
def test_trns_l(self):
im = lena('L')
im.info['transparency'] = 128
f = self.tempfile('temp.png')
rgb = im.convert('RGB')
self.assertEqual(rgb.info['transparency'], (128, 128, 128)) # undone
rgb.save(f)
p = im.convert('P')
self.assertIn('transparency', p.info)
p.save(f)
p = self.assert_warning(
UserWarning,
lambda: im.convert('P', palette=Image.ADAPTIVE))
self.assertNotIn('transparency', p.info)
p.save(f)
def test_trns_RGB(self):
im = lena('RGB')
im.info['transparency'] = im.getpixel((0, 0))
f = self.tempfile('temp.png')
l = im.convert('L')
self.assertEqual(l.info['transparency'], l.getpixel((0, 0))) # undone
l.save(f)
p = im.convert('P')
self.assertIn('transparency', p.info)
p.save(f)
p = self.assert_warning(
UserWarning,
lambda: im.convert('P', palette=Image.ADAPTIVE))
self.assertNotIn('transparency', p.info)
p.save(f)
def test_default(): if __name__ == '__main__':
unittest.main()
im = lena("P") # End of file
assert_image(im, "P", im.size)
im = im.convert()
assert_image(im, "RGB", im.size)
im = im.convert()
assert_image(im, "RGB", im.size)
# ref https://github.com/python-imaging/Pillow/issues/274
def _test_float_conversion(im):
orig = im.getpixel((5, 5))
converted = im.convert('F').getpixel((5, 5))
assert_equal(orig, converted)
def test_8bit():
im = Image.open('Images/lena.jpg')
_test_float_conversion(im.convert('L'))
def test_16bit():
im = Image.open('Tests/images/16bit.cropped.tif')
_test_float_conversion(im)
def test_16bit_workaround():
im = Image.open('Tests/images/16bit.cropped.tif')
_test_float_conversion(im.convert('I'))
def test_rgba_p():
im = lena('RGBA')
im.putalpha(lena('L'))
converted = im.convert('P')
comparable = converted.convert('RGBA')
assert_image_similar(im, comparable, 20)
def test_trns_p():
im = lena('P')
im.info['transparency'] = 0
f = tempfile('temp.png')
l = im.convert('L')
assert_equal(l.info['transparency'], 0) # undone
assert_no_exception(lambda: l.save(f))
rgb = im.convert('RGB')
assert_equal(rgb.info['transparency'], (0, 0, 0)) # undone
assert_no_exception(lambda: rgb.save(f))
# ref https://github.com/python-imaging/Pillow/issues/664
def test_trns_p_rgba():
# Arrange
im = lena('P')
im.info['transparency'] = 128
# Act
rgba = im.convert('RGBA')
# Assert
assert_false('transparency' in rgba.info)
def test_trns_l():
im = lena('L')
im.info['transparency'] = 128
f = tempfile('temp.png')
rgb = im.convert('RGB')
assert_equal(rgb.info['transparency'], (128, 128, 128)) # undone
assert_no_exception(lambda: rgb.save(f))
p = im.convert('P')
assert_true('transparency' in p.info)
assert_no_exception(lambda: p.save(f))
p = assert_warning(UserWarning,
lambda: im.convert('P', palette=Image.ADAPTIVE))
assert_false('transparency' in p.info)
assert_no_exception(lambda: p.save(f))
def test_trns_RGB():
im = lena('RGB')
im.info['transparency'] = im.getpixel((0, 0))
f = tempfile('temp.png')
l = im.convert('L')
assert_equal(l.info['transparency'], l.getpixel((0, 0))) # undone
assert_no_exception(lambda: l.save(f))
p = im.convert('P')
assert_true('transparency' in p.info)
assert_no_exception(lambda: p.save(f))
p = assert_warning(UserWarning,
lambda: im.convert('P', palette=Image.ADAPTIVE))
assert_false('transparency' in p.info)
assert_no_exception(lambda: p.save(f))

View File

@ -1,12 +1,20 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image from PIL import Image
def test_copy():
def copy(mode): class TestImageCopy(PillowTestCase):
im = lena(mode)
out = im.copy() def test_copy(self):
assert_equal(out.mode, mode) def copy(mode):
assert_equal(out.size, im.size) im = lena(mode)
for mode in "1", "P", "L", "RGB", "I", "F": out = im.copy()
yield_test(copy, mode) self.assertEqual(out.mode, mode)
self.assertEqual(out.size, im.size)
for mode in "1", "P", "L", "RGB", "I", "F":
copy(mode)
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,52 +1,59 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image from PIL import Image
def test_crop():
def crop(mode):
out = lena(mode).crop((50, 50, 100, 100))
assert_equal(out.mode, mode)
assert_equal(out.size, (50, 50))
for mode in "1", "P", "L", "RGB", "I", "F":
yield_test(crop, mode)
def test_wide_crop(): class TestImageCrop(PillowTestCase):
def crop(*bbox): def test_crop(self):
i = im.crop(bbox) def crop(mode):
h = i.histogram() out = lena(mode).crop((50, 50, 100, 100))
while h and not h[-1]: self.assertEqual(out.mode, mode)
del h[-1] self.assertEqual(out.size, (50, 50))
return tuple(h) for mode in "1", "P", "L", "RGB", "I", "F":
crop(mode)
im = Image.new("L", (100, 100), 1) def test_wide_crop(self):
assert_equal(crop(0, 0, 100, 100), (0, 10000)) def crop(*bbox):
assert_equal(crop(25, 25, 75, 75), (0, 2500)) i = im.crop(bbox)
h = i.histogram()
while h and not h[-1]:
del h[-1]
return tuple(h)
# sides im = Image.new("L", (100, 100), 1)
assert_equal(crop(-25, 0, 25, 50), (1250, 1250))
assert_equal(crop(0, -25, 50, 25), (1250, 1250))
assert_equal(crop(75, 0, 125, 50), (1250, 1250))
assert_equal(crop(0, 75, 50, 125), (1250, 1250))
assert_equal(crop(-25, 25, 125, 75), (2500, 5000)) self.assertEqual(crop(0, 0, 100, 100), (0, 10000))
assert_equal(crop(25, -25, 75, 125), (2500, 5000)) self.assertEqual(crop(25, 25, 75, 75), (0, 2500))
# corners # sides
assert_equal(crop(-25, -25, 25, 25), (1875, 625)) self.assertEqual(crop(-25, 0, 25, 50), (1250, 1250))
assert_equal(crop(75, -25, 125, 25), (1875, 625)) self.assertEqual(crop(0, -25, 50, 25), (1250, 1250))
assert_equal(crop(75, 75, 125, 125), (1875, 625)) self.assertEqual(crop(75, 0, 125, 50), (1250, 1250))
assert_equal(crop(-25, 75, 25, 125), (1875, 625)) self.assertEqual(crop(0, 75, 50, 125), (1250, 1250))
# -------------------------------------------------------------------- self.assertEqual(crop(-25, 25, 125, 75), (2500, 5000))
self.assertEqual(crop(25, -25, 75, 125), (2500, 5000))
def test_negative_crop(): # corners
# Check negative crop size (@PIL171) self.assertEqual(crop(-25, -25, 25, 25), (1875, 625))
self.assertEqual(crop(75, -25, 125, 25), (1875, 625))
self.assertEqual(crop(75, 75, 125, 125), (1875, 625))
self.assertEqual(crop(-25, 75, 25, 125), (1875, 625))
im = Image.new("L", (512, 512)) def test_negative_crop(self):
im = im.crop((400, 400, 200, 200)) # Check negative crop size (@PIL171)
assert_equal(im.size, (0, 0)) im = Image.new("L", (512, 512))
assert_equal(len(im.getdata()), 0) im = im.crop((400, 400, 200, 200))
assert_exception(IndexError, lambda: im.getdata()[0])
self.assertEqual(im.size, (0, 0))
self.assertEqual(len(im.getdata()), 0)
self.assertRaises(IndexError, lambda: im.getdata()[0])
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,30 +1,39 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, fromstring, tostring
from PIL import Image from PIL import Image
codecs = dir(Image.core) codecs = dir(Image.core)
if "jpeg_encoder" not in codecs or "jpeg_decoder" not in codecs:
skip("jpeg support not available")
filename = "Images/lena.jpg" filename = "Images/lena.jpg"
data = tostring(Image.open(filename).resize((512, 512)), "JPEG") data = tostring(Image.open(filename).resize((512, 512)), "JPEG")
def draft(mode, size): def draft(mode, size):
im = fromstring(data) im = fromstring(data)
im.draft(mode, size) im.draft(mode, size)
return im return im
def test_size():
assert_equal(draft("RGB", (512, 512)).size, (512, 512))
assert_equal(draft("RGB", (256, 256)).size, (256, 256))
assert_equal(draft("RGB", (128, 128)).size, (128, 128))
assert_equal(draft("RGB", (64, 64)).size, (64, 64))
assert_equal(draft("RGB", (32, 32)).size, (64, 64))
def test_mode(): class TestImageDraft(PillowTestCase):
assert_equal(draft("1", (512, 512)).mode, "RGB")
assert_equal(draft("L", (512, 512)).mode, "L") def setUp(self):
assert_equal(draft("RGB", (512, 512)).mode, "RGB") if "jpeg_encoder" not in codecs or "jpeg_decoder" not in codecs:
assert_equal(draft("YCbCr", (512, 512)).mode, "YCbCr") self.skipTest("jpeg support not available")
def test_size(self):
self.assertEqual(draft("RGB", (512, 512)).size, (512, 512))
self.assertEqual(draft("RGB", (256, 256)).size, (256, 256))
self.assertEqual(draft("RGB", (128, 128)).size, (128, 128))
self.assertEqual(draft("RGB", (64, 64)).size, (64, 64))
self.assertEqual(draft("RGB", (32, 32)).size, (64, 64))
def test_mode(self):
self.assertEqual(draft("1", (512, 512)).mode, "RGB")
self.assertEqual(draft("L", (512, 512)).mode, "L")
self.assertEqual(draft("RGB", (512, 512)).mode, "RGB")
self.assertEqual(draft("YCbCr", (512, 512)).mode, "YCbCr")
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,82 +1,91 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image from PIL import Image
from PIL import ImageFilter from PIL import ImageFilter
def test_sanity():
def filter(filter): class TestImageFilter(PillowTestCase):
im = lena("L")
out = im.filter(filter)
assert_equal(out.mode, im.mode)
assert_equal(out.size, im.size)
filter(ImageFilter.BLUR) def test_sanity(self):
filter(ImageFilter.CONTOUR)
filter(ImageFilter.DETAIL)
filter(ImageFilter.EDGE_ENHANCE)
filter(ImageFilter.EDGE_ENHANCE_MORE)
filter(ImageFilter.EMBOSS)
filter(ImageFilter.FIND_EDGES)
filter(ImageFilter.SMOOTH)
filter(ImageFilter.SMOOTH_MORE)
filter(ImageFilter.SHARPEN)
filter(ImageFilter.MaxFilter)
filter(ImageFilter.MedianFilter)
filter(ImageFilter.MinFilter)
filter(ImageFilter.ModeFilter)
filter(ImageFilter.Kernel((3, 3), list(range(9))))
assert_exception(TypeError, lambda: filter("hello")) def filter(filter):
im = lena("L")
out = im.filter(filter)
self.assertEqual(out.mode, im.mode)
self.assertEqual(out.size, im.size)
def test_crash(): filter(ImageFilter.BLUR)
filter(ImageFilter.CONTOUR)
filter(ImageFilter.DETAIL)
filter(ImageFilter.EDGE_ENHANCE)
filter(ImageFilter.EDGE_ENHANCE_MORE)
filter(ImageFilter.EMBOSS)
filter(ImageFilter.FIND_EDGES)
filter(ImageFilter.SMOOTH)
filter(ImageFilter.SMOOTH_MORE)
filter(ImageFilter.SHARPEN)
filter(ImageFilter.MaxFilter)
filter(ImageFilter.MedianFilter)
filter(ImageFilter.MinFilter)
filter(ImageFilter.ModeFilter)
filter(ImageFilter.Kernel((3, 3), list(range(9))))
# crashes on small images self.assertRaises(TypeError, lambda: filter("hello"))
im = Image.new("RGB", (1, 1))
assert_no_exception(lambda: im.filter(ImageFilter.SMOOTH))
im = Image.new("RGB", (2, 2)) def test_crash(self):
assert_no_exception(lambda: im.filter(ImageFilter.SMOOTH))
im = Image.new("RGB", (3, 3)) # crashes on small images
assert_no_exception(lambda: im.filter(ImageFilter.SMOOTH)) im = Image.new("RGB", (1, 1))
im.filter(ImageFilter.SMOOTH)
def test_modefilter(): im = Image.new("RGB", (2, 2))
im.filter(ImageFilter.SMOOTH)
def modefilter(mode): im = Image.new("RGB", (3, 3))
im = Image.new(mode, (3, 3), None) im.filter(ImageFilter.SMOOTH)
im.putdata(list(range(9)))
# image is:
# 0 1 2
# 3 4 5
# 6 7 8
mod = im.filter(ImageFilter.ModeFilter).getpixel((1, 1))
im.putdata([0, 0, 1, 2, 5, 1, 5, 2, 0]) # mode=0
mod2 = im.filter(ImageFilter.ModeFilter).getpixel((1, 1))
return mod, mod2
assert_equal(modefilter("1"), (4, 0)) def test_modefilter(self):
assert_equal(modefilter("L"), (4, 0))
assert_equal(modefilter("P"), (4, 0))
assert_equal(modefilter("RGB"), ((4, 0, 0), (0, 0, 0)))
def test_rankfilter(): def modefilter(mode):
im = Image.new(mode, (3, 3), None)
im.putdata(list(range(9)))
# image is:
# 0 1 2
# 3 4 5
# 6 7 8
mod = im.filter(ImageFilter.ModeFilter).getpixel((1, 1))
im.putdata([0, 0, 1, 2, 5, 1, 5, 2, 0]) # mode=0
mod2 = im.filter(ImageFilter.ModeFilter).getpixel((1, 1))
return mod, mod2
def rankfilter(mode): self.assertEqual(modefilter("1"), (4, 0))
im = Image.new(mode, (3, 3), None) self.assertEqual(modefilter("L"), (4, 0))
im.putdata(list(range(9))) self.assertEqual(modefilter("P"), (4, 0))
# image is: self.assertEqual(modefilter("RGB"), ((4, 0, 0), (0, 0, 0)))
# 0 1 2
# 3 4 5
# 6 7 8
min = im.filter(ImageFilter.MinFilter).getpixel((1, 1))
med = im.filter(ImageFilter.MedianFilter).getpixel((1, 1))
max = im.filter(ImageFilter.MaxFilter).getpixel((1, 1))
return min, med, max
assert_equal(rankfilter("1"), (0, 4, 8)) def test_rankfilter(self):
assert_equal(rankfilter("L"), (0, 4, 8))
assert_exception(ValueError, lambda: rankfilter("P")) def rankfilter(mode):
assert_equal(rankfilter("RGB"), ((0, 0, 0), (4, 0, 0), (8, 0, 0))) im = Image.new(mode, (3, 3), None)
assert_equal(rankfilter("I"), (0, 4, 8)) im.putdata(list(range(9)))
assert_equal(rankfilter("F"), (0.0, 4.0, 8.0)) # image is:
# 0 1 2
# 3 4 5
# 6 7 8
min = im.filter(ImageFilter.MinFilter).getpixel((1, 1))
med = im.filter(ImageFilter.MedianFilter).getpixel((1, 1))
max = im.filter(ImageFilter.MaxFilter).getpixel((1, 1))
return min, med, max
self.assertEqual(rankfilter("1"), (0, 4, 8))
self.assertEqual(rankfilter("L"), (0, 4, 8))
self.assertRaises(ValueError, lambda: rankfilter("P"))
self.assertEqual(rankfilter("RGB"), ((0, 0, 0), (4, 0, 0), (8, 0, 0)))
self.assertEqual(rankfilter("I"), (0, 4, 8))
self.assertEqual(rankfilter("F"), (0.0, 4.0, 8.0))
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,10 +1,18 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image from PIL import Image
def test_sanity():
im1 = lena()
im2 = Image.frombytes(im1.mode, im1.size, im1.tobytes())
assert_image_equal(im1, im2) class TestImageFromBytes(PillowTestCase):
def test_sanity(self):
im1 = lena()
im2 = Image.frombytes(im1.mode, im1.size, im1.tobytes())
self.assert_image_equal(im1, im2)
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,15 +1,26 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule
from PIL import Image from PIL import Image
def test_getbands():
assert_equal(Image.new("1", (1, 1)).getbands(), ("1",)) class TestImageGetBands(PillowTestCase):
assert_equal(Image.new("L", (1, 1)).getbands(), ("L",))
assert_equal(Image.new("I", (1, 1)).getbands(), ("I",)) def test_getbands(self):
assert_equal(Image.new("F", (1, 1)).getbands(), ("F",)) self.assertEqual(Image.new("1", (1, 1)).getbands(), ("1",))
assert_equal(Image.new("P", (1, 1)).getbands(), ("P",)) self.assertEqual(Image.new("L", (1, 1)).getbands(), ("L",))
assert_equal(Image.new("RGB", (1, 1)).getbands(), ("R", "G", "B")) self.assertEqual(Image.new("I", (1, 1)).getbands(), ("I",))
assert_equal(Image.new("RGBA", (1, 1)).getbands(), ("R", "G", "B", "A")) self.assertEqual(Image.new("F", (1, 1)).getbands(), ("F",))
assert_equal(Image.new("CMYK", (1, 1)).getbands(), ("C", "M", "Y", "K")) self.assertEqual(Image.new("P", (1, 1)).getbands(), ("P",))
assert_equal(Image.new("YCbCr", (1, 1)).getbands(), ("Y", "Cb", "Cr")) self.assertEqual(Image.new("RGB", (1, 1)).getbands(), ("R", "G", "B"))
self.assertEqual(
Image.new("RGBA", (1, 1)).getbands(), ("R", "G", "B", "A"))
self.assertEqual(
Image.new("CMYK", (1, 1)).getbands(), ("C", "M", "Y", "K"))
self.assertEqual(
Image.new("YCbCr", (1, 1)).getbands(), ("Y", "Cb", "Cr"))
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,36 +1,45 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image from PIL import Image
def test_sanity():
bbox = lena().getbbox() class TestImageGetBbox(PillowTestCase):
assert_true(isinstance(bbox, tuple))
def test_bbox(): def test_sanity(self):
# 8-bit mode bbox = lena().getbbox()
im = Image.new("L", (100, 100), 0) self.assertIsInstance(bbox, tuple)
assert_equal(im.getbbox(), None)
im.paste(255, (10, 25, 90, 75)) def test_bbox(self):
assert_equal(im.getbbox(), (10, 25, 90, 75))
im.paste(255, (25, 10, 75, 90)) # 8-bit mode
assert_equal(im.getbbox(), (10, 10, 90, 90)) im = Image.new("L", (100, 100), 0)
self.assertEqual(im.getbbox(), None)
im.paste(255, (-10, -10, 110, 110)) im.paste(255, (10, 25, 90, 75))
assert_equal(im.getbbox(), (0, 0, 100, 100)) self.assertEqual(im.getbbox(), (10, 25, 90, 75))
# 32-bit mode im.paste(255, (25, 10, 75, 90))
im = Image.new("RGB", (100, 100), 0) self.assertEqual(im.getbbox(), (10, 10, 90, 90))
assert_equal(im.getbbox(), None)
im.paste(255, (10, 25, 90, 75)) im.paste(255, (-10, -10, 110, 110))
assert_equal(im.getbbox(), (10, 25, 90, 75)) self.assertEqual(im.getbbox(), (0, 0, 100, 100))
im.paste(255, (25, 10, 75, 90)) # 32-bit mode
assert_equal(im.getbbox(), (10, 10, 90, 90)) im = Image.new("RGB", (100, 100), 0)
self.assertEqual(im.getbbox(), None)
im.paste(255, (-10, -10, 110, 110)) im.paste(255, (10, 25, 90, 75))
assert_equal(im.getbbox(), (0, 0, 100, 100)) self.assertEqual(im.getbbox(), (10, 25, 90, 75))
im.paste(255, (25, 10, 75, 90))
self.assertEqual(im.getbbox(), (10, 10, 90, 90))
im.paste(255, (-10, -10, 110, 110))
self.assertEqual(im.getbbox(), (0, 0, 100, 100))
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,64 +1,74 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image
def test_getcolors(): class TestImageGetColors(PillowTestCase):
def getcolors(mode, limit=None): def test_getcolors(self):
im = lena(mode)
if limit:
colors = im.getcolors(limit)
else:
colors = im.getcolors()
if colors:
return len(colors)
return None
assert_equal(getcolors("1"), 2) def getcolors(mode, limit=None):
assert_equal(getcolors("L"), 193) im = lena(mode)
assert_equal(getcolors("I"), 193) if limit:
assert_equal(getcolors("F"), 193) colors = im.getcolors(limit)
assert_equal(getcolors("P"), 54) # fixed palette else:
assert_equal(getcolors("RGB"), None) colors = im.getcolors()
assert_equal(getcolors("RGBA"), None) if colors:
assert_equal(getcolors("CMYK"), None) return len(colors)
assert_equal(getcolors("YCbCr"), None) return None
assert_equal(getcolors("L", 128), None) self.assertEqual(getcolors("1"), 2)
assert_equal(getcolors("L", 1024), 193) self.assertEqual(getcolors("L"), 193)
self.assertEqual(getcolors("I"), 193)
self.assertEqual(getcolors("F"), 193)
self.assertEqual(getcolors("P"), 54) # fixed palette
self.assertEqual(getcolors("RGB"), None)
self.assertEqual(getcolors("RGBA"), None)
self.assertEqual(getcolors("CMYK"), None)
self.assertEqual(getcolors("YCbCr"), None)
assert_equal(getcolors("RGB", 8192), None) self.assertEqual(getcolors("L", 128), None)
assert_equal(getcolors("RGB", 16384), 14836) self.assertEqual(getcolors("L", 1024), 193)
assert_equal(getcolors("RGB", 100000), 14836)
assert_equal(getcolors("RGBA", 16384), 14836) self.assertEqual(getcolors("RGB", 8192), None)
assert_equal(getcolors("CMYK", 16384), 14836) self.assertEqual(getcolors("RGB", 16384), 14836)
assert_equal(getcolors("YCbCr", 16384), 11995) self.assertEqual(getcolors("RGB", 100000), 14836)
# -------------------------------------------------------------------- self.assertEqual(getcolors("RGBA", 16384), 14836)
self.assertEqual(getcolors("CMYK", 16384), 14836)
self.assertEqual(getcolors("YCbCr", 16384), 11995)
def test_pack(): # --------------------------------------------------------------------
# Pack problems for small tables (@PIL209)
im = lena().quantize(3).convert("RGB") def test_pack(self):
# Pack problems for small tables (@PIL209)
expected = [(3236, (227, 183, 147)), (6297, (143, 84, 81)), (6851, (208, 143, 112))] im = lena().quantize(3).convert("RGB")
A = im.getcolors(maxcolors=2) expected = [
assert_equal(A, None) (3236, (227, 183, 147)),
(6297, (143, 84, 81)),
(6851, (208, 143, 112))]
A = im.getcolors(maxcolors=3) A = im.getcolors(maxcolors=2)
A.sort() self.assertEqual(A, None)
assert_equal(A, expected)
A = im.getcolors(maxcolors=4) A = im.getcolors(maxcolors=3)
A.sort() A.sort()
assert_equal(A, expected) self.assertEqual(A, expected)
A = im.getcolors(maxcolors=8) A = im.getcolors(maxcolors=4)
A.sort() A.sort()
assert_equal(A, expected) self.assertEqual(A, expected)
A = im.getcolors(maxcolors=16) A = im.getcolors(maxcolors=8)
A.sort() A.sort()
assert_equal(A, expected) self.assertEqual(A, expected)
A = im.getcolors(maxcolors=16)
A.sort()
self.assertEqual(A, expected)
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,28 +1,35 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image
def test_sanity(): class TestImageGetData(PillowTestCase):
data = lena().getdata() def test_sanity(self):
assert_no_exception(lambda: len(data)) data = lena().getdata()
assert_no_exception(lambda: list(data))
assert_equal(data[0], (223, 162, 133)) len(data)
list(data)
def test_roundtrip(): self.assertEqual(data[0], (223, 162, 133))
def getdata(mode): def test_roundtrip(self):
im = lena(mode).resize((32, 30))
data = im.getdata()
return data[0], len(data), len(list(data))
assert_equal(getdata("1"), (255, 960, 960)) def getdata(mode):
assert_equal(getdata("L"), (176, 960, 960)) im = lena(mode).resize((32, 30))
assert_equal(getdata("I"), (176, 960, 960)) data = im.getdata()
assert_equal(getdata("F"), (176.0, 960, 960)) return data[0], len(data), len(list(data))
assert_equal(getdata("RGB"), ((223, 162, 133), 960, 960))
assert_equal(getdata("RGBA"), ((223, 162, 133, 255), 960, 960)) self.assertEqual(getdata("1"), (255, 960, 960))
assert_equal(getdata("CMYK"), ((32, 93, 122, 0), 960, 960)) self.assertEqual(getdata("L"), (176, 960, 960))
assert_equal(getdata("YCbCr"), ((176, 103, 160), 960, 960)) self.assertEqual(getdata("I"), (176, 960, 960))
self.assertEqual(getdata("F"), (176.0, 960, 960))
self.assertEqual(getdata("RGB"), ((223, 162, 133), 960, 960))
self.assertEqual(getdata("RGBA"), ((223, 162, 133, 255), 960, 960))
self.assertEqual(getdata("CMYK"), ((32, 93, 122, 0), 960, 960))
self.assertEqual(getdata("YCbCr"), ((176, 103, 160), 960, 960))
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,17 +1,27 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image
def test_extrema(): class TestImageGetExtrema(PillowTestCase):
def extrema(mode): def test_extrema(self):
return lena(mode).getextrema()
assert_equal(extrema("1"), (0, 255)) def extrema(mode):
assert_equal(extrema("L"), (40, 235)) return lena(mode).getextrema()
assert_equal(extrema("I"), (40, 235))
assert_equal(extrema("F"), (40.0, 235.0)) self.assertEqual(extrema("1"), (0, 255))
assert_equal(extrema("P"), (11, 218)) # fixed palette self.assertEqual(extrema("L"), (40, 235))
assert_equal(extrema("RGB"), ((61, 255), (26, 234), (44, 223))) self.assertEqual(extrema("I"), (40, 235))
assert_equal(extrema("RGBA"), ((61, 255), (26, 234), (44, 223), (255, 255))) self.assertEqual(extrema("F"), (40.0, 235.0))
assert_equal(extrema("CMYK"), ((0, 194), (21, 229), (32, 211), (0, 0))) self.assertEqual(extrema("P"), (11, 218)) # fixed palette
self.assertEqual(
extrema("RGB"), ((61, 255), (26, 234), (44, 223)))
self.assertEqual(
extrema("RGBA"), ((61, 255), (26, 234), (44, 223), (255, 255)))
self.assertEqual(
extrema("CMYK"), ((0, 194), (21, 229), (32, 211), (0, 0)))
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,14 +1,19 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena, py3
from PIL import Image
def test_sanity(): class TestImageGetIm(PillowTestCase):
im = lena() def test_sanity(self):
type_repr = repr(type(im.getim())) im = lena()
type_repr = repr(type(im.getim()))
if py3: if py3:
assert_true("PyCapsule" in type_repr) self.assertIn("PyCapsule", type_repr)
assert_true(isinstance(im.im.id, int)) self.assertIsInstance(im.im.id, int)
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,19 +1,26 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image
def test_palette(): class TestImageGetPalette(PillowTestCase):
def palette(mode):
p = lena(mode).getpalette() def test_palette(self):
if p: def palette(mode):
return p[:10] p = lena(mode).getpalette()
return None if p:
assert_equal(palette("1"), None) return p[:10]
assert_equal(palette("L"), None) return None
assert_equal(palette("I"), None) self.assertEqual(palette("1"), None)
assert_equal(palette("F"), None) self.assertEqual(palette("L"), None)
assert_equal(palette("P"), [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) self.assertEqual(palette("I"), None)
assert_equal(palette("RGB"), None) self.assertEqual(palette("F"), None)
assert_equal(palette("RGBA"), None) self.assertEqual(palette("P"), [0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
assert_equal(palette("CMYK"), None) self.assertEqual(palette("RGB"), None)
assert_equal(palette("YCbCr"), None) self.assertEqual(palette("RGBA"), None)
self.assertEqual(palette("CMYK"), None)
self.assertEqual(palette("YCbCr"), None)
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,8 +1,9 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule
from PIL import Image from PIL import Image
Image.USE_CFFI_ACCESS=False Image.USE_CFFI_ACCESS = False
def color(mode): def color(mode):
bands = Image.getmodebands(mode) bands = Image.getmodebands(mode)
@ -12,38 +13,41 @@ def color(mode):
return tuple(range(1, bands+1)) return tuple(range(1, bands+1))
class TestImageGetPixel(PillowTestCase):
def check(mode, c=None): def check(self, mode, c=None):
if not c: if not c:
c = color(mode) c = color(mode)
#check putpixel
im = Image.new(mode, (1, 1), None)
im.putpixel((0, 0), c)
assert_equal(im.getpixel((0, 0)), c,
"put/getpixel roundtrip failed for mode %s, color %s" %
(mode, c))
# check inital color
im = Image.new(mode, (1, 1), c)
assert_equal(im.getpixel((0, 0)), c,
"initial color failed for mode %s, color %s " %
(mode, color))
def test_basic(): # check putpixel
for mode in ("1", "L", "LA", "I", "I;16", "I;16B", "F", im = Image.new(mode, (1, 1), None)
"P", "PA", "RGB", "RGBA", "RGBX", "CMYK","YCbCr"): im.putpixel((0, 0), c)
check(mode) self.assertEqual(
im.getpixel((0, 0)), c,
"put/getpixel roundtrip failed for mode %s, color %s" % (mode, c))
def test_signedness(): # check inital color
# see https://github.com/python-imaging/Pillow/issues/452 im = Image.new(mode, (1, 1), c)
# pixelaccess is using signed int* instead of uint* self.assertEqual(
for mode in ("I;16", "I;16B"): im.getpixel((0, 0)), c,
check(mode, 2**15-1) "initial color failed for mode %s, color %s " % (mode, color))
check(mode, 2**15)
check(mode, 2**15+1)
check(mode, 2**16-1)
def test_basic(self):
for mode in ("1", "L", "LA", "I", "I;16", "I;16B", "F",
"P", "PA", "RGB", "RGBA", "RGBX", "CMYK", "YCbCr"):
self.check(mode)
def test_signedness(self):
# see https://github.com/python-pillow/Pillow/issues/452
# pixelaccess is using signed int* instead of uint*
for mode in ("I;16", "I;16B"):
self.check(mode, 2**15-1)
self.check(mode, 2**15)
self.check(mode, 2**15+1)
self.check(mode, 2**16-1)
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,30 +1,38 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image from PIL import Image
def test_sanity():
im = lena() class TestImageGetProjection(PillowTestCase):
projection = im.getprojection() def test_sanity(self):
assert_equal(len(projection), 2) im = lena()
assert_equal(len(projection[0]), im.size[0])
assert_equal(len(projection[1]), im.size[1])
# 8-bit image projection = im.getprojection()
im = Image.new("L", (10, 10))
assert_equal(im.getprojection()[0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
assert_equal(im.getprojection()[1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
im.paste(255, (2, 4, 8, 6))
assert_equal(im.getprojection()[0], [0, 0, 1, 1, 1, 1, 1, 1, 0, 0])
assert_equal(im.getprojection()[1], [0, 0, 0, 0, 1, 1, 0, 0, 0, 0])
# 32-bit image self.assertEqual(len(projection), 2)
im = Image.new("RGB", (10, 10)) self.assertEqual(len(projection[0]), im.size[0])
assert_equal(im.getprojection()[0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) self.assertEqual(len(projection[1]), im.size[1])
assert_equal(im.getprojection()[1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
im.paste(255, (2, 4, 8, 6))
assert_equal(im.getprojection()[0], [0, 0, 1, 1, 1, 1, 1, 1, 0, 0])
assert_equal(im.getprojection()[1], [0, 0, 0, 0, 1, 1, 0, 0, 0, 0])
# 8-bit image
im = Image.new("L", (10, 10))
self.assertEqual(im.getprojection()[0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
self.assertEqual(im.getprojection()[1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
im.paste(255, (2, 4, 8, 6))
self.assertEqual(im.getprojection()[0], [0, 0, 1, 1, 1, 1, 1, 1, 0, 0])
self.assertEqual(im.getprojection()[1], [0, 0, 0, 0, 1, 1, 0, 0, 0, 0])
# 32-bit image
im = Image.new("RGB", (10, 10))
self.assertEqual(im.getprojection()[0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
self.assertEqual(im.getprojection()[1], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
im.paste(255, (2, 4, 8, 6))
self.assertEqual(im.getprojection()[0], [0, 0, 1, 1, 1, 1, 1, 1, 0, 0])
self.assertEqual(im.getprojection()[1], [0, 0, 0, 0, 1, 1, 0, 0, 0, 0])
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,19 +1,26 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image
def test_histogram(): class TestImageHistogram(PillowTestCase):
def histogram(mode): def test_histogram(self):
h = lena(mode).histogram()
return len(h), min(h), max(h)
assert_equal(histogram("1"), (256, 0, 8872)) def histogram(mode):
assert_equal(histogram("L"), (256, 0, 199)) h = lena(mode).histogram()
assert_equal(histogram("I"), (256, 0, 199)) return len(h), min(h), max(h)
assert_equal(histogram("F"), (256, 0, 199))
assert_equal(histogram("P"), (256, 0, 2912)) self.assertEqual(histogram("1"), (256, 0, 8872))
assert_equal(histogram("RGB"), (768, 0, 285)) self.assertEqual(histogram("L"), (256, 0, 199))
assert_equal(histogram("RGBA"), (1024, 0, 16384)) self.assertEqual(histogram("I"), (256, 0, 199))
assert_equal(histogram("CMYK"), (1024, 0, 16384)) self.assertEqual(histogram("F"), (256, 0, 199))
assert_equal(histogram("YCbCr"), (768, 0, 741)) self.assertEqual(histogram("P"), (256, 0, 2912))
self.assertEqual(histogram("RGB"), (768, 0, 285))
self.assertEqual(histogram("RGBA"), (1024, 0, 16384))
self.assertEqual(histogram("CMYK"), (1024, 0, 16384))
self.assertEqual(histogram("YCbCr"), (768, 0, 741))
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,27 +1,35 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image from PIL import Image
import os import os
def test_sanity():
im = lena() class TestImageLoad(PillowTestCase):
pix = im.load() def test_sanity(self):
assert_equal(pix[0, 0], (223, 162, 133)) im = lena()
def test_close(): pix = im.load()
im = Image.open("Images/lena.gif")
assert_no_exception(lambda: im.close())
assert_exception(ValueError, lambda: im.load())
assert_exception(ValueError, lambda: im.getpixel((0,0)))
def test_contextmanager(): self.assertEqual(pix[0, 0], (223, 162, 133))
fn = None
with Image.open("Images/lena.gif") as im:
fn = im.fp.fileno()
assert_no_exception(lambda: os.fstat(fn))
assert_exception(OSError, lambda: os.fstat(fn)) def test_close(self):
im = Image.open("Images/lena.gif")
im.close()
self.assertRaises(ValueError, lambda: im.load())
self.assertRaises(ValueError, lambda: im.getpixel((0, 0)))
def test_contextmanager(self):
fn = None
with Image.open("Images/lena.gif") as im:
fn = im.fp.fileno()
os.fstat(fn)
self.assertRaises(OSError, lambda: os.fstat(fn))
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,27 +1,36 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image from PIL import Image
def test_sanity():
im = lena() class TestImageMode(PillowTestCase):
assert_no_exception(lambda: im.mode)
def test_properties(): def test_sanity(self):
def check(mode, *result):
signature = ( im = lena()
Image.getmodebase(mode), Image.getmodetype(mode), im.mode
Image.getmodebands(mode), Image.getmodebandnames(mode),
) def test_properties(self):
assert_equal(signature, result) def check(mode, *result):
check("1", "L", "L", 1, ("1",)) signature = (
check("L", "L", "L", 1, ("L",)) Image.getmodebase(mode), Image.getmodetype(mode),
check("P", "RGB", "L", 1, ("P",)) Image.getmodebands(mode), Image.getmodebandnames(mode),
check("I", "L", "I", 1, ("I",)) )
check("F", "L", "F", 1, ("F",)) self.assertEqual(signature, result)
check("RGB", "RGB", "L", 3, ("R", "G", "B")) check("1", "L", "L", 1, ("1",))
check("RGBA", "RGB", "L", 4, ("R", "G", "B", "A")) check("L", "L", "L", 1, ("L",))
check("RGBX", "RGB", "L", 4, ("R", "G", "B", "X")) check("P", "RGB", "L", 1, ("P",))
check("RGBX", "RGB", "L", 4, ("R", "G", "B", "X")) check("I", "L", "I", 1, ("I",))
check("CMYK", "RGB", "L", 4, ("C", "M", "Y", "K")) check("F", "L", "F", 1, ("F",))
check("YCbCr", "RGB", "L", 3, ("Y", "Cb", "Cr")) check("RGB", "RGB", "L", 3, ("R", "G", "B"))
check("RGBA", "RGB", "L", 4, ("R", "G", "B", "A"))
check("RGBX", "RGB", "L", 4, ("R", "G", "B", "X"))
check("RGBX", "RGB", "L", 4, ("R", "G", "B", "X"))
check("CMYK", "RGB", "L", 4, ("C", "M", "Y", "K"))
check("YCbCr", "RGB", "L", 3, ("Y", "Cb", "Cr"))
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,16 +1,25 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image
def test_offset(): class TestImageOffset(PillowTestCase):
im1 = lena() def test_offset(self):
im2 = assert_warning(DeprecationWarning, lambda: im1.offset(10)) im1 = lena()
assert_equal(im1.getpixel((0, 0)), im2.getpixel((10, 10)))
im2 = assert_warning(DeprecationWarning, lambda: im1.offset(10, 20)) im2 = self.assert_warning(DeprecationWarning, lambda: im1.offset(10))
assert_equal(im1.getpixel((0, 0)), im2.getpixel((10, 20))) self.assertEqual(im1.getpixel((0, 0)), im2.getpixel((10, 10)))
im2 = assert_warning(DeprecationWarning, lambda: im1.offset(20, 20)) im2 = self.assert_warning(
assert_equal(im1.getpixel((0, 0)), im2.getpixel((20, 20))) DeprecationWarning, lambda: im1.offset(10, 20))
self.assertEqual(im1.getpixel((0, 0)), im2.getpixel((10, 20)))
im2 = self.assert_warning(
DeprecationWarning, lambda: im1.offset(20, 20))
self.assertEqual(im1.getpixel((0, 0)), im2.getpixel((20, 20)))
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,5 +0,0 @@
from tester import *
from PIL import Image
success()

View File

@ -1,33 +1,41 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image import sys
if hasattr(sys, 'pypy_version_info'):
# This takes _forever_ on pypy. Open Bug,
# see https://github.com/python-imaging/Pillow/issues/484
skip()
def test_sanity():
im = lena()
assert_exception(ValueError, lambda: im.point(list(range(256))))
assert_no_exception(lambda: im.point(list(range(256))*3))
assert_no_exception(lambda: im.point(lambda x: x))
im = im.convert("I")
assert_exception(ValueError, lambda: im.point(list(range(256))))
assert_no_exception(lambda: im.point(lambda x: x*1))
assert_no_exception(lambda: im.point(lambda x: x+1))
assert_no_exception(lambda: im.point(lambda x: x*1+1))
assert_exception(TypeError, lambda: im.point(lambda x: x-1))
assert_exception(TypeError, lambda: im.point(lambda x: x/1))
def test_16bit_lut(): class TestImagePoint(PillowTestCase):
""" Tests for 16 bit -> 8 bit lut for converting I->L images
see https://github.com/python-imaging/Pillow/issues/440
"""
im = lena("I") def setUp(self):
assert_no_exception(lambda: im.point(list(range(256))*256, 'L')) if hasattr(sys, 'pypy_version_info'):
# This takes _forever_ on PyPy. Open Bug,
# see https://github.com/python-pillow/Pillow/issues/484
self.skipTest("Too slow on PyPy")
def test_sanity(self):
im = lena()
self.assertRaises(ValueError, lambda: im.point(list(range(256))))
im.point(list(range(256))*3)
im.point(lambda x: x)
im = im.convert("I")
self.assertRaises(ValueError, lambda: im.point(list(range(256))))
im.point(lambda x: x*1)
im.point(lambda x: x+1)
im.point(lambda x: x*1+1)
self.assertRaises(TypeError, lambda: im.point(lambda x: x-1))
self.assertRaises(TypeError, lambda: im.point(lambda x: x/1))
def test_16bit_lut(self):
""" Tests for 16 bit -> 8 bit lut for converting I->L images
see https://github.com/python-pillow/Pillow/issues/440
"""
im = lena("I")
im.point(list(range(256))*256, 'L')
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,43 +1,52 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule
from PIL import Image from PIL import Image
def test_interface():
im = Image.new("RGBA", (1, 1), (1, 2, 3, 0)) class TestImagePutAlpha(PillowTestCase):
assert_equal(im.getpixel((0, 0)), (1, 2, 3, 0))
im = Image.new("RGBA", (1, 1), (1, 2, 3)) def test_interface(self):
assert_equal(im.getpixel((0, 0)), (1, 2, 3, 255))
im.putalpha(Image.new("L", im.size, 4)) im = Image.new("RGBA", (1, 1), (1, 2, 3, 0))
assert_equal(im.getpixel((0, 0)), (1, 2, 3, 4)) self.assertEqual(im.getpixel((0, 0)), (1, 2, 3, 0))
im.putalpha(5) im = Image.new("RGBA", (1, 1), (1, 2, 3))
assert_equal(im.getpixel((0, 0)), (1, 2, 3, 5)) self.assertEqual(im.getpixel((0, 0)), (1, 2, 3, 255))
def test_promote(): im.putalpha(Image.new("L", im.size, 4))
self.assertEqual(im.getpixel((0, 0)), (1, 2, 3, 4))
im = Image.new("L", (1, 1), 1) im.putalpha(5)
assert_equal(im.getpixel((0, 0)), 1) self.assertEqual(im.getpixel((0, 0)), (1, 2, 3, 5))
im.putalpha(2) def test_promote(self):
assert_equal(im.mode, 'LA')
assert_equal(im.getpixel((0, 0)), (1, 2))
im = Image.new("RGB", (1, 1), (1, 2, 3)) im = Image.new("L", (1, 1), 1)
assert_equal(im.getpixel((0, 0)), (1, 2, 3)) self.assertEqual(im.getpixel((0, 0)), 1)
im.putalpha(4) im.putalpha(2)
assert_equal(im.mode, 'RGBA') self.assertEqual(im.mode, 'LA')
assert_equal(im.getpixel((0, 0)), (1, 2, 3, 4)) self.assertEqual(im.getpixel((0, 0)), (1, 2))
def test_readonly(): im = Image.new("RGB", (1, 1), (1, 2, 3))
self.assertEqual(im.getpixel((0, 0)), (1, 2, 3))
im = Image.new("RGB", (1, 1), (1, 2, 3)) im.putalpha(4)
im.readonly = 1 self.assertEqual(im.mode, 'RGBA')
self.assertEqual(im.getpixel((0, 0)), (1, 2, 3, 4))
im.putalpha(4) def test_readonly(self):
assert_false(im.readonly)
assert_equal(im.mode, 'RGBA') im = Image.new("RGB", (1, 1), (1, 2, 3))
assert_equal(im.getpixel((0, 0)), (1, 2, 3, 4)) im.readonly = 1
im.putalpha(4)
self.assertFalse(im.readonly)
self.assertEqual(im.mode, 'RGBA')
self.assertEqual(im.getpixel((0, 0)), (1, 2, 3, 4))
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,40 +1,48 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
import sys import sys
from PIL import Image from PIL import Image
def test_sanity():
im1 = lena() class TestImagePutData(PillowTestCase):
data = list(im1.getdata()) def test_sanity(self):
im2 = Image.new(im1.mode, im1.size, 0) im1 = lena()
im2.putdata(data)
assert_image_equal(im1, im2) data = list(im1.getdata())
# readonly im2 = Image.new(im1.mode, im1.size, 0)
im2 = Image.new(im1.mode, im2.size, 0) im2.putdata(data)
im2.readonly = 1
im2.putdata(data)
assert_false(im2.readonly) self.assert_image_equal(im1, im2)
assert_image_equal(im1, im2)
# readonly
im2 = Image.new(im1.mode, im2.size, 0)
im2.readonly = 1
im2.putdata(data)
self.assertFalse(im2.readonly)
self.assert_image_equal(im1, im2)
def test_long_integers(self):
# see bug-200802-systemerror
def put(value):
im = Image.new("RGBA", (1, 1))
im.putdata([value])
return im.getpixel((0, 0))
self.assertEqual(put(0xFFFFFFFF), (255, 255, 255, 255))
self.assertEqual(put(0xFFFFFFFF), (255, 255, 255, 255))
self.assertEqual(put(-1), (255, 255, 255, 255))
self.assertEqual(put(-1), (255, 255, 255, 255))
if sys.maxsize > 2**32:
self.assertEqual(put(sys.maxsize), (255, 255, 255, 255))
else:
self.assertEqual(put(sys.maxsize), (255, 255, 255, 127))
def test_long_integers(): if __name__ == '__main__':
# see bug-200802-systemerror unittest.main()
def put(value):
im = Image.new("RGBA", (1, 1)) # End of file
im.putdata([value])
return im.getpixel((0, 0))
assert_equal(put(0xFFFFFFFF), (255, 255, 255, 255))
assert_equal(put(0xFFFFFFFF), (255, 255, 255, 255))
assert_equal(put(-1), (255, 255, 255, 255))
assert_equal(put(-1), (255, 255, 255, 255))
if sys.maxsize > 2**32:
assert_equal(put(sys.maxsize), (255, 255, 255, 255))
else:
assert_equal(put(sys.maxsize), (255, 255, 255, 127))

View File

@ -1,28 +1,36 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image
from PIL import ImagePalette from PIL import ImagePalette
def test_putpalette():
def palette(mode):
im = lena(mode).copy()
im.putpalette(list(range(256))*3)
p = im.getpalette()
if p:
return im.mode, p[:10]
return im.mode
assert_exception(ValueError, lambda: palette("1"))
assert_equal(palette("L"), ("P", [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))
assert_equal(palette("P"), ("P", [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))
assert_exception(ValueError, lambda: palette("I"))
assert_exception(ValueError, lambda: palette("F"))
assert_exception(ValueError, lambda: palette("RGB"))
assert_exception(ValueError, lambda: palette("RGBA"))
assert_exception(ValueError, lambda: palette("YCbCr"))
def test_imagepalette(): class TestImagePutPalette(PillowTestCase):
im = lena("P")
assert_no_exception(lambda: im.putpalette(ImagePalette.negative())) def test_putpalette(self):
assert_no_exception(lambda: im.putpalette(ImagePalette.random())) def palette(mode):
assert_no_exception(lambda: im.putpalette(ImagePalette.sepia())) im = lena(mode).copy()
assert_no_exception(lambda: im.putpalette(ImagePalette.wedge())) im.putpalette(list(range(256))*3)
p = im.getpalette()
if p:
return im.mode, p[:10]
return im.mode
self.assertRaises(ValueError, lambda: palette("1"))
self.assertEqual(palette("L"), ("P", [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))
self.assertEqual(palette("P"), ("P", [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))
self.assertRaises(ValueError, lambda: palette("I"))
self.assertRaises(ValueError, lambda: palette("F"))
self.assertRaises(ValueError, lambda: palette("RGB"))
self.assertRaises(ValueError, lambda: palette("RGBA"))
self.assertRaises(ValueError, lambda: palette("YCbCr"))
def test_imagepalette(self):
im = lena("P")
im.putpalette(ImagePalette.negative())
im.putpalette(ImagePalette.random())
im.putpalette(ImagePalette.sepia())
im.putpalette(ImagePalette.wedge())
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,45 +1,50 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image from PIL import Image
Image.USE_CFFI_ACCESS=False Image.USE_CFFI_ACCESS = False
def test_sanity():
im1 = lena()
im2 = Image.new(im1.mode, im1.size, 0)
for y in range(im1.size[1]):
for x in range(im1.size[0]):
pos = x, y
im2.putpixel(pos, im1.getpixel(pos))
assert_image_equal(im1, im2)
im2 = Image.new(im1.mode, im1.size, 0)
im2.readonly = 1
for y in range(im1.size[1]):
for x in range(im1.size[0]):
pos = x, y
im2.putpixel(pos, im1.getpixel(pos))
assert_false(im2.readonly)
assert_image_equal(im1, im2)
im2 = Image.new(im1.mode, im1.size, 0)
pix1 = im1.load()
pix2 = im2.load()
for y in range(im1.size[1]):
for x in range(im1.size[0]):
pix2[x, y] = pix1[x, y]
assert_image_equal(im1, im2)
class TestImagePutPixel(PillowTestCase):
def test_sanity(self):
im1 = lena()
im2 = Image.new(im1.mode, im1.size, 0)
for y in range(im1.size[1]):
for x in range(im1.size[0]):
pos = x, y
im2.putpixel(pos, im1.getpixel(pos))
self.assert_image_equal(im1, im2)
im2 = Image.new(im1.mode, im1.size, 0)
im2.readonly = 1
for y in range(im1.size[1]):
for x in range(im1.size[0]):
pos = x, y
im2.putpixel(pos, im1.getpixel(pos))
self.assertFalse(im2.readonly)
self.assert_image_equal(im1, im2)
im2 = Image.new(im1.mode, im1.size, 0)
pix1 = im1.load()
pix2 = im2.load()
for y in range(im1.size[1]):
for x in range(im1.size[0]):
pix2[x, y] = pix1[x, y]
self.assert_image_equal(im1, im2)
# see test_image_getpixel for more tests
# see test_image_getpixel for more tests if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,27 +1,35 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image from PIL import Image
def test_sanity():
im = lena() class TestImageQuantize(PillowTestCase):
im = im.quantize() def test_sanity(self):
assert_image(im, "P", im.size) im = lena()
im = lena() im = im.quantize()
im = im.quantize(palette=lena("P")) self.assert_image(im, "P", im.size)
assert_image(im, "P", im.size)
def test_octree_quantize(): im = lena()
im = lena() im = im.quantize(palette=lena("P"))
self.assert_image(im, "P", im.size)
im = im.quantize(100, Image.FASTOCTREE) def test_octree_quantize(self):
assert_image(im, "P", im.size) im = lena()
assert len(im.getcolors()) == 100 im = im.quantize(100, Image.FASTOCTREE)
self.assert_image(im, "P", im.size)
def test_rgba_quantize(): assert len(im.getcolors()) == 100
im = lena('RGBA')
assert_no_exception(lambda: im.quantize()) def test_rgba_quantize(self):
assert_exception(Exception, lambda: im.quantize(method=0)) im = lena('RGBA')
im.quantize()
self.assertRaises(Exception, lambda: im.quantize(method=0))
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,12 +1,19 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image
def test_resize(): class TestImageResize(PillowTestCase):
def resize(mode, size):
out = lena(mode).resize(size) def test_resize(self):
assert_equal(out.mode, mode) def resize(mode, size):
assert_equal(out.size, size) out = lena(mode).resize(size)
for mode in "1", "P", "L", "RGB", "I", "F": self.assertEqual(out.mode, mode)
yield_test(resize, mode, (100, 100)) self.assertEqual(out.size, size)
yield_test(resize, mode, (200, 200)) for mode in "1", "P", "L", "RGB", "I", "F":
resize(mode, (100, 100))
resize(mode, (200, 200))
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,15 +1,22 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image
def test_rotate(): class TestImageRotate(PillowTestCase):
def rotate(mode):
im = lena(mode) def test_rotate(self):
out = im.rotate(45) def rotate(mode):
assert_equal(out.mode, mode) im = lena(mode)
assert_equal(out.size, im.size) # default rotate clips output out = im.rotate(45)
out = im.rotate(45, expand=1) self.assertEqual(out.mode, mode)
assert_equal(out.mode, mode) self.assertEqual(out.size, im.size) # default rotate clips output
assert_true(out.size != im.size) out = im.rotate(45, expand=1)
for mode in "1", "P", "L", "RGB", "I", "F": self.assertEqual(out.mode, mode)
yield_test(rotate, mode) self.assertNotEqual(out.size, im.size)
for mode in "1", "P", "L", "RGB", "I", "F":
rotate(mode)
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,5 +0,0 @@
from tester import *
from PIL import Image
success()

View File

@ -1,5 +0,0 @@
from tester import *
from PIL import Image
success()

View File

@ -1,5 +0,0 @@
from tester import *
from PIL import Image
success()

View File

@ -1,49 +1,67 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image from PIL import Image
def test_split():
def split(mode):
layers = lena(mode).split()
return [(i.mode, i.size[0], i.size[1]) for i in layers]
assert_equal(split("1"), [('1', 128, 128)])
assert_equal(split("L"), [('L', 128, 128)])
assert_equal(split("I"), [('I', 128, 128)])
assert_equal(split("F"), [('F', 128, 128)])
assert_equal(split("P"), [('P', 128, 128)])
assert_equal(split("RGB"), [('L', 128, 128), ('L', 128, 128), ('L', 128, 128)])
assert_equal(split("RGBA"), [('L', 128, 128), ('L', 128, 128), ('L', 128, 128), ('L', 128, 128)])
assert_equal(split("CMYK"), [('L', 128, 128), ('L', 128, 128), ('L', 128, 128), ('L', 128, 128)])
assert_equal(split("YCbCr"), [('L', 128, 128), ('L', 128, 128), ('L', 128, 128)])
def test_split_merge(): class TestImageSplit(PillowTestCase):
def split_merge(mode):
return Image.merge(mode, lena(mode).split())
assert_image_equal(lena("1"), split_merge("1"))
assert_image_equal(lena("L"), split_merge("L"))
assert_image_equal(lena("I"), split_merge("I"))
assert_image_equal(lena("F"), split_merge("F"))
assert_image_equal(lena("P"), split_merge("P"))
assert_image_equal(lena("RGB"), split_merge("RGB"))
assert_image_equal(lena("RGBA"), split_merge("RGBA"))
assert_image_equal(lena("CMYK"), split_merge("CMYK"))
assert_image_equal(lena("YCbCr"), split_merge("YCbCr"))
def test_split_open(): def test_split(self):
codecs = dir(Image.core) def split(mode):
layers = lena(mode).split()
return [(i.mode, i.size[0], i.size[1]) for i in layers]
self.assertEqual(split("1"), [('1', 128, 128)])
self.assertEqual(split("L"), [('L', 128, 128)])
self.assertEqual(split("I"), [('I', 128, 128)])
self.assertEqual(split("F"), [('F', 128, 128)])
self.assertEqual(split("P"), [('P', 128, 128)])
self.assertEqual(
split("RGB"), [('L', 128, 128), ('L', 128, 128), ('L', 128, 128)])
self.assertEqual(
split("RGBA"),
[('L', 128, 128), ('L', 128, 128),
('L', 128, 128), ('L', 128, 128)])
self.assertEqual(
split("CMYK"),
[('L', 128, 128), ('L', 128, 128),
('L', 128, 128), ('L', 128, 128)])
self.assertEqual(
split("YCbCr"),
[('L', 128, 128), ('L', 128, 128), ('L', 128, 128)])
if 'zip_encoder' in codecs: def test_split_merge(self):
file = tempfile("temp.png") def split_merge(mode):
else: return Image.merge(mode, lena(mode).split())
file = tempfile("temp.pcx") self.assert_image_equal(lena("1"), split_merge("1"))
self.assert_image_equal(lena("L"), split_merge("L"))
self.assert_image_equal(lena("I"), split_merge("I"))
self.assert_image_equal(lena("F"), split_merge("F"))
self.assert_image_equal(lena("P"), split_merge("P"))
self.assert_image_equal(lena("RGB"), split_merge("RGB"))
self.assert_image_equal(lena("RGBA"), split_merge("RGBA"))
self.assert_image_equal(lena("CMYK"), split_merge("CMYK"))
self.assert_image_equal(lena("YCbCr"), split_merge("YCbCr"))
def split_open(mode): def test_split_open(self):
lena(mode).save(file) codecs = dir(Image.core)
im = Image.open(file)
return len(im.split()) if 'zip_encoder' in codecs:
assert_equal(split_open("1"), 1) file = self.tempfile("temp.png")
assert_equal(split_open("L"), 1) else:
assert_equal(split_open("P"), 1) file = self.tempfile("temp.pcx")
assert_equal(split_open("RGB"), 3)
if 'zip_encoder' in codecs: def split_open(mode):
assert_equal(split_open("RGBA"), 4) lena(mode).save(file)
im = Image.open(file)
return len(im.split())
self.assertEqual(split_open("1"), 1)
self.assertEqual(split_open("L"), 1)
self.assertEqual(split_open("P"), 1)
self.assertEqual(split_open("RGB"), 3)
if 'zip_encoder' in codecs:
self.assertEqual(split_open("RGBA"), 4)
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,5 +0,0 @@
from tester import *
from PIL import Image
success()

View File

@ -1,36 +1,43 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image
def test_sanity(): class TestImageThumbnail(PillowTestCase):
im = lena() def test_sanity(self):
im.thumbnail((100, 100))
assert_image(im, im.mode, (100, 100)) im = lena()
im.thumbnail((100, 100))
def test_aspect(): self.assert_image(im, im.mode, (100, 100))
im = lena() def test_aspect(self):
im.thumbnail((100, 100))
assert_image(im, im.mode, (100, 100))
im = lena().resize((128, 256)) im = lena()
im.thumbnail((100, 100)) im.thumbnail((100, 100))
assert_image(im, im.mode, (50, 100)) self.assert_image(im, im.mode, (100, 100))
im = lena().resize((128, 256)) im = lena().resize((128, 256))
im.thumbnail((50, 100)) im.thumbnail((100, 100))
assert_image(im, im.mode, (50, 100)) self.assert_image(im, im.mode, (50, 100))
im = lena().resize((256, 128)) im = lena().resize((128, 256))
im.thumbnail((100, 100)) im.thumbnail((50, 100))
assert_image(im, im.mode, (100, 50)) self.assert_image(im, im.mode, (50, 100))
im = lena().resize((256, 128)) im = lena().resize((256, 128))
im.thumbnail((100, 50)) im.thumbnail((100, 100))
assert_image(im, im.mode, (100, 50)) self.assert_image(im, im.mode, (100, 50))
im = lena().resize((128, 128)) im = lena().resize((256, 128))
im.thumbnail((100, 100)) im.thumbnail((100, 50))
assert_image(im, im.mode, (100, 100)) self.assert_image(im, im.mode, (100, 50))
im = lena().resize((128, 128))
im.thumbnail((100, 100))
self.assert_image(im, im.mode, (100, 100))
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,15 +1,22 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena, fromstring
from PIL import Image
def test_sanity(): class TestImageToBitmap(PillowTestCase):
assert_exception(ValueError, lambda: lena().tobitmap()) def test_sanity(self):
assert_no_exception(lambda: lena().convert("1").tobitmap())
im1 = lena().convert("1") self.assertRaises(ValueError, lambda: lena().tobitmap())
lena().convert("1").tobitmap()
bitmap = im1.tobitmap() im1 = lena().convert("1")
assert_true(isinstance(bitmap, bytes)) bitmap = im1.tobitmap()
assert_image_equal(im1, fromstring(bitmap))
self.assertIsInstance(bitmap, bytes)
self.assert_image_equal(im1, fromstring(bitmap))
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,7 +1,13 @@
from tester import * from helper import unittest, lena
from PIL import Image
def test_sanity(): class TestImageToBytes(unittest.TestCase):
data = lena().tobytes()
assert_true(isinstance(data, bytes)) def test_sanity(self):
data = lena().tobytes()
self.assertTrue(isinstance(data, bytes))
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,116 +1,125 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image from PIL import Image
def test_extent():
im = lena('RGB')
(w,h) = im.size
transformed = im.transform(im.size, Image.EXTENT,
(0,0,
w//2,h//2), # ul -> lr
Image.BILINEAR)
class TestImageTransform(PillowTestCase):
scaled = im.resize((w*2, h*2), Image.BILINEAR).crop((0,0,w,h))
assert_image_similar(transformed, scaled, 10) # undone -- precision?
def test_quad(): def test_extent(self):
# one simple quad transform, equivalent to scale & crop upper left quad im = lena('RGB')
im = lena('RGB') (w, h) = im.size
(w,h) = im.size transformed = im.transform(im.size, Image.EXTENT,
transformed = im.transform(im.size, Image.QUAD, (0, 0,
(0,0,0,h//2, w//2, h//2), # ul -> lr
w//2,h//2,w//2,0), # ul -> ccw around quad Image.BILINEAR)
Image.BILINEAR)
scaled = im.resize((w*2, h*2), Image.BILINEAR).crop((0,0,w,h))
assert_image_equal(transformed, scaled)
def test_mesh(): scaled = im.resize((w*2, h*2), Image.BILINEAR).crop((0, 0, w, h))
# this should be a checkerboard of halfsized lenas in ul, lr
im = lena('RGBA')
(w,h) = im.size
transformed = im.transform(im.size, Image.MESH,
[((0,0,w//2,h//2), # box
(0,0,0,h,
w,h,w,0)), # ul -> ccw around quad
((w//2,h//2,w,h), # box
(0,0,0,h,
w,h,w,0))], # ul -> ccw around quad
Image.BILINEAR)
#transformed.save('transformed.png') # undone -- precision?
self.assert_image_similar(transformed, scaled, 10)
scaled = im.resize((w//2, h//2), Image.BILINEAR) def test_quad(self):
# one simple quad transform, equivalent to scale & crop upper left quad
im = lena('RGB')
(w, h) = im.size
transformed = im.transform(im.size, Image.QUAD,
(0, 0, 0, h//2,
# ul -> ccw around quad:
w//2, h//2, w//2, 0),
Image.BILINEAR)
checker = Image.new('RGBA', im.size) scaled = im.resize((w*2, h*2), Image.BILINEAR).crop((0, 0, w, h))
checker.paste(scaled, (0,0))
checker.paste(scaled, (w//2,h//2))
assert_image_equal(transformed, checker)
# now, check to see that the extra area is (0,0,0,0) self.assert_image_equal(transformed, scaled)
blank = Image.new('RGBA', (w//2,h//2), (0,0,0,0))
assert_image_equal(blank, transformed.crop((w//2,0,w,h//2))) def test_mesh(self):
assert_image_equal(blank, transformed.crop((0,h//2,w//2,h))) # this should be a checkerboard of halfsized lenas in ul, lr
im = lena('RGBA')
(w, h) = im.size
transformed = im.transform(im.size, Image.MESH,
[((0, 0, w//2, h//2), # box
(0, 0, 0, h,
w, h, w, 0)), # ul -> ccw around quad
((w//2, h//2, w, h), # box
(0, 0, 0, h,
w, h, w, 0))], # ul -> ccw around quad
Image.BILINEAR)
def _test_alpha_premult(op): # transformed.save('transformed.png')
# create image with half white, half black, with the black half transparent.
# do op,
# there should be no darkness in the white section.
im = Image.new('RGBA', (10,10), (0,0,0,0));
im2 = Image.new('RGBA', (5,10), (255,255,255,255));
im.paste(im2, (0,0))
im = op(im, (40,10))
im_background = Image.new('RGB', (40,10), (255,255,255))
im_background.paste(im, (0,0), im)
hist = im_background.histogram()
assert_equal(40*10, hist[-1])
scaled = im.resize((w//2, h//2), Image.BILINEAR)
def test_alpha_premult_resize():
def op (im, sz): checker = Image.new('RGBA', im.size)
return im.resize(sz, Image.LINEAR) checker.paste(scaled, (0, 0))
checker.paste(scaled, (w//2, h//2))
_test_alpha_premult(op)
def test_alpha_premult_transform():
def op(im, sz):
(w,h) = im.size
return im.transform(sz, Image.EXTENT,
(0,0,
w,h),
Image.BILINEAR)
_test_alpha_premult(op) self.assert_image_equal(transformed, checker)
# now, check to see that the extra area is (0, 0, 0, 0)
blank = Image.new('RGBA', (w//2, h//2), (0, 0, 0, 0))
self.assert_image_equal(blank, transformed.crop((w//2, 0, w, h//2)))
self.assert_image_equal(blank, transformed.crop((0, h//2, w//2, h)))
def _test_alpha_premult(self, op):
# create image with half white, half black,
# with the black half transparent.
# do op,
# there should be no darkness in the white section.
im = Image.new('RGBA', (10, 10), (0, 0, 0, 0))
im2 = Image.new('RGBA', (5, 10), (255, 255, 255, 255))
im.paste(im2, (0, 0))
im = op(im, (40, 10))
im_background = Image.new('RGB', (40, 10), (255, 255, 255))
im_background.paste(im, (0, 0), im)
hist = im_background.histogram()
self.assertEqual(40*10, hist[-1])
def test_alpha_premult_resize(self):
def op(im, sz):
return im.resize(sz, Image.LINEAR)
self._test_alpha_premult(op)
def test_alpha_premult_transform(self):
def op(im, sz):
(w, h) = im.size
return im.transform(sz, Image.EXTENT,
(0, 0,
w, h),
Image.BILINEAR)
self._test_alpha_premult(op)
def test_blank_fill(self):
# attempting to hit
# https://github.com/python-pillow/Pillow/issues/254 reported
#
# issue is that transforms with transparent overflow area
# contained junk from previous images, especially on systems with
# constrained memory. So, attempt to fill up memory with a
# pattern, free it, and then run the mesh test again. Using a 1Mp
# image with 4 bands, for 4 megs of data allocated, x 64. OMM (64
# bit 12.04 VM with 512 megs available, this fails with Pillow <
# a0eaf06cc5f62a6fb6de556989ac1014ff3348ea
#
# Running by default, but I'd totally understand not doing it in
# the future
foo = [Image.new('RGBA', (1024, 1024), (a, a, a, a))
for a in range(1, 65)]
# Yeah. Watch some JIT optimize this out.
foo = None
self.test_mesh()
def test_blank_fill(): if __name__ == '__main__':
# attempting to hit unittest.main()
# https://github.com/python-imaging/Pillow/issues/254 reported
#
# issue is that transforms with transparent overflow area
# contained junk from previous images, especially on systems with
# constrained memory. So, attempt to fill up memory with a
# pattern, free it, and then run the mesh test again. Using a 1Mp
# image with 4 bands, for 4 megs of data allocated, x 64. OMM (64
# bit 12.04 VM with 512 megs available, this fails with Pillow <
# a0eaf06cc5f62a6fb6de556989ac1014ff3348ea
#
# Running by default, but I'd totally understand not doing it in
# the future
foo = [Image.new('RGBA',(1024,1024), (a,a,a,a))
for a in range(1,65)]
# Yeah. Watch some JIT optimize this out. # End of file
foo = None
test_mesh()

View File

@ -1,4 +1,4 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image from PIL import Image
@ -8,27 +8,37 @@ ROTATE_90 = Image.ROTATE_90
ROTATE_180 = Image.ROTATE_180 ROTATE_180 = Image.ROTATE_180
ROTATE_270 = Image.ROTATE_270 ROTATE_270 = Image.ROTATE_270
def test_sanity():
im = lena() class TestImageTranspose(PillowTestCase):
assert_no_exception(lambda: im.transpose(FLIP_LEFT_RIGHT)) def test_sanity(self):
assert_no_exception(lambda: im.transpose(FLIP_TOP_BOTTOM))
assert_no_exception(lambda: im.transpose(ROTATE_90)) im = lena()
assert_no_exception(lambda: im.transpose(ROTATE_180))
assert_no_exception(lambda: im.transpose(ROTATE_270))
def test_roundtrip(): im.transpose(FLIP_LEFT_RIGHT)
im.transpose(FLIP_TOP_BOTTOM)
im = lena() im.transpose(ROTATE_90)
im.transpose(ROTATE_180)
im.transpose(ROTATE_270)
def transpose(first, second): def test_roundtrip(self):
return im.transpose(first).transpose(second)
assert_image_equal(im, transpose(FLIP_LEFT_RIGHT, FLIP_LEFT_RIGHT)) im = lena()
assert_image_equal(im, transpose(FLIP_TOP_BOTTOM, FLIP_TOP_BOTTOM))
assert_image_equal(im, transpose(ROTATE_90, ROTATE_270)) def transpose(first, second):
assert_image_equal(im, transpose(ROTATE_180, ROTATE_180)) return im.transpose(first).transpose(second)
self.assert_image_equal(
im, transpose(FLIP_LEFT_RIGHT, FLIP_LEFT_RIGHT))
self.assert_image_equal(
im, transpose(FLIP_TOP_BOTTOM, FLIP_TOP_BOTTOM))
self.assert_image_equal(im, transpose(ROTATE_90, ROTATE_270))
self.assert_image_equal(im, transpose(ROTATE_180, ROTATE_180))
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,5 +0,0 @@
from tester import *
from PIL import Image
success()

View File

@ -1,56 +1,74 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image from PIL import Image
from PIL import ImageChops from PIL import ImageChops
def test_sanity():
im = lena("L") class TestImageChops(PillowTestCase):
ImageChops.constant(im, 128) def test_sanity(self):
ImageChops.duplicate(im)
ImageChops.invert(im)
ImageChops.lighter(im, im)
ImageChops.darker(im, im)
ImageChops.difference(im, im)
ImageChops.multiply(im, im)
ImageChops.screen(im, im)
ImageChops.add(im, im) im = lena("L")
ImageChops.add(im, im, 2.0)
ImageChops.add(im, im, 2.0, 128)
ImageChops.subtract(im, im)
ImageChops.subtract(im, im, 2.0)
ImageChops.subtract(im, im, 2.0, 128)
ImageChops.add_modulo(im, im) ImageChops.constant(im, 128)
ImageChops.subtract_modulo(im, im) ImageChops.duplicate(im)
ImageChops.invert(im)
ImageChops.lighter(im, im)
ImageChops.darker(im, im)
ImageChops.difference(im, im)
ImageChops.multiply(im, im)
ImageChops.screen(im, im)
ImageChops.blend(im, im, 0.5) ImageChops.add(im, im)
ImageChops.composite(im, im, im) ImageChops.add(im, im, 2.0)
ImageChops.add(im, im, 2.0, 128)
ImageChops.subtract(im, im)
ImageChops.subtract(im, im, 2.0)
ImageChops.subtract(im, im, 2.0, 128)
ImageChops.offset(im, 10) ImageChops.add_modulo(im, im)
ImageChops.offset(im, 10, 20) ImageChops.subtract_modulo(im, im)
def test_logical(): ImageChops.blend(im, im, 0.5)
ImageChops.composite(im, im, im)
def table(op, a, b): ImageChops.offset(im, 10)
out = [] ImageChops.offset(im, 10, 20)
for x in (a, b):
imx = Image.new("1", (1, 1), x)
for y in (a, b):
imy = Image.new("1", (1, 1), y)
out.append(op(imx, imy).getpixel((0, 0)))
return tuple(out)
assert_equal(table(ImageChops.logical_and, 0, 1), (0, 0, 0, 255)) def test_logical(self):
assert_equal(table(ImageChops.logical_or, 0, 1), (0, 255, 255, 255))
assert_equal(table(ImageChops.logical_xor, 0, 1), (0, 255, 255, 0))
assert_equal(table(ImageChops.logical_and, 0, 128), (0, 0, 0, 255)) def table(op, a, b):
assert_equal(table(ImageChops.logical_or, 0, 128), (0, 255, 255, 255)) out = []
assert_equal(table(ImageChops.logical_xor, 0, 128), (0, 255, 255, 0)) for x in (a, b):
imx = Image.new("1", (1, 1), x)
for y in (a, b):
imy = Image.new("1", (1, 1), y)
out.append(op(imx, imy).getpixel((0, 0)))
return tuple(out)
assert_equal(table(ImageChops.logical_and, 0, 255), (0, 0, 0, 255)) self.assertEqual(
assert_equal(table(ImageChops.logical_or, 0, 255), (0, 255, 255, 255)) table(ImageChops.logical_and, 0, 1), (0, 0, 0, 255))
assert_equal(table(ImageChops.logical_xor, 0, 255), (0, 255, 255, 0)) self.assertEqual(
table(ImageChops.logical_or, 0, 1), (0, 255, 255, 255))
self.assertEqual(
table(ImageChops.logical_xor, 0, 1), (0, 255, 255, 0))
self.assertEqual(
table(ImageChops.logical_and, 0, 128), (0, 0, 0, 255))
self.assertEqual(
table(ImageChops.logical_or, 0, 128), (0, 255, 255, 255))
self.assertEqual(
table(ImageChops.logical_xor, 0, 128), (0, 255, 255, 0))
self.assertEqual(
table(ImageChops.logical_and, 0, 255), (0, 0, 0, 255))
self.assertEqual(
table(ImageChops.logical_or, 0, 255), (0, 255, 255, 255))
self.assertEqual(
table(ImageChops.logical_xor, 0, 255), (0, 255, 255, 0))
if __name__ == '__main__':
unittest.main()
# End of file

View File

@ -1,160 +1,214 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule, lena
from PIL import Image from PIL import Image
try: try:
from PIL import ImageCms from PIL import ImageCms
ImageCms.core.profile_open ImageCms.core.profile_open
except ImportError: except ImportError as v:
skip() # Skipped via setUp()
pass
SRGB = "Tests/icc/sRGB.icm" SRGB = "Tests/icc/sRGB.icm"
def test_sanity():
# basic smoke test. class TestImageCms(PillowTestCase):
# this mostly follows the cms_test outline.
v = ImageCms.versions() # should return four strings def setUp(self):
assert_equal(v[0], '1.0.0 pil') try:
assert_equal(list(map(type, v)), [str, str, str, str]) from PIL import ImageCms
except ImportError as v:
self.skipTest(v)
# internal version number def test_sanity(self):
assert_match(ImageCms.core.littlecms_version, "\d+\.\d+$")
i = ImageCms.profileToProfile(lena(), SRGB, SRGB) # basic smoke test.
assert_image(i, "RGB", (128, 128)) # this mostly follows the cms_test outline.
t = ImageCms.buildTransform(SRGB, SRGB, "RGB", "RGB") v = ImageCms.versions() # should return four strings
i = ImageCms.applyTransform(lena(), t) self.assertEqual(v[0], '1.0.0 pil')
assert_image(i, "RGB", (128, 128)) self.assertEqual(list(map(type, v)), [str, str, str, str])
p = ImageCms.createProfile("sRGB") # internal version number
o = ImageCms.getOpenProfile(SRGB) self.assertRegexpMatches(ImageCms.core.littlecms_version, "\d+\.\d+$")
t = ImageCms.buildTransformFromOpenProfiles(p, o, "RGB", "RGB")
i = ImageCms.applyTransform(lena(), t)
assert_image(i, "RGB", (128, 128))
t = ImageCms.buildProofTransform(SRGB, SRGB, SRGB, "RGB", "RGB") i = ImageCms.profileToProfile(lena(), SRGB, SRGB)
assert_equal(t.inputMode, "RGB") self.assert_image(i, "RGB", (128, 128))
assert_equal(t.outputMode, "RGB")
i = ImageCms.applyTransform(lena(), t)
assert_image(i, "RGB", (128, 128))
# test PointTransform convenience API i = lena()
im = lena().point(t) ImageCms.profileToProfile(i, SRGB, SRGB, inPlace=True)
self.assert_image(i, "RGB", (128, 128))
def test_name(): t = ImageCms.buildTransform(SRGB, SRGB, "RGB", "RGB")
# get profile information for file i = ImageCms.applyTransform(lena(), t)
assert_equal(ImageCms.getProfileName(SRGB).strip(), self.assert_image(i, "RGB", (128, 128))
'IEC 61966-2.1 Default RGB colour space - sRGB')
def x_test_info():
assert_equal(ImageCms.getProfileInfo(SRGB).splitlines(),
['sRGB IEC61966-2.1', '',
'Copyright (c) 1998 Hewlett-Packard Company', '',
'WhitePoint : D65 (daylight)', '',
'Tests/icc/sRGB.icm'])
def test_intent(): i = lena()
assert_equal(ImageCms.getDefaultIntent(SRGB), 0) t = ImageCms.buildTransform(SRGB, SRGB, "RGB", "RGB")
assert_equal(ImageCms.isIntentSupported( ImageCms.applyTransform(lena(), t, inPlace=True)
self.assert_image(i, "RGB", (128, 128))
p = ImageCms.createProfile("sRGB")
o = ImageCms.getOpenProfile(SRGB)
t = ImageCms.buildTransformFromOpenProfiles(p, o, "RGB", "RGB")
i = ImageCms.applyTransform(lena(), t)
self.assert_image(i, "RGB", (128, 128))
t = ImageCms.buildProofTransform(SRGB, SRGB, SRGB, "RGB", "RGB")
self.assertEqual(t.inputMode, "RGB")
self.assertEqual(t.outputMode, "RGB")
i = ImageCms.applyTransform(lena(), t)
self.assert_image(i, "RGB", (128, 128))
# test PointTransform convenience API
lena().point(t)
def test_name(self):
# get profile information for file
self.assertEqual(
ImageCms.getProfileName(SRGB).strip(),
'IEC 61966-2.1 Default RGB colour space - sRGB')
def test_info(self):
self.assertEqual(
ImageCms.getProfileInfo(SRGB).splitlines(), [
'sRGB IEC61966-2.1', '',
'Copyright (c) 1998 Hewlett-Packard Company', ''])
def test_copyright(self):
self.assertEqual(
ImageCms.getProfileCopyright(SRGB).strip(),
'Copyright (c) 1998 Hewlett-Packard Company')
def test_manufacturer(self):
self.assertEqual(
ImageCms.getProfileManufacturer(SRGB).strip(),
'IEC http://www.iec.ch')
def test_model(self):
self.assertEqual(
ImageCms.getProfileModel(SRGB).strip(),
'IEC 61966-2.1 Default RGB colour space - sRGB')
def test_description(self):
self.assertEqual(
ImageCms.getProfileDescription(SRGB).strip(),
'sRGB IEC61966-2.1')
def test_intent(self):
self.assertEqual(ImageCms.getDefaultIntent(SRGB), 0)
self.assertEqual(ImageCms.isIntentSupported(
SRGB, ImageCms.INTENT_ABSOLUTE_COLORIMETRIC, SRGB, ImageCms.INTENT_ABSOLUTE_COLORIMETRIC,
ImageCms.DIRECTION_INPUT), 1) ImageCms.DIRECTION_INPUT), 1)
def test_profile_object(): def test_profile_object(self):
# same, using profile object # same, using profile object
p = ImageCms.createProfile("sRGB") p = ImageCms.createProfile("sRGB")
# assert_equal(ImageCms.getProfileName(p).strip(), # self.assertEqual(ImageCms.getProfileName(p).strip(),
# 'sRGB built-in - (lcms internal)') # 'sRGB built-in - (lcms internal)')
# assert_equal(ImageCms.getProfileInfo(p).splitlines(), # self.assertEqual(ImageCms.getProfileInfo(p).splitlines(),
# ['sRGB built-in', '', 'WhitePoint : D65 (daylight)', '', '']) # ['sRGB built-in', '', 'WhitePoint : D65 (daylight)', '', ''])
assert_equal(ImageCms.getDefaultIntent(p), 0) self.assertEqual(ImageCms.getDefaultIntent(p), 0)
assert_equal(ImageCms.isIntentSupported( self.assertEqual(ImageCms.isIntentSupported(
p, ImageCms.INTENT_ABSOLUTE_COLORIMETRIC, p, ImageCms.INTENT_ABSOLUTE_COLORIMETRIC,
ImageCms.DIRECTION_INPUT), 1) ImageCms.DIRECTION_INPUT), 1)
def test_extensions(): def test_extensions(self):
# extensions # extensions
i = Image.open("Tests/images/rgb.jpg") from io import BytesIO
p = ImageCms.getOpenProfile(BytesIO(i.info["icc_profile"])) i = Image.open("Tests/images/rgb.jpg")
assert_equal(ImageCms.getProfileName(p).strip(), p = ImageCms.getOpenProfile(BytesIO(i.info["icc_profile"]))
'IEC 61966-2.1 Default RGB colour space - sRGB') self.assertEqual(
ImageCms.getProfileName(p).strip(),
'IEC 61966-2.1 Default RGB colour space - sRGB')
def test_exceptions(): def test_exceptions(self):
# the procedural pyCMS API uses PyCMSError for all sorts of errors # the procedural pyCMS API uses PyCMSError for all sorts of errors
assert_exception(ImageCms.PyCMSError, lambda: ImageCms.profileToProfile(lena(), "foo", "bar")) self.assertRaises(
assert_exception(ImageCms.PyCMSError, lambda: ImageCms.buildTransform("foo", "bar", "RGB", "RGB")) ImageCms.PyCMSError,
assert_exception(ImageCms.PyCMSError, lambda: ImageCms.getProfileName(None)) lambda: ImageCms.profileToProfile(lena(), "foo", "bar"))
assert_exception(ImageCms.PyCMSError, lambda: ImageCms.isIntentSupported(SRGB, None, None)) self.assertRaises(
ImageCms.PyCMSError,
lambda: ImageCms.buildTransform("foo", "bar", "RGB", "RGB"))
self.assertRaises(
ImageCms.PyCMSError,
lambda: ImageCms.getProfileName(None))
self.assertRaises(
ImageCms.PyCMSError,
lambda: ImageCms.isIntentSupported(SRGB, None, None))
def test_display_profile(self):
# try fetching the profile for the current display device
ImageCms.get_display_profile()
def test_lab_color_profile(self):
ImageCms.createProfile("LAB", 5000)
ImageCms.createProfile("LAB", 6500)
def test_simple_lab(self):
i = Image.new('RGB', (10, 10), (128, 128, 128))
pLab = ImageCms.createProfile("LAB")
t = ImageCms.buildTransform(SRGB, pLab, "RGB", "LAB")
i_lab = ImageCms.applyTransform(i, t)
self.assertEqual(i_lab.mode, 'LAB')
k = i_lab.getpixel((0, 0))
# not a linear luminance map. so L != 128:
self.assertEqual(k, (137, 128, 128))
L = i_lab.getdata(0)
a = i_lab.getdata(1)
b = i_lab.getdata(2)
self.assertEqual(list(L), [137] * 100)
self.assertEqual(list(a), [128] * 100)
self.assertEqual(list(b), [128] * 100)
def test_lab_color(self):
pLab = ImageCms.createProfile("LAB")
t = ImageCms.buildTransform(SRGB, pLab, "RGB", "LAB")
# Need to add a type mapping for some PIL type to TYPE_Lab_8 in
# findLCMSType, and have that mapping work back to a PIL mode
# (likely RGB).
i = ImageCms.applyTransform(lena(), t)
self.assert_image(i, "LAB", (128, 128))
# i.save('temp.lab.tif') # visually verified vs PS.
target = Image.open('Tests/images/lena.Lab.tif')
self.assert_image_similar(i, target, 30)
def test_lab_srgb(self):
pLab = ImageCms.createProfile("LAB")
t = ImageCms.buildTransform(pLab, SRGB, "LAB", "RGB")
img = Image.open('Tests/images/lena.Lab.tif')
img_srgb = ImageCms.applyTransform(img, t)
# img_srgb.save('temp.srgb.tif') # visually verified vs ps.
self.assert_image_similar(lena(), img_srgb, 30)
def test_lab_roundtrip(self):
# check to see if we're at least internally consistent.
pLab = ImageCms.createProfile("LAB")
t = ImageCms.buildTransform(SRGB, pLab, "RGB", "LAB")
t2 = ImageCms.buildTransform(pLab, SRGB, "LAB", "RGB")
i = ImageCms.applyTransform(lena(), t)
out = ImageCms.applyTransform(i, t2)
self.assert_image_similar(lena(), out, 2)
def test_display_profile(): if __name__ == '__main__':
# try fetching the profile for the current display device unittest.main()
assert_no_exception(lambda: ImageCms.get_display_profile())
def test_lab_color_profile():
pLab = ImageCms.createProfile("LAB", 5000)
pLab = ImageCms.createProfile("LAB", 6500)
def test_simple_lab():
i = Image.new('RGB', (10,10), (128,128,128))
pLab = ImageCms.createProfile("LAB")
t = ImageCms.buildTransform(SRGB, pLab, "RGB", "LAB")
i_lab = ImageCms.applyTransform(i, t)
assert_equal(i_lab.mode, 'LAB')
k = i_lab.getpixel((0,0))
assert_equal(k, (137,128,128)) # not a linear luminance map. so L != 128
L = i_lab.getdata(0)
a = i_lab.getdata(1)
b = i_lab.getdata(2)
assert_equal(list(L), [137]*100)
assert_equal(list(a), [128]*100)
assert_equal(list(b), [128]*100)
def test_lab_color():
pLab = ImageCms.createProfile("LAB")
t = ImageCms.buildTransform(SRGB, pLab, "RGB", "LAB")
# need to add a type mapping for some PIL type to TYPE_Lab_8 in findLCMSType,
# and have that mapping work back to a PIL mode. (likely RGB)
i = ImageCms.applyTransform(lena(), t)
assert_image(i, "LAB", (128, 128))
# i.save('temp.lab.tif') # visually verified vs PS.
target = Image.open('Tests/images/lena.Lab.tif')
assert_image_similar(i, target, 30)
def test_lab_srgb():
pLab = ImageCms.createProfile("LAB")
t = ImageCms.buildTransform(pLab, SRGB, "LAB", "RGB")
img = Image.open('Tests/images/lena.Lab.tif')
img_srgb = ImageCms.applyTransform(img, t)
# img_srgb.save('temp.srgb.tif') # visually verified vs ps.
assert_image_similar(lena(), img_srgb, 30)
def test_lab_roundtrip():
# check to see if we're at least internally consistent.
pLab = ImageCms.createProfile("LAB")
t = ImageCms.buildTransform(SRGB, pLab, "RGB", "LAB")
t2 = ImageCms.buildTransform(pLab, SRGB, "LAB", "RGB")
i = ImageCms.applyTransform(lena(), t)
out = ImageCms.applyTransform(i, t2)
assert_image_similar(lena(), out, 2)
# End of file

View File

@ -1,54 +1,71 @@
from tester import * from helper import unittest, PillowTestCase, tearDownModule
from PIL import Image from PIL import Image
from PIL import ImageColor from PIL import ImageColor
# --------------------------------------------------------------------
# sanity
assert_equal((255, 0, 0), ImageColor.getrgb("#f00")) class TestImageColor(PillowTestCase):
assert_equal((255, 0, 0), ImageColor.getrgb("#ff0000"))
assert_equal((255, 0, 0), ImageColor.getrgb("rgb(255,0,0)"))
assert_equal((255, 0, 0), ImageColor.getrgb("rgb(255, 0, 0)"))
assert_equal((255, 0, 0), ImageColor.getrgb("rgb(100%,0%,0%)"))
assert_equal((255, 0, 0), ImageColor.getrgb("hsl(0, 100%, 50%)"))
assert_equal((255, 0, 0, 0), ImageColor.getrgb("rgba(255,0,0,0)"))
assert_equal((255, 0, 0, 0), ImageColor.getrgb("rgba(255, 0, 0, 0)"))
assert_equal((255, 0, 0), ImageColor.getrgb("red"))
# -------------------------------------------------------------------- def test_sanity(self):
# look for rounding errors (based on code by Tim Hatch) self.assertEqual((255, 0, 0), ImageColor.getrgb("#f00"))
self.assertEqual((255, 0, 0), ImageColor.getrgb("#ff0000"))
self.assertEqual((255, 0, 0), ImageColor.getrgb("rgb(255,0,0)"))
self.assertEqual((255, 0, 0), ImageColor.getrgb("rgb(255, 0, 0)"))
self.assertEqual((255, 0, 0), ImageColor.getrgb("rgb(100%,0%,0%)"))
self.assertEqual((255, 0, 0), ImageColor.getrgb("hsl(0, 100%, 50%)"))
self.assertEqual((255, 0, 0, 0), ImageColor.getrgb("rgba(255,0,0,0)"))
self.assertEqual(
(255, 0, 0, 0), ImageColor.getrgb("rgba(255, 0, 0, 0)"))
self.assertEqual((255, 0, 0), ImageColor.getrgb("red"))
for color in list(ImageColor.colormap.keys()): # look for rounding errors (based on code by Tim Hatch)
expected = Image.new("RGB", (1, 1), color).convert("L").getpixel((0, 0)) def test_rounding_errors(self):
actual = Image.new("L", (1, 1), color).getpixel((0, 0))
assert_equal(expected, actual)
assert_equal((0, 0, 0), ImageColor.getcolor("black", "RGB")) for color in list(ImageColor.colormap.keys()):
assert_equal((255, 255, 255), ImageColor.getcolor("white", "RGB")) expected = Image.new(
assert_equal((0, 255, 115), ImageColor.getcolor("rgba(0, 255, 115, 33)", "RGB")) "RGB", (1, 1), color).convert("L").getpixel((0, 0))
Image.new("RGB", (1, 1), "white") actual = Image.new("L", (1, 1), color).getpixel((0, 0))
self.assertEqual(expected, actual)
assert_equal((0, 0, 0, 255), ImageColor.getcolor("black", "RGBA")) self.assertEqual((0, 0, 0), ImageColor.getcolor("black", "RGB"))
assert_equal((255, 255, 255, 255), ImageColor.getcolor("white", "RGBA")) self.assertEqual((255, 255, 255), ImageColor.getcolor("white", "RGB"))
assert_equal((0, 255, 115, 33), ImageColor.getcolor("rgba(0, 255, 115, 33)", "RGBA")) self.assertEqual(
Image.new("RGBA", (1, 1), "white") (0, 255, 115), ImageColor.getcolor("rgba(0, 255, 115, 33)", "RGB"))
Image.new("RGB", (1, 1), "white")
assert_equal(0, ImageColor.getcolor("black", "L")) self.assertEqual((0, 0, 0, 255), ImageColor.getcolor("black", "RGBA"))
assert_equal(255, ImageColor.getcolor("white", "L")) self.assertEqual(
assert_equal(162, ImageColor.getcolor("rgba(0, 255, 115, 33)", "L")) (255, 255, 255, 255), ImageColor.getcolor("white", "RGBA"))
Image.new("L", (1, 1), "white") self.assertEqual(
(0, 255, 115, 33),
ImageColor.getcolor("rgba(0, 255, 115, 33)", "RGBA"))
Image.new("RGBA", (1, 1), "white")
assert_equal(0, ImageColor.getcolor("black", "1")) self.assertEqual(0, ImageColor.getcolor("black", "L"))
assert_equal(255, ImageColor.getcolor("white", "1")) self.assertEqual(255, ImageColor.getcolor("white", "L"))
# The following test is wrong, but is current behavior self.assertEqual(
# The correct result should be 255 due to the mode 1 162, ImageColor.getcolor("rgba(0, 255, 115, 33)", "L"))
assert_equal(162, ImageColor.getcolor("rgba(0, 255, 115, 33)", "1")) Image.new("L", (1, 1), "white")
# Correct behavior
# assert_equal(255, ImageColor.getcolor("rgba(0, 255, 115, 33)", "1"))
Image.new("1", (1, 1), "white")
assert_equal((0, 255), ImageColor.getcolor("black", "LA")) self.assertEqual(0, ImageColor.getcolor("black", "1"))
assert_equal((255, 255), ImageColor.getcolor("white", "LA")) self.assertEqual(255, ImageColor.getcolor("white", "1"))
assert_equal((162, 33), ImageColor.getcolor("rgba(0, 255, 115, 33)", "LA")) # The following test is wrong, but is current behavior
Image.new("LA", (1, 1), "white") # The correct result should be 255 due to the mode 1
self.assertEqual(
162, ImageColor.getcolor("rgba(0, 255, 115, 33)", "1"))
# Correct behavior
# self.assertEqual(
# 255, ImageColor.getcolor("rgba(0, 255, 115, 33)", "1"))
Image.new("1", (1, 1), "white")
self.assertEqual((0, 255), ImageColor.getcolor("black", "LA"))
self.assertEqual((255, 255), ImageColor.getcolor("white", "LA"))
self.assertEqual(
(162, 33), ImageColor.getcolor("rgba(0, 255, 115, 33)", "LA"))
Image.new("LA", (1, 1), "white")
if __name__ == '__main__':
unittest.main()
# End of file

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