mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-07-15 02:32:29 +03:00
Merge pull request #2985 from Metallicow/trim-trailing-space
Trim trailing whitespace
This commit is contained in:
commit
4936b447f0
|
@ -16,7 +16,7 @@ logger = logging.getLogger(__name__)
|
||||||
HAS_UPLOADER = False
|
HAS_UPLOADER = False
|
||||||
|
|
||||||
if os.environ.get('SHOW_ERRORS', None):
|
if os.environ.get('SHOW_ERRORS', None):
|
||||||
# local img.show for errors.
|
# local img.show for errors.
|
||||||
HAS_UPLOADER=True
|
HAS_UPLOADER=True
|
||||||
class test_image_results:
|
class test_image_results:
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -119,7 +119,7 @@ class PillowTestCase(unittest.TestCase):
|
||||||
if mode:
|
if mode:
|
||||||
img = img.convert(mode)
|
img = img.convert(mode)
|
||||||
self.assert_image_equal(a, img, msg)
|
self.assert_image_equal(a, img, msg)
|
||||||
|
|
||||||
def assert_image_similar(self, a, b, epsilon, msg=None):
|
def assert_image_similar(self, a, b, epsilon, msg=None):
|
||||||
epsilon = float(epsilon)
|
epsilon = float(epsilon)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
|
|
|
@ -80,7 +80,7 @@ class TestFileSgi(PillowTestCase):
|
||||||
|
|
||||||
reloaded = Image.open(out)
|
reloaded = Image.open(out)
|
||||||
self.assert_image_equal(im, reloaded)
|
self.assert_image_equal(im, reloaded)
|
||||||
|
|
||||||
def test_unsupported_mode(self):
|
def test_unsupported_mode(self):
|
||||||
im = hopper('LA')
|
im = hopper('LA')
|
||||||
out = self.tempfile('temp.sgi')
|
out = self.tempfile('temp.sgi')
|
||||||
|
|
|
@ -70,7 +70,7 @@ class TestFileTiffMetadata(PillowTestCase):
|
||||||
self.assertAlmostEqual(loaded_double, doubledata)
|
self.assertAlmostEqual(loaded_double, doubledata)
|
||||||
|
|
||||||
# check with 2 element ImageJMetaDataByteCounts, issue #2006
|
# check with 2 element ImageJMetaDataByteCounts, issue #2006
|
||||||
|
|
||||||
info[ImageJMetaDataByteCounts] = (8, len(bindata) - 8)
|
info[ImageJMetaDataByteCounts] = (8, len(bindata) - 8)
|
||||||
img.save(f, tiffinfo=info)
|
img.save(f, tiffinfo=info)
|
||||||
loaded = Image.open(f)
|
loaded = Image.open(f)
|
||||||
|
|
|
@ -14,7 +14,7 @@ class TestTTypeFontLeak(PillowLeakTestCase):
|
||||||
draw = ImageDraw.ImageDraw(im)
|
draw = ImageDraw.ImageDraw(im)
|
||||||
self._test_leak(lambda: draw.text((0, 0), "some text "*1024, #~10k
|
self._test_leak(lambda: draw.text((0, 0), "some text "*1024, #~10k
|
||||||
font=font, fill="black"))
|
font=font, fill="black"))
|
||||||
|
|
||||||
@unittest.skipIf(not features.check('freetype2'), "Test requires freetype2")
|
@unittest.skipIf(not features.check('freetype2'), "Test requires freetype2")
|
||||||
def test_leak(self):
|
def test_leak(self):
|
||||||
ttype = ImageFont.truetype('Tests/fonts/FreeMono.ttf', 20)
|
ttype = ImageFont.truetype('Tests/fonts/FreeMono.ttf', 20)
|
||||||
|
@ -24,7 +24,7 @@ class TestDefaultFontLeak(TestTTypeFontLeak):
|
||||||
# fails at iteration 37 in master
|
# fails at iteration 37 in master
|
||||||
iterations = 100
|
iterations = 100
|
||||||
mem_limit = 1024 #k
|
mem_limit = 1024 #k
|
||||||
|
|
||||||
def test_leak(self):
|
def test_leak(self):
|
||||||
default_font = ImageFont.load_default()
|
default_font = ImageFont.load_default()
|
||||||
self._test_font(default_font)
|
self._test_font(default_font)
|
||||||
|
|
|
@ -51,7 +51,7 @@ class TestFontPcf(PillowTestCase):
|
||||||
draw.text((0, 0), message, 'black', font=font)
|
draw.text((0, 0), message, 'black', font=font)
|
||||||
with Image.open('Tests/images/test_draw_pbm_target.png') as target:
|
with Image.open('Tests/images/test_draw_pbm_target.png') as target:
|
||||||
self.assert_image_similar(im, target, 0)
|
self.assert_image_similar(im, target, 0)
|
||||||
|
|
||||||
def test_textsize(self):
|
def test_textsize(self):
|
||||||
tempname = self.save_font()
|
tempname = self.save_font()
|
||||||
font = ImageFont.load(tempname)
|
font = ImageFont.load(tempname)
|
||||||
|
|
|
@ -89,7 +89,7 @@ class TestImageConvert(PillowTestCase):
|
||||||
self.assertNotIn('transparency', rgba.info)
|
self.assertNotIn('transparency', rgba.info)
|
||||||
# https://github.com/python-pillow/Pillow/issues/2702
|
# https://github.com/python-pillow/Pillow/issues/2702
|
||||||
self.assertEqual(rgba.palette, None)
|
self.assertEqual(rgba.palette, None)
|
||||||
|
|
||||||
|
|
||||||
def test_trns_l(self):
|
def test_trns_l(self):
|
||||||
im = hopper('L')
|
im = hopper('L')
|
||||||
|
|
|
@ -15,8 +15,8 @@ class TestImagecomplextext(PillowTestCase):
|
||||||
im = Image.new(mode='RGB', size=(300, 100))
|
im = Image.new(mode='RGB', size=(300, 100))
|
||||||
draw = ImageDraw.Draw(im)
|
draw = ImageDraw.Draw(im)
|
||||||
draw.text((0, 0), 'TEST', font=ttf, fill=500, direction='ltr')
|
draw.text((0, 0), 'TEST', font=ttf, fill=500, direction='ltr')
|
||||||
|
|
||||||
|
|
||||||
def test_complex_text(self):
|
def test_complex_text(self):
|
||||||
ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
|
ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ class TestImagecomplextext(PillowTestCase):
|
||||||
|
|
||||||
liga_size = ttf.getsize('fi', features=['-liga'])
|
liga_size = ttf.getsize('fi', features=['-liga'])
|
||||||
self.assertEqual(liga_size,(13,19))
|
self.assertEqual(liga_size,(13,19))
|
||||||
|
|
||||||
def test_kerning_features(self):
|
def test_kerning_features(self):
|
||||||
ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
|
ttf = ImageFont.truetype(FONT_PATH, FONT_SIZE)
|
||||||
|
|
||||||
|
|
|
@ -168,10 +168,10 @@ Instances of the :py:class:`Image` class have the following attributes:
|
||||||
|
|
||||||
.. py:attribute:: filename
|
.. py:attribute:: filename
|
||||||
|
|
||||||
The filename or path of the source file. Only images created with the
|
The filename or path of the source file. Only images created with the
|
||||||
factory function `open` have a filename attribute. If the input is a
|
factory function `open` have a filename attribute. If the input is a
|
||||||
file like object, the filename attribute is set to an empty string.
|
file like object, the filename attribute is set to an empty string.
|
||||||
|
|
||||||
:type: :py:class: `string`
|
:type: :py:class: `string`
|
||||||
|
|
||||||
.. py:attribute:: format
|
.. py:attribute:: format
|
||||||
|
|
|
@ -40,8 +40,8 @@ variables:
|
||||||
|
|
||||||
* ``PILLOW_BLOCK_SIZE``, in bytes, K, or M. Specifies the maximum
|
* ``PILLOW_BLOCK_SIZE``, in bytes, K, or M. Specifies the maximum
|
||||||
block size for ``ImagingAllocateArray``. Valid values are
|
block size for ``ImagingAllocateArray``. Valid values are
|
||||||
integers, with an optional `k` or `m` suffix. Defaults to 16M.
|
integers, with an optional `k` or `m` suffix. Defaults to 16M.
|
||||||
|
|
||||||
* ``PILLOW_BLOCKS_MAX`` Specifies the number of freed blocks to
|
* ``PILLOW_BLOCKS_MAX`` Specifies the number of freed blocks to
|
||||||
retain to fill future memory requests. Any freed blocks over this
|
retain to fill future memory requests. Any freed blocks over this
|
||||||
threshold will be returned to the OS immediately. Defaults to 0.
|
threshold will be returned to the OS immediately. Defaults to 0.
|
||||||
|
|
|
@ -3,8 +3,8 @@ Internal Reference Docs
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
|
||||||
open_files
|
open_files
|
||||||
limits
|
limits
|
||||||
block_allocator
|
block_allocator
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ File Handling in Pillow
|
||||||
When opening a file as an image, Pillow requires a filename,
|
When opening a file as an image, Pillow requires a filename,
|
||||||
pathlib.Path object, or a file-like object. Pillow uses the filename
|
pathlib.Path object, or a file-like object. Pillow uses the filename
|
||||||
or Path to open a file, so for the rest of this article, they will all
|
or Path to open a file, so for the rest of this article, they will all
|
||||||
be treated as a file-like object.
|
be treated as a file-like object.
|
||||||
|
|
||||||
The first four of these items are equivalent, the last is dangerous
|
The first four of these items are equivalent, the last is dangerous
|
||||||
and may fail::
|
and may fail::
|
||||||
|
@ -12,14 +12,14 @@ and may fail::
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
import io
|
import io
|
||||||
import pathlib
|
import pathlib
|
||||||
|
|
||||||
im = Image.open('test.jpg')
|
im = Image.open('test.jpg')
|
||||||
|
|
||||||
im2 = Image.open(pathlib.Path('test.jpg'))
|
im2 = Image.open(pathlib.Path('test.jpg'))
|
||||||
|
|
||||||
f = open('test.jpg', 'rb')
|
f = open('test.jpg', 'rb')
|
||||||
im3 = Image.open(f)
|
im3 = Image.open(f)
|
||||||
|
|
||||||
with open('test.jpg', 'rb') as f:
|
with open('test.jpg', 'rb') as f:
|
||||||
im4 = Image.open(io.BytesIO(f.read()))
|
im4 = Image.open(io.BytesIO(f.read()))
|
||||||
|
|
||||||
|
@ -31,10 +31,10 @@ and may fail::
|
||||||
The documentation specifies that the file will be closed after the
|
The documentation specifies that the file will be closed after the
|
||||||
``Image.Image.load()`` method is called. This is an aspirational
|
``Image.Image.load()`` method is called. This is an aspirational
|
||||||
specification rather than an accurate reflection of the state of the
|
specification rather than an accurate reflection of the state of the
|
||||||
code.
|
code.
|
||||||
|
|
||||||
Pillow cannot in general close and reopen a file, so any access to
|
Pillow cannot in general close and reopen a file, so any access to
|
||||||
that file needs to be prior to the close.
|
that file needs to be prior to the close.
|
||||||
|
|
||||||
Issues
|
Issues
|
||||||
------
|
------
|
||||||
|
@ -44,10 +44,10 @@ The current open file handling is inconsistent at best:
|
||||||
* Most of the image plugins do not close the input file.
|
* Most of the image plugins do not close the input file.
|
||||||
* Multi-frame images behave badly when seeking through the file, as
|
* Multi-frame images behave badly when seeking through the file, as
|
||||||
it's legal to seek backward in the file until the last image is
|
it's legal to seek backward in the file until the last image is
|
||||||
read, and then it's not.
|
read, and then it's not.
|
||||||
* Using the file context manager to provide a file-like object to
|
* Using the file context manager to provide a file-like object to
|
||||||
Pillow is dangerous unless the context of the image is limited to
|
Pillow is dangerous unless the context of the image is limited to
|
||||||
the context of the file.
|
the context of the file.
|
||||||
|
|
||||||
Image Lifecycle
|
Image Lifecycle
|
||||||
---------------
|
---------------
|
||||||
|
@ -59,7 +59,7 @@ Image Lifecycle
|
||||||
* ``Image.Image.load()`` when the pixel data from the image is
|
* ``Image.Image.load()`` when the pixel data from the image is
|
||||||
required, ``load()`` is called. The current frame is read into
|
required, ``load()`` is called. The current frame is read into
|
||||||
memory. The image can now be used independently of the underlying
|
memory. The image can now be used independently of the underlying
|
||||||
image file.
|
image file.
|
||||||
|
|
||||||
* ``Image.Image.seek()`` in the case of multi-frame images
|
* ``Image.Image.seek()`` in the case of multi-frame images
|
||||||
(e.g. multipage TIFF and animated GIF) the image file left open so
|
(e.g. multipage TIFF and animated GIF) the image file left open so
|
||||||
|
@ -72,12 +72,12 @@ Image Lifecycle
|
||||||
support. e.g.::
|
support. e.g.::
|
||||||
|
|
||||||
with Image.open('test.jpg') as img:
|
with Image.open('test.jpg') as img:
|
||||||
... # image operations here.
|
... # image operations here.
|
||||||
|
|
||||||
|
|
||||||
The lifecycle of a single frame image is relatively simple. The file
|
The lifecycle of a single frame image is relatively simple. The file
|
||||||
must remain open until the ``load()`` or ``close()`` function is
|
must remain open until the ``load()`` or ``close()`` function is
|
||||||
called.
|
called.
|
||||||
|
|
||||||
Multi-frame images are more complicated. The ``load()`` method is not
|
Multi-frame images are more complicated. The ``load()`` method is not
|
||||||
a terminal method, so it should not close the underlying file. The
|
a terminal method, so it should not close the underlying file. The
|
||||||
|
@ -85,7 +85,7 @@ current behavior of ``seek()`` closing the underlying file on
|
||||||
accessing the last frame is presumably a heuristic for closing the
|
accessing the last frame is presumably a heuristic for closing the
|
||||||
file after iterating through the entire sequence. In general, Pillow
|
file after iterating through the entire sequence. In general, Pillow
|
||||||
does not know if there are going to be any requests for additional
|
does not know if there are going to be any requests for additional
|
||||||
data until the caller has explicitly closed the image.
|
data until the caller has explicitly closed the image.
|
||||||
|
|
||||||
|
|
||||||
Complications
|
Complications
|
||||||
|
@ -94,7 +94,7 @@ Complications
|
||||||
* TiffImagePlugin has some code to pass the underlying file descriptor
|
* TiffImagePlugin has some code to pass the underlying file descriptor
|
||||||
into libtiff (if working on an actual file). Since libtiff closes
|
into libtiff (if working on an actual file). Since libtiff closes
|
||||||
the file descriptor internally, it is duplicated prior to passing it
|
the file descriptor internally, it is duplicated prior to passing it
|
||||||
into libtiff.
|
into libtiff.
|
||||||
|
|
||||||
* ``decoder.handles_eof`` This slightly misnamed flag indicates that
|
* ``decoder.handles_eof`` This slightly misnamed flag indicates that
|
||||||
the decoder wants to be called with a 0 length buffer when reads are
|
the decoder wants to be called with a 0 length buffer when reads are
|
||||||
|
@ -118,8 +118,8 @@ Proposed File Handling
|
||||||
* ``Image.Image.load()`` should close the image file, unless there are
|
* ``Image.Image.load()`` should close the image file, unless there are
|
||||||
multiple frames.
|
multiple frames.
|
||||||
|
|
||||||
* ``Image.Image.seek()`` should never close the image file.
|
* ``Image.Image.seek()`` should never close the image file.
|
||||||
|
|
||||||
* Users of the library should call ``Image.Image.close()`` on any
|
* Users of the library should call ``Image.Image.close()`` on any
|
||||||
multi-frame image to ensure that the underlying file is closed.
|
multi-frame image to ensure that the underlying file is closed.
|
||||||
|
|
||||||
|
|
|
@ -23,17 +23,17 @@ redirected to the olefile package. Direct accesses to
|
||||||
``PIL.OlefileIO`` raises a deprecation warning, then patches the
|
``PIL.OlefileIO`` raises a deprecation warning, then patches the
|
||||||
upstream olefile into ``sys.modules`` in its place.
|
upstream olefile into ``sys.modules`` in its place.
|
||||||
|
|
||||||
SGI image save
|
SGI image save
|
||||||
==============
|
==============
|
||||||
|
|
||||||
It is now possible to save images in modes ``L``, ``RGB``, and
|
It is now possible to save images in modes ``L``, ``RGB``, and
|
||||||
``RGBA`` to the uncompressed SGI image format.
|
``RGBA`` to the uncompressed SGI image format.
|
||||||
|
|
||||||
Zero sized images
|
Zero sized images
|
||||||
=================
|
=================
|
||||||
|
|
||||||
Pillow 3.4.0 removed support for creating images with (0,0) size. This
|
Pillow 3.4.0 removed support for creating images with (0,0) size. This
|
||||||
has been reenabled, restoring pre 3.4 behavior.
|
has been reenabled, restoring pre 3.4 behavior.
|
||||||
|
|
||||||
Internal handles_eof flag
|
Internal handles_eof flag
|
||||||
=========================
|
=========================
|
||||||
|
@ -41,11 +41,11 @@ Internal handles_eof flag
|
||||||
The ``handles_eof flag`` for decoding images has been removed, as there
|
The ``handles_eof flag`` for decoding images has been removed, as there
|
||||||
were no internal users of the flag. Anyone maintaining image decoders
|
were no internal users of the flag. Anyone maintaining image decoders
|
||||||
outside of the Pillow source tree should consider using the cleanup
|
outside of the Pillow source tree should consider using the cleanup
|
||||||
function pointers instead.
|
function pointers instead.
|
||||||
|
|
||||||
Image.core.stretch removed
|
Image.core.stretch removed
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
The stretch function on the core image object has been removed. This
|
The stretch function on the core image object has been removed. This
|
||||||
used to be for enlarging the image, but has been aliased to resize
|
used to be for enlarging the image, but has been aliased to resize
|
||||||
recently.
|
recently.
|
||||||
|
|
|
@ -12,7 +12,7 @@ Several deprecated items have been removed.
|
||||||
|
|
||||||
* The methods :py:meth:`PIL.ImageDraw.ImageDraw.setink`,
|
* The methods :py:meth:`PIL.ImageDraw.ImageDraw.setink`,
|
||||||
:py:meth:`PIL.ImageDraw.ImageDraw.setfill`, and
|
:py:meth:`PIL.ImageDraw.ImageDraw.setfill`, and
|
||||||
:py:meth:`PIL.ImageDraw.ImageDraw.setfont` have been removed.
|
:py:meth:`PIL.ImageDraw.ImageDraw.setfont` have been removed.
|
||||||
|
|
||||||
|
|
||||||
Closing Files When Opening Images
|
Closing Files When Opening Images
|
||||||
|
@ -27,7 +27,7 @@ is specified:
|
||||||
responsibility of the calling code to close the file.
|
responsibility of the calling code to close the file.
|
||||||
|
|
||||||
* For images where Pillow opens the file and the file is known to have
|
* For images where Pillow opens the file and the file is known to have
|
||||||
only one frame, the file is closed after loading.
|
only one frame, the file is closed after loading.
|
||||||
|
|
||||||
* If the file has more than one frame, or if it can't be determined,
|
* If the file has more than one frame, or if it can't be determined,
|
||||||
then the file is left open to permit seeking to subsequent
|
then the file is left open to permit seeking to subsequent
|
||||||
|
@ -36,7 +36,7 @@ is specified:
|
||||||
|
|
||||||
* If the image is memory mapped, then we can't close the mapping to
|
* If the image is memory mapped, then we can't close the mapping to
|
||||||
the underlying file until we are done with the image. The mapping
|
the underlying file until we are done with the image. The mapping
|
||||||
will be closed in the ``close`` or ``__del__`` method.
|
will be closed in the ``close`` or ``__del__`` method.
|
||||||
|
|
||||||
|
|
||||||
Changes to GIF Handling When Saving
|
Changes to GIF Handling When Saving
|
||||||
|
@ -50,7 +50,7 @@ saving images. There are two external changes that arise from this:
|
||||||
|
|
||||||
* The image to be saved is no longer modified in place by any of the
|
* The image to be saved is no longer modified in place by any of the
|
||||||
operations of the save function. Previously it was modified when
|
operations of the save function. Previously it was modified when
|
||||||
optimizing the image palette.
|
optimizing the image palette.
|
||||||
|
|
||||||
This refactor fixed some bugs with palette handling when saving
|
This refactor fixed some bugs with palette handling when saving
|
||||||
multiple frame GIFs.
|
multiple frame GIFs.
|
||||||
|
@ -60,7 +60,7 @@ New Method: Image.remap_palette
|
||||||
|
|
||||||
The method :py:meth:`PIL.Image.Image.remap_palette()` has been
|
The method :py:meth:`PIL.Image.Image.remap_palette()` has been
|
||||||
added. This method was hoisted from the GifImagePlugin code used to
|
added. This method was hoisted from the GifImagePlugin code used to
|
||||||
optimize the palette.
|
optimize the palette.
|
||||||
|
|
||||||
Added Decoder Registry and Support for Python Based Decoders
|
Added Decoder Registry and Support for Python Based Decoders
|
||||||
============================================================
|
============================================================
|
||||||
|
@ -76,7 +76,7 @@ Tests
|
||||||
=====
|
=====
|
||||||
|
|
||||||
Many tests have been added, including correctness tests for image
|
Many tests have been added, including correctness tests for image
|
||||||
formats that have been previously untested.
|
formats that have been previously untested.
|
||||||
|
|
||||||
We are now running automated tests in Docker containers against more
|
We are now running automated tests in Docker containers against more
|
||||||
Linux versions than are provided on Travis CI, which is currently
|
Linux versions than are provided on Travis CI, which is currently
|
||||||
|
|
|
@ -20,7 +20,7 @@ TIFF Metadata Changes
|
||||||
single element tuple. This is only with the new api, not the legacy
|
single element tuple. This is only with the new api, not the legacy
|
||||||
api. This normalizes the handling of fields, so that the metadata
|
api. This normalizes the handling of fields, so that the metadata
|
||||||
with inferred or image specified counts are handled the same as
|
with inferred or image specified counts are handled the same as
|
||||||
metadata with count specified in the TIFF spec.
|
metadata with count specified in the TIFF spec.
|
||||||
* The ``PhotoshopInfo``, ``XMP``, and ``JPEGTables`` tags now have a
|
* The ``PhotoshopInfo``, ``XMP``, and ``JPEGTables`` tags now have a
|
||||||
defined type (bytes) and a count of 1.
|
defined type (bytes) and a count of 1.
|
||||||
* The ``ImageJMetaDataByteCounts`` tag now has an arbitrary number of
|
* The ``ImageJMetaDataByteCounts`` tag now has an arbitrary number of
|
||||||
|
@ -85,7 +85,7 @@ There is a new :py:class:`PIL.ImageFilter.MultibandFilter` base class
|
||||||
for image filters that can run on all channels of an image in one
|
for image filters that can run on all channels of an image in one
|
||||||
operation. The original :py:class:`PIL.ImageFilter.Filter` class
|
operation. The original :py:class:`PIL.ImageFilter.Filter` class
|
||||||
remains for image filters that can process only single band images, or
|
remains for image filters that can process only single band images, or
|
||||||
require splitting of channels prior to filtering.
|
require splitting of channels prior to filtering.
|
||||||
|
|
||||||
Other Changes
|
Other Changes
|
||||||
=============
|
=============
|
||||||
|
@ -109,7 +109,7 @@ images to and from RGB and RGBA formats. The image data is truncated
|
||||||
to 8-bit precision.
|
to 8-bit precision.
|
||||||
|
|
||||||
Pillow can now read RLE encoded SGI images in both 8 and 16-bit
|
Pillow can now read RLE encoded SGI images in both 8 and 16-bit
|
||||||
precision.
|
precision.
|
||||||
|
|
||||||
Performance
|
Performance
|
||||||
^^^^^^^^^^^
|
^^^^^^^^^^^
|
||||||
|
@ -124,7 +124,7 @@ This release contains several performance improvements:
|
||||||
* ``Image.transpose`` has been accelerated 15% or more by using a cache
|
* ``Image.transpose`` has been accelerated 15% or more by using a cache
|
||||||
friendly algorithm.
|
friendly algorithm.
|
||||||
* ImageFilters based on Kernel convolution are significantly faster
|
* ImageFilters based on Kernel convolution are significantly faster
|
||||||
due to the new MultibandFilter feature.
|
due to the new MultibandFilter feature.
|
||||||
* All memory allocation for images is now done in blocks, rather than
|
* All memory allocation for images is now done in blocks, rather than
|
||||||
falling back to an allocation for each scan line for images larger
|
falling back to an allocation for each scan line for images larger
|
||||||
than the block size.
|
than the block size.
|
||||||
|
|
|
@ -69,7 +69,7 @@ GIF Disposal
|
||||||
^^^^^^^^^^^^
|
^^^^^^^^^^^^
|
||||||
|
|
||||||
Multiframe GIF images now take an optional disposal parameter to
|
Multiframe GIF images now take an optional disposal parameter to
|
||||||
specify the disposal option for changed pixels.
|
specify the disposal option for changed pixels.
|
||||||
|
|
||||||
Other Changes
|
Other Changes
|
||||||
=============
|
=============
|
||||||
|
@ -88,7 +88,7 @@ Libraqm is now Dynamically Linked
|
||||||
The libraqm dependency for complex text scripts is now linked
|
The libraqm dependency for complex text scripts is now linked
|
||||||
dynamically at runtime rather than at packaging time. This allows us
|
dynamically at runtime rather than at packaging time. This allows us
|
||||||
to release binaries with support for libraqm if it is installed on the
|
to release binaries with support for libraqm if it is installed on the
|
||||||
user's machine.
|
user's machine.
|
||||||
|
|
||||||
Source Layout Changes
|
Source Layout Changes
|
||||||
^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
@ -42,7 +42,7 @@ class DcxImageFile(PcxImageFile):
|
||||||
format = "DCX"
|
format = "DCX"
|
||||||
format_description = "Intel DCX"
|
format_description = "Intel DCX"
|
||||||
_close_exclusive_fp_after_loading = False
|
_close_exclusive_fp_after_loading = False
|
||||||
|
|
||||||
def _open(self):
|
def _open(self):
|
||||||
|
|
||||||
# Header
|
# Header
|
||||||
|
|
|
@ -278,7 +278,7 @@ class BitmapImage(object):
|
||||||
|
|
||||||
def getimage(photo):
|
def getimage(photo):
|
||||||
""" This function is unimplemented """
|
""" This function is unimplemented """
|
||||||
|
|
||||||
"""Copies the contents of a PhotoImage to a PIL image memory."""
|
"""Copies the contents of a PhotoImage to a PIL image memory."""
|
||||||
photo.tk.call("PyImagingPhotoGet", photo)
|
photo.tk.call("PyImagingPhotoGet", photo)
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ class MpoImageFile(JpegImagePlugin.JpegImageFile):
|
||||||
format = "MPO"
|
format = "MPO"
|
||||||
format_description = "MPO (CIPA DC-007)"
|
format_description = "MPO (CIPA DC-007)"
|
||||||
_close_exclusive_fp_after_loading = False
|
_close_exclusive_fp_after_loading = False
|
||||||
|
|
||||||
def _open(self):
|
def _open(self):
|
||||||
self.fp.seek(0) # prep the fp in order to pass the JPEG test
|
self.fp.seek(0) # prep the fp in order to pass the JPEG test
|
||||||
JpegImagePlugin.JpegImageFile._open(self)
|
JpegImagePlugin.JpegImageFile._open(self)
|
||||||
|
|
|
@ -750,7 +750,7 @@ def _save(im, fp, filename, chunk=putchunk):
|
||||||
name = b"ICC Profile"
|
name = b"ICC Profile"
|
||||||
data = name + b"\0\0" + zlib.compress(icc)
|
data = name + b"\0\0" + zlib.compress(icc)
|
||||||
chunk(fp, b"iCCP", data)
|
chunk(fp, b"iCCP", data)
|
||||||
|
|
||||||
# You must either have sRGB or iCCP.
|
# You must either have sRGB or iCCP.
|
||||||
# Disallow sRGB chunks when an iCCP-chunk has been emitted.
|
# Disallow sRGB chunks when an iCCP-chunk has been emitted.
|
||||||
chunks.remove(b"sRGB")
|
chunks.remove(b"sRGB")
|
||||||
|
|
|
@ -143,7 +143,7 @@ TAGS_V2 = {
|
||||||
342: ("TransferRange", SHORT, 6),
|
342: ("TransferRange", SHORT, 6),
|
||||||
|
|
||||||
347: ("JPEGTables", UNDEFINED, 1),
|
347: ("JPEGTables", UNDEFINED, 1),
|
||||||
|
|
||||||
# obsolete JPEG tags
|
# obsolete JPEG tags
|
||||||
512: ("JPEGProc", SHORT, 1),
|
512: ("JPEGProc", SHORT, 1),
|
||||||
513: ("JPEGInterchangeFormat", LONG, 1),
|
513: ("JPEGInterchangeFormat", LONG, 1),
|
||||||
|
@ -161,7 +161,7 @@ TAGS_V2 = {
|
||||||
532: ("ReferenceBlackWhite", LONG, 0),
|
532: ("ReferenceBlackWhite", LONG, 0),
|
||||||
|
|
||||||
700: ('XMP', BYTE, 1),
|
700: ('XMP', BYTE, 1),
|
||||||
|
|
||||||
33432: ("Copyright", ASCII, 1),
|
33432: ("Copyright", ASCII, 1),
|
||||||
34377: ('PhotoshopInfo', BYTE, 1),
|
34377: ('PhotoshopInfo', BYTE, 1),
|
||||||
|
|
||||||
|
@ -193,7 +193,7 @@ TAGS_V2 = {
|
||||||
|
|
||||||
50741: ("MakerNoteSafety", SHORT, 1, {"Unsafe": 0, "Safe": 1}),
|
50741: ("MakerNoteSafety", SHORT, 1, {"Unsafe": 0, "Safe": 1}),
|
||||||
50780: ("BestQualityScale", RATIONAL, 1),
|
50780: ("BestQualityScale", RATIONAL, 1),
|
||||||
50838: ("ImageJMetaDataByteCounts", LONG, 0), # Can be more than one
|
50838: ("ImageJMetaDataByteCounts", LONG, 0), # Can be more than one
|
||||||
50839: ("ImageJMetaData", UNDEFINED, 1) # see Issue #2006
|
50839: ("ImageJMetaData", UNDEFINED, 1) # see Issue #2006
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1499,11 +1499,11 @@ _resize(ImagingObject* self, PyObject* args)
|
||||||
int xsize, ysize;
|
int xsize, ysize;
|
||||||
int filter = IMAGING_TRANSFORM_NEAREST;
|
int filter = IMAGING_TRANSFORM_NEAREST;
|
||||||
float box[4] = {0, 0, 0, 0};
|
float box[4] = {0, 0, 0, 0};
|
||||||
|
|
||||||
imIn = self->image;
|
imIn = self->image;
|
||||||
box[2] = imIn->xsize;
|
box[2] = imIn->xsize;
|
||||||
box[3] = imIn->ysize;
|
box[3] = imIn->ysize;
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "(ii)|i(ffff)", &xsize, &ysize, &filter,
|
if (!PyArg_ParseTuple(args, "(ii)|i(ffff)", &xsize, &ysize, &filter,
|
||||||
&box[0], &box[1], &box[2], &box[3]))
|
&box[0], &box[1], &box[2], &box[3]))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -3325,7 +3325,7 @@ _reset_stats(PyObject* self, PyObject* args)
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, ":reset_stats"))
|
if (!PyArg_ParseTuple(args, ":reset_stats"))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
arena->stats_new_count = 0;
|
arena->stats_new_count = 0;
|
||||||
arena->stats_allocated_blocks = 0;
|
arena->stats_allocated_blocks = 0;
|
||||||
arena->stats_reused_blocks = 0;
|
arena->stats_reused_blocks = 0;
|
||||||
|
@ -3341,7 +3341,7 @@ _get_alignment(PyObject* self, PyObject* args)
|
||||||
{
|
{
|
||||||
if (!PyArg_ParseTuple(args, ":get_alignment"))
|
if (!PyArg_ParseTuple(args, ":get_alignment"))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return PyInt_FromLong(ImagingDefaultArena.alignment);
|
return PyInt_FromLong(ImagingDefaultArena.alignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3350,7 +3350,7 @@ _get_block_size(PyObject* self, PyObject* args)
|
||||||
{
|
{
|
||||||
if (!PyArg_ParseTuple(args, ":get_block_size"))
|
if (!PyArg_ParseTuple(args, ":get_block_size"))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return PyInt_FromLong(ImagingDefaultArena.block_size);
|
return PyInt_FromLong(ImagingDefaultArena.block_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3359,7 +3359,7 @@ _get_blocks_max(PyObject* self, PyObject* args)
|
||||||
{
|
{
|
||||||
if (!PyArg_ParseTuple(args, ":get_blocks_max"))
|
if (!PyArg_ParseTuple(args, ":get_blocks_max"))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return PyInt_FromLong(ImagingDefaultArena.blocks_max);
|
return PyInt_FromLong(ImagingDefaultArena.blocks_max);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3369,7 +3369,7 @@ _set_alignment(PyObject* self, PyObject* args)
|
||||||
int alignment;
|
int alignment;
|
||||||
if (!PyArg_ParseTuple(args, "i:set_alignment", &alignment))
|
if (!PyArg_ParseTuple(args, "i:set_alignment", &alignment))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (alignment < 1 || alignment > 128) {
|
if (alignment < 1 || alignment > 128) {
|
||||||
PyErr_SetString(PyExc_ValueError, "alignment should be from 1 to 128");
|
PyErr_SetString(PyExc_ValueError, "alignment should be from 1 to 128");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -3392,7 +3392,7 @@ _set_block_size(PyObject* self, PyObject* args)
|
||||||
int block_size;
|
int block_size;
|
||||||
if (!PyArg_ParseTuple(args, "i:set_block_size", &block_size))
|
if (!PyArg_ParseTuple(args, "i:set_block_size", &block_size))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (block_size <= 0) {
|
if (block_size <= 0) {
|
||||||
PyErr_SetString(PyExc_ValueError,
|
PyErr_SetString(PyExc_ValueError,
|
||||||
"block_size should be greater than 0");
|
"block_size should be greater than 0");
|
||||||
|
@ -3417,7 +3417,7 @@ _set_blocks_max(PyObject* self, PyObject* args)
|
||||||
int blocks_max;
|
int blocks_max;
|
||||||
if (!PyArg_ParseTuple(args, "i:set_blocks_max", &blocks_max))
|
if (!PyArg_ParseTuple(args, "i:set_blocks_max", &blocks_max))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (blocks_max < 0) {
|
if (blocks_max < 0) {
|
||||||
PyErr_SetString(PyExc_ValueError,
|
PyErr_SetString(PyExc_ValueError,
|
||||||
"blocks_max should be greater than 0");
|
"blocks_max should be greater than 0");
|
||||||
|
@ -3440,7 +3440,7 @@ _clear_cache(PyObject* self, PyObject* args)
|
||||||
|
|
||||||
if (!PyArg_ParseTuple(args, "|i:clear_cache", &i))
|
if (!PyArg_ParseTuple(args, "|i:clear_cache", &i))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
ImagingMemoryClearCache(&ImagingDefaultArena, i);
|
ImagingMemoryClearCache(&ImagingDefaultArena, i);
|
||||||
|
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
|
|
|
@ -108,7 +108,7 @@ typedef struct {
|
||||||
t_raqm_set_par_direction set_par_direction;
|
t_raqm_set_par_direction set_par_direction;
|
||||||
t_raqm_add_font_feature add_font_feature;
|
t_raqm_add_font_feature add_font_feature;
|
||||||
t_raqm_set_freetype_face set_freetype_face;
|
t_raqm_set_freetype_face set_freetype_face;
|
||||||
t_raqm_layout layout;
|
t_raqm_layout layout;
|
||||||
t_raqm_get_glyphs get_glyphs;
|
t_raqm_get_glyphs get_glyphs;
|
||||||
t_raqm_get_glyphs_01 get_glyphs_01;
|
t_raqm_get_glyphs_01 get_glyphs_01;
|
||||||
t_raqm_destroy destroy;
|
t_raqm_destroy destroy;
|
||||||
|
@ -247,7 +247,7 @@ getfont(PyObject* self_, PyObject* args, PyObject* kw)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kw, "eti|is"PY_ARG_BYTES_LENGTH"i",
|
if (!PyArg_ParseTupleAndKeywords(args, kw, "eti|is"PY_ARG_BYTES_LENGTH"i",
|
||||||
kwlist,
|
kwlist,
|
||||||
Py_FileSystemDefaultEncoding, &filename,
|
Py_FileSystemDefaultEncoding, &filename,
|
||||||
&size, &index, &encoding, &font_bytes,
|
&size, &index, &encoding, &font_bytes,
|
||||||
|
@ -458,7 +458,7 @@ text_layout_raqm(PyObject* string, FontObject* self, const char* dir,
|
||||||
count = 0;
|
count = 0;
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
} else { /* version == 2 */
|
} else { /* version == 2 */
|
||||||
glyphs = (*p_raqm.get_glyphs)(rq, &count);
|
glyphs = (*p_raqm.get_glyphs)(rq, &count);
|
||||||
if (glyphs == NULL) {
|
if (glyphs == NULL) {
|
||||||
PyErr_SetString(PyExc_ValueError, "raqm_get_glyphs() failed.");
|
PyErr_SetString(PyExc_ValueError, "raqm_get_glyphs() failed.");
|
||||||
|
@ -654,7 +654,7 @@ font_getsize(FontObject* self, PyObject* args)
|
||||||
PyMem_Free(glyph_info);
|
PyMem_Free(glyph_info);
|
||||||
glyph_info = NULL;
|
glyph_info = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (face) {
|
if (face) {
|
||||||
|
|
||||||
/* left bearing */
|
/* left bearing */
|
||||||
|
|
|
@ -226,7 +226,7 @@ normalize_coeffs_8bpc(int outSize, int ksize, double *prekk)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ImagingResampleHorizontal_8bpc(Imaging imOut, Imaging imIn, int offset,
|
ImagingResampleHorizontal_8bpc(Imaging imOut, Imaging imIn, int offset,
|
||||||
int ksize, int *bounds, double *prekk)
|
int ksize, int *bounds, double *prekk)
|
||||||
{
|
{
|
||||||
|
|
|
@ -28,7 +28,7 @@ static void read4B(UINT32* dest, UINT8* buf)
|
||||||
static int expandrow(UINT8* dest, UINT8* src, int n, int z)
|
static int expandrow(UINT8* dest, UINT8* src, int n, int z)
|
||||||
{
|
{
|
||||||
UINT8 pixel, count;
|
UINT8 pixel, count;
|
||||||
|
|
||||||
for (;n > 0; n--)
|
for (;n > 0; n--)
|
||||||
{
|
{
|
||||||
pixel = *src++;
|
pixel = *src++;
|
||||||
|
@ -42,7 +42,7 @@ static int expandrow(UINT8* dest, UINT8* src, int n, int z)
|
||||||
*dest = *src++;
|
*dest = *src++;
|
||||||
dest += z;
|
dest += z;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
pixel = *src++;
|
pixel = *src++;
|
||||||
|
@ -51,7 +51,7 @@ static int expandrow(UINT8* dest, UINT8* src, int n, int z)
|
||||||
dest += z;
|
dest += z;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ static int expandrow2(UINT16* dest, UINT16* src, int n, int z)
|
||||||
{
|
{
|
||||||
UINT8 pixel, count;
|
UINT8 pixel, count;
|
||||||
|
|
||||||
|
|
||||||
for (;n > 0; n--)
|
for (;n > 0; n--)
|
||||||
{
|
{
|
||||||
pixel = ((UINT8*)src)[1];
|
pixel = ((UINT8*)src)[1];
|
||||||
|
@ -96,7 +96,7 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
|
||||||
SGISTATE *c;
|
SGISTATE *c;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
/* Get all data from File descriptor */
|
/* Get all data from File descriptor */
|
||||||
c = (SGISTATE*)state->context;
|
c = (SGISTATE*)state->context;
|
||||||
_imaging_seek_pyFd(state->fd, 0L, SEEK_END);
|
_imaging_seek_pyFd(state->fd, 0L, SEEK_END);
|
||||||
c->bufsize = _imaging_tell_pyFd(state->fd);
|
c->bufsize = _imaging_tell_pyFd(state->fd);
|
||||||
|
@ -155,7 +155,7 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
|
||||||
c->rleoffset = c->starttab[c->rowno + c->channo * im->ysize];
|
c->rleoffset = c->starttab[c->rowno + c->channo * im->ysize];
|
||||||
c->rlelength = c->lengthtab[c->rowno + c->channo * im->ysize];
|
c->rlelength = c->lengthtab[c->rowno + c->channo * im->ysize];
|
||||||
c->rleoffset -= SGI_HEADER_SIZE;
|
c->rleoffset -= SGI_HEADER_SIZE;
|
||||||
|
|
||||||
/* row decompression */
|
/* row decompression */
|
||||||
if (c->bpc ==1) {
|
if (c->bpc ==1) {
|
||||||
if(expandrow(&state->buffer[c->channo], &ptr[c->rleoffset], c->rlelength, im->bands))
|
if(expandrow(&state->buffer[c->channo], &ptr[c->rleoffset], c->rlelength, im->bands))
|
||||||
|
@ -165,19 +165,19 @@ ImagingSgiRleDecode(Imaging im, ImagingCodecState state,
|
||||||
if(expandrow2((UINT16*)&state->buffer[c->channo * 2], (UINT16*)&ptr[c->rleoffset], c->rlelength, im->bands))
|
if(expandrow2((UINT16*)&state->buffer[c->channo * 2], (UINT16*)&ptr[c->rleoffset], c->rlelength, im->bands))
|
||||||
goto sgi_finish_decode;
|
goto sgi_finish_decode;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->count += c->rlelength;
|
state->count += c->rlelength;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* store decompressed data in image */
|
/* store decompressed data in image */
|
||||||
state->shuffle((UINT8*)im->image[state->y], state->buffer, im->xsize);
|
state->shuffle((UINT8*)im->image[state->y], state->buffer, im->xsize);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c->bufsize++;
|
c->bufsize++;
|
||||||
|
|
||||||
sgi_finish_decode: ;
|
sgi_finish_decode: ;
|
||||||
|
|
||||||
free(c->starttab);
|
free(c->starttab);
|
||||||
free(c->lengthtab);
|
free(c->lengthtab);
|
||||||
free(ptr);
|
free(ptr);
|
||||||
|
|
|
@ -188,7 +188,7 @@ unpack1IR(UINT8* out, const UINT8* in, int pixels)
|
||||||
static void
|
static void
|
||||||
unpack18(UINT8* out, const UINT8* in, int pixels)
|
unpack18(UINT8* out, const UINT8* in, int pixels)
|
||||||
{
|
{
|
||||||
/* Unpack a '|b1' image, which is a numpy boolean.
|
/* Unpack a '|b1' image, which is a numpy boolean.
|
||||||
1 == true, 0==false, in bytes */
|
1 == true, 0==false, in bytes */
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
@ -1334,7 +1334,7 @@ static struct {
|
||||||
{"RGBA", "RGBA;16N", 64, unpackRGBA16L},
|
{"RGBA", "RGBA;16N", 64, unpackRGBA16L},
|
||||||
{"RGBX", "RGBX;16N", 64, unpackRGBA16B},
|
{"RGBX", "RGBX;16N", 64, unpackRGBA16B},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* true colour w. alpha premultiplied */
|
/* true colour w. alpha premultiplied */
|
||||||
{"RGBa", "RGBa", 32, copy4},
|
{"RGBa", "RGBa", 32, copy4},
|
||||||
|
|
Loading…
Reference in New Issue
Block a user