Merge branch 'master' into patch-2

This commit is contained in:
Andrew Murray 2018-12-27 17:39:40 +11:00 committed by GitHub
commit 21268c87b3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 437 additions and 47 deletions

View File

@ -5,6 +5,27 @@ Changelog (Pillow)
5.4.0 (unreleased)
------------------
- Improve setup.py configuration #3395
[diorcety]
- Read textual chunks located after IDAT chunks for PNG #3506
[radarhere]
- Performance: Don't try to hash value if enum is empty #3503
[Glandos]
- Added custom int and float TIFF tags #3350
[radarhere]
- Fixes for issues reported by static code analysis #3393
[frenzymadness]
- GIF: Wait until mode is normalized to copy im.info into encoderinfo #3187
[radarhere]
- Docs: Add page of deprecations and removals #3486
[hugovk]
- Travis CI: Upgrade PyPy from 5.8.0 to 6.0 #3488
[hugovk]

View File

@ -16,7 +16,7 @@ Pillow is the friendly PIL fork by `Alex Clark and Contributors <https://github.
* - tests
- |linux| |macos| |windows| |coverage|
* - package
- |zenodo| |version| |downloads|
- |zenodo| |tidelift| |version| |downloads|
* - social
- |gitter| |twitter|
@ -43,6 +43,9 @@ Pillow is the friendly PIL fork by `Alex Clark and Contributors <https://github.
.. |zenodo| image:: https://zenodo.org/badge/17549/python-pillow/Pillow.svg
:target: https://zenodo.org/badge/latestdoi/17549/python-pillow/Pillow
.. |tidelift| image:: https://tidelift.com/badges/github/python-pillow/Pillow?style=flat
:target: https://tidelift.com/subscription/pkg/pypi-pillow?utm_source=pypi-pillow&utm_medium=referral&utm_campaign=readme
.. |version| image:: https://img.shields.io/pypi/v/pillow.svg
:target: https://pypi.org/project/Pillow/
:alt: Latest PyPI version

View File

@ -536,6 +536,27 @@ class TestFileGif(PillowTestCase):
self.assertEqual(reloaded.info['transparency'], 253)
def test_rgb_transparency(self):
out = self.tempfile('temp.gif')
# Single frame
im = Image.new('RGB', (1, 1))
im.info['transparency'] = (255, 0, 0)
self.assert_warning(UserWarning, im.save, out)
reloaded = Image.open(out)
self.assertNotIn('transparency', reloaded.info)
# Multiple frames
im = Image.new('RGB', (1, 1))
im.info['transparency'] = b""
ims = [Image.new('RGB', (1, 1))]
self.assert_warning(UserWarning,
im.save, out, save_all=True, append_images=ims)
reloaded = Image.open(out)
self.assertNotIn('transparency', reloaded.info)
def test_bbox(self):
out = self.tempfile('temp.gif')

View File

@ -8,6 +8,7 @@ import io
import logging
import itertools
import os
import distutils.version
from PIL import Image, TiffImagePlugin, TiffTags
@ -231,6 +232,32 @@ class TestFileLibTiff(LibTiffTestCase):
TiffImagePlugin.WRITE_LIBTIFF = False
def test_custom_metadata(self):
custom = {
37000: 4,
37001: 4.2
}
libtiff_version = TiffImagePlugin._libtiff_version()
libtiffs = [False]
if distutils.version.StrictVersion(libtiff_version) >= \
distutils.version.StrictVersion("4.0"):
libtiffs.append(True)
for libtiff in libtiffs:
TiffImagePlugin.WRITE_LIBTIFF = libtiff
im = hopper()
out = self.tempfile("temp.tif")
im.save(out, tiffinfo=custom)
TiffImagePlugin.WRITE_LIBTIFF = False
reloaded = Image.open(out)
for tag, value in custom.items():
self.assertEqual(reloaded.tag_v2[tag], value)
def test_int_dpi(self):
# issue #1765
im = hopper('RGB')

View File

@ -563,6 +563,28 @@ class TestFilePng(PillowTestCase):
chunks = PngImagePlugin.getchunks(im)
self.assertEqual(len(chunks), 3)
def test_textual_chunks_after_idat(self):
im = Image.open("Tests/images/hopper.png")
self.assertIn('comment', im.text.keys())
for k, v in {
'date:create': '2014-09-04T09:37:08+03:00',
'date:modify': '2014-09-04T09:37:08+03:00',
}.items():
self.assertEqual(im.text[k], v)
# Raises a SyntaxError in load_end
im = Image.open("Tests/images/broken_data_stream.png")
with self.assertRaises(IOError):
self.assertIsInstance(im.text, dict)
# Raises a UnicodeDecodeError in load_end
im = Image.open("Tests/images/truncated_image.png")
# The file is truncated
self.assertRaises(IOError, lambda: im.text)
ImageFile.LOAD_TRUNCATED_IMAGES = True
self.assertIsInstance(im.text, dict)
ImageFile.LOAD_TRUNCATED_IMAGES = False
@unittest.skipUnless(HAVE_WEBP and _webp.HAVE_WEBPANIM,
"WebP support not installed with animation")
def test_apng(self):

View File

@ -135,7 +135,7 @@ class TestFileTiffMetadata(PillowTestCase):
for k, v in original.items():
if isinstance(v, IFDRational):
original[k] = IFDRational(*_limit_rational(v, 2**31))
if isinstance(v, tuple) and isinstance(v[0], IFDRational):
elif isinstance(v, tuple) and isinstance(v[0], IFDRational):
original[k] = tuple(IFDRational(*_limit_rational(elt, 2**31))
for elt in v)

View File

@ -10,6 +10,7 @@ def version(module, version):
version(Image, "jpeglib")
version(Image, "zlib")
version(Image, "libtiff")
try:
from PIL import ImageFont

60
docs/_static/js/script.js vendored Normal file
View File

@ -0,0 +1,60 @@
jQuery(document).ready(function ($) {
setTimeout(function () {
var sectionID = 'base';
var search = function ($section, $sidebarItem) {
$section.children('.section, .function, .method').each(function () {
if ($(this).hasClass('section')) {
sectionID = $(this).attr('id');
search($(this), $sidebarItem.parent().find('[href=#'+sectionID+']'));
} else {
var $dt = $(this).children('dt');
var id = $dt.attr('id');
if (id === undefined) {
return;
}
var $functionsUL = $sidebarItem.siblings('[data-sectionID='+sectionID+']');
if (!$functionsUL.length) {
$functionsUL = $('<ul />').attr('data-sectionID', sectionID);
$functionsUL.insertAfter($sidebarItem);
}
var $li = $('<li />');
var $a = $('<a />').css('font-size', '11.5px');
var $upperA = $sidebarItem.parent().children('a');
var $upperAParent = $upperA.parent();
if ($upperAParent.hasClass('toctree-l2')) {
$a.css('background-color', '#c9c9c9');
$a.css('padding-left', '4em');
} else if ($upperAParent.hasClass('toctree-l3')) {
if (!$upperA.find('.toctree-expand').length) {
$upperA.prepend($('<span />').addClass('toctree-expand'));
}
$a.css('background-color', '#c9c9c9');
$a.css('padding-left', '5em');
} else {
$a.css('background-color', '#bdbdbd');
$a.css('padding-left', '6.25em');
}
$a.attr('href', '#'+id);
$a.text('- '+$dt.find('code').text());
$a.click(function () {
setTimeout(function () {
$a.css('font-weight', 'bold');
}, 0);
});
$li.append($a);
$functionsUL.append($li);
}
});
};
search($('[itemprop=articleBody] > .section'), $('.wy-nav-side a[href=#]'));
}, 0);
$(window).on('hashchange', function () {
$('ul[data-sectionID]').each(function () {
$(this).find('a').each(function () {
$(this).css('font-weight', 'normal');
});
});
});
});

View File

@ -286,3 +286,7 @@ texinfo_documents = [
# If true, do not generate a @detailmenu in the "Top" node's menu.
# texinfo_no_detailmenu = False
def setup(app):
app.add_javascript('js/script.js')

82
docs/deprecations.rst Normal file
View File

@ -0,0 +1,82 @@
.. _deprecations:
Deprecations and removals
=========================
This page lists Pillow features that are deprecated, or have been removed in
past major releases, and gives the alternatives to use instead.
Deprecated features
-------------------
Below are features which are considered deprecated. Where appropriate,
a ``DeprecationWarning`` is issued.
Setting the size of TIFF images
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. deprecated:: 5.3.0
Setting the image size of a TIFF image (eg. ``im.size = (256, 256)``) issues
a ``DeprecationWarning``:
.. code-block:: none
Setting the size of a TIFF image directly is deprecated, and will
be removed in a future version. Use the resize method instead.
PILLOW_VERSION and VERSION constants
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. deprecated:: 5.2.0
Two version constants ``VERSION`` (the old PIL version, always 1.1.7) and
``PILLOW_VERSION`` have been deprecated and will be removed in the next
major release. Use ``__version__`` instead.
Undocumented ImageOps functions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. deprecated:: 4.3.0
Several undocumented functions in ``ImageOps`` have been deprecated. They issue
a ``DeprecationWarning`` informing which equivalent to use from ``ImageFilter``
instead:
========================== ============================
Deprecated Use instead
========================== ============================
``ImageOps.box_blur`` ``ImageFilter.BoxBlur``
``ImageOps.gaussian_blur`` ``ImageFilter.GaussianBlur``
``ImageOps.gblur`` ``ImageFilter.GaussianBlur``
``ImageOps.usm`` ``ImageFilter.UnsharpMask``
``ImageOps.unsharp_mask`` ``ImageFilter.UnsharpMask``
========================== ============================
PIL.OleFileIO
~~~~~~~~~~~~~
.. deprecated:: 4.0.0
The vendored version of olefile has been removed. Attempting to import
``PIL.OleFileIO`` issues a ``DeprecationWarning`` (from 4.0.0) or raises
``ImportError`` (from 5.0.0):
.. code-block:: none
PIL.OleFileIO is deprecated. Use the olefile Python package
instead. This module will be removed in a future version.
Removed features
----------------
Deprecated features are only removed in major releases after an appropriate
period of deprecation has passed.
Vendored olefile
~~~~~~~~~~~~~~~~
*Removed in version 4.0.0.*
The vendored version of the olefile Python package was removed in favour of the
upstream package. Install if needed (eg. ``pip install olefile``).

View File

@ -482,7 +482,7 @@ The :py:meth:`~PIL.Image.Image.open` method sets the following
This key is omitted if the image is not a transparent palette image.
``Open`` also sets ``Image.text`` to a list of the values of the
``Open`` also sets ``Image.text`` to a dictionary of the values of the
``tEXt``, ``zTXt``, and ``iTXt`` chunks of the PNG image. Individual
compressed chunks are limited to a decompressed size of
``PngImagePlugin.MAX_TEXT_CHUNK``, by default 1MB, to prevent

View File

@ -43,6 +43,7 @@ Pillow is the friendly PIL fork by `Alex Clark and Contributors <https://github.
porting.rst
about.rst
releasenotes/index.rst
deprecations.rst
Indices and tables
==================

View File

@ -147,15 +147,30 @@ LCMS_ROOT = None
def _pkg_config(name):
try:
command = [
command_libs = [
'pkg-config',
'--libs-only-L', name,
]
command_cflags = [
'pkg-config',
'--cflags-only-I', name,
]
if not DEBUG:
command.append('--silence-errors')
libs = subprocess.check_output(command).decode('utf8').split(' ')
return libs[1][2:].strip(), libs[0][2:].strip()
command_libs.append('--silence-errors')
command_cflags.append('--silence-errors')
libs = (
subprocess.check_output(command_libs)
.decode("utf8")
.strip()
.replace("-L", "")
)
cflags = (
subprocess.check_output(command_cflags)
.decode("utf8")
.strip()
.replace("-I", "")
)
return (libs, cflags)
except Exception:
pass
@ -247,6 +262,11 @@ class pil_build_ext(build_ext):
IMAGEQUANT_ROOT="libimagequant"
).items():
root = globals()[root_name]
if root is None and root_name in os.environ:
prefix = os.environ[root_name]
root = (os.path.join(prefix, 'lib'), os.path.join(prefix, 'include'))
if root is None and pkg_config:
if isinstance(lib_name, tuple):
for lib_name2 in lib_name:

View File

@ -393,6 +393,8 @@ def _normalize_palette(im, palette, info):
def _write_single_frame(im, fp, palette):
im_out = _normalize_mode(im, True)
for k, v in im_out.info.items():
im.encoderinfo.setdefault(k, v)
im_out = _normalize_palette(im_out, palette, im.encoderinfo)
for s in _get_global_header(im_out, im.encoderinfo):
@ -413,8 +415,8 @@ def _write_single_frame(im, fp, palette):
def _write_multiple_frames(im, fp, palette):
duration = im.encoderinfo.get("duration", None)
disposal = im.encoderinfo.get('disposal', None)
duration = im.encoderinfo.get("duration", im.info.get("duration"))
disposal = im.encoderinfo.get("disposal", im.info.get("disposal"))
im_frames = []
frame_count = 0
@ -423,6 +425,9 @@ def _write_multiple_frames(im, fp, palette):
for im_frame in ImageSequence.Iterator(imSequence):
# a copy is required here since seek can still mutate the image
im_frame = _normalize_mode(im_frame.copy())
if frame_count == 0:
for k, v in im_frame.info.items():
im.encoderinfo.setdefault(k, v)
im_frame = _normalize_palette(im_frame, palette, im.encoderinfo)
encoderinfo = im.encoderinfo.copy()
@ -481,12 +486,10 @@ def _save_all(im, fp, filename):
def _save(im, fp, filename, save_all=False):
for k, v in im.info.items():
im.encoderinfo.setdefault(k, v)
# header
try:
palette = im.encoderinfo["palette"]
except KeyError:
if "palette" in im.encoderinfo or "palette" in im.info:
palette = im.encoderinfo.get("palette", im.info.get("palette"))
else:
palette = None
im.encoderinfo["optimize"] = im.encoderinfo.get("optimize", True)

View File

@ -592,7 +592,7 @@ class PngImageFile(ImageFile.ImageFile):
self.mode = self.png.im_mode
self._size = self.png.im_size
self.info = self.png.im_info
self.text = self.png.im_text # experimental
self._text = None
self.tile = self.png.im_tile
if self.png.im_palette:
@ -601,6 +601,15 @@ class PngImageFile(ImageFile.ImageFile):
self.__idat = length # used by load_read()
@property
def text(self):
# experimental
if self._text is None:
# iTxt, tEXt and zTXt chunks may appear at the end of the file
# So load the file to ensure that they are read
self.load()
return self._text
def verify(self):
"Verify PNG file"
@ -653,7 +662,22 @@ class PngImageFile(ImageFile.ImageFile):
def load_end(self):
"internal: finished reading image data"
while True:
self.fp.read(4) # CRC
try:
cid, pos, length = self.png.read()
except (struct.error, SyntaxError):
break
if cid == b"IEND":
break
try:
self.png.call(cid, pos, length)
except UnicodeDecodeError:
break
self._text = self.png.im_text
self.png.close()
self.png = None

View File

@ -54,6 +54,7 @@ import os
import struct
import sys
import warnings
import distutils.version
from .TiffTags import TYPES
@ -284,6 +285,10 @@ def _limit_rational(val, max_val):
return n_d[::-1] if inv else n_d
def _libtiff_version():
return Image.core.libtiff_version.split("\n")[0].split("Version ")[1]
##
# Wrapper for TIFF IFDs.
@ -1508,12 +1513,13 @@ def _save(im, fp, filename):
getattr(im, 'tag_v2', {}).items(),
legacy_ifd.items()):
# Libtiff can only process certain core items without adding
# them to the custom dictionary. It will segfault if it attempts
# to add a custom tag without the dictionary entry
#
# UNDONE -- add code for the custom dictionary
# them to the custom dictionary. Support has only been been added
# for int and float values
if tag not in TiffTags.LIBTIFF_CORE:
continue
if (distutils.version.StrictVersion(_libtiff_version()) <
distutils.version.StrictVersion("4.0")) \
or not (isinstance(value, int) or isinstance(value, float)):
continue
if tag not in atts and tag not in blocklist:
if isinstance(value, str if py3 else unicode): # noqa: F821
atts[tag] = value.encode('ascii', 'replace') + b"\0"

View File

@ -29,7 +29,10 @@ class TagInfo(namedtuple("_TagInfo", "value name type length enum")):
cls, value, name, type, length, enum or {})
def cvt_enum(self, value):
return self.enum.get(value, value)
# Using get will call hash(value), which can be expensive
# for some types (e.g. Fraction). Since self.enum is rarely
# used, it's usually better to test it first.
return self.enum.get(value, value) if self.enum else value
def lookup(tag):
@ -425,6 +428,7 @@ TYPES = {}
# some of these are not in our TAGS_V2 dict and were included from tiff.h
# This list also exists in encode.c
LIBTIFF_CORE = {255, 256, 257, 258, 259, 262, 263, 266, 274, 277,
278, 280, 281, 340, 341, 282, 283, 284, 286, 287,
296, 297, 321, 320, 338, 32995, 322, 323, 32998,

View File

@ -425,6 +425,7 @@ int load_tkinter_funcs(void)
/* Try loading from the main program namespace first */
main_program = dlopen(NULL, RTLD_LAZY);
if (_func_loader(main_program) == 0) {
dlclose(main_program);
return 0;
}
/* Clear exception triggered when we didn't find symbols above */
@ -453,6 +454,7 @@ int load_tkinter_funcs(void)
/* dlclose probably safe because tkinter has been imported. */
dlclose(tkinter_lib);
exit:
dlclose(main_program);
Py_XDECREF(pModule);
Py_XDECREF(pString);
return ret;

View File

@ -1053,8 +1053,10 @@ _gaussian_blur(ImagingObject* self, PyObject* args)
if (!imOut)
return NULL;
if (!ImagingGaussianBlur(imOut, imIn, radius, passes))
if (!ImagingGaussianBlur(imOut, imIn, radius, passes)) {
ImagingDelete(imOut);
return NULL;
}
return PyImagingNew(imOut);
}
@ -1949,8 +1951,10 @@ _box_blur(ImagingObject* self, PyObject* args)
if (!imOut)
return NULL;
if (!ImagingBoxBlur(imOut, imIn, radius, n))
if (!ImagingBoxBlur(imOut, imIn, radius, n)) {
ImagingDelete(imOut);
return NULL;
}
return PyImagingNew(imOut);
}
@ -2596,6 +2600,7 @@ _draw_arc(ImagingDrawObject* self, PyObject* args)
return NULL;
if (n != 2) {
PyErr_SetString(PyExc_TypeError, must_be_two_coordinates);
free(xy);
return NULL;
}
@ -2633,6 +2638,7 @@ _draw_bitmap(ImagingDrawObject* self, PyObject* args)
PyErr_SetString(PyExc_TypeError,
"coordinate list must contain exactly 1 coordinate"
);
free(xy);
return NULL;
}
@ -2669,6 +2675,7 @@ _draw_chord(ImagingDrawObject* self, PyObject* args)
return NULL;
if (n != 2) {
PyErr_SetString(PyExc_TypeError, must_be_two_coordinates);
free(xy);
return NULL;
}
@ -2705,6 +2712,7 @@ _draw_ellipse(ImagingDrawObject* self, PyObject* args)
return NULL;
if (n != 2) {
PyErr_SetString(PyExc_TypeError, must_be_two_coordinates);
free(xy);
return NULL;
}
@ -2856,6 +2864,7 @@ _draw_pieslice(ImagingDrawObject* self, PyObject* args)
return NULL;
if (n != 2) {
PyErr_SetString(PyExc_TypeError, must_be_two_coordinates);
free(xy);
return NULL;
}
@ -2894,6 +2903,7 @@ _draw_polygon(ImagingDrawObject* self, PyObject* args)
PyErr_SetString(PyExc_TypeError,
"coordinate list must contain at least 2 coordinates"
);
free(xy);
return NULL;
}
@ -2937,6 +2947,7 @@ _draw_rectangle(ImagingDrawObject* self, PyObject* args)
return NULL;
if (n != 2) {
PyErr_SetString(PyExc_TypeError, must_be_two_coordinates);
free(xy);
return NULL;
}
@ -3859,6 +3870,13 @@ setup_module(PyObject* m) {
}
#endif
#ifdef HAVE_LIBTIFF
{
extern const char * ImagingTiffVersion(void);
PyDict_SetItemString(d, "libtiff_version", PyUnicode_FromString(ImagingTiffVersion()));
}
#endif
PyDict_SetItemString(d, "PILLOW_VERSION", PyUnicode_FromString(version));
return 0;

View File

@ -584,11 +584,15 @@ PyImaging_ZipEncoderNew(PyObject* self, PyObject* args)
dictionary = NULL;
encoder = PyImaging_EncoderNew(sizeof(ZIPSTATE));
if (encoder == NULL)
if (encoder == NULL) {
free(dictionary);
return NULL;
}
if (get_packer(encoder, mode, rawmode) < 0)
if (get_packer(encoder, mode, rawmode) < 0) {
free(dictionary);
return NULL;
}
encoder->encode = ImagingZipEncode;
encoder->cleanup = ImagingZipEncodeCleanup;
@ -749,8 +753,10 @@ PyImaging_JpegEncoderNew(PyObject* self, PyObject* args)
if (rawExif && rawExifLen > 0) {
/* malloc check ok, length is from python parsearg */
char* pp = malloc(rawExifLen); // Freed in JpegEncode, Case 5
if (!pp)
if (!pp) {
if (extra) free(extra);
return PyErr_NoMemory();
}
memcpy(pp, rawExif, rawExifLen);
rawExif = pp;
} else
@ -804,7 +810,13 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args)
PyObject *dir;
PyObject *key, *value;
Py_ssize_t pos = 0;
int status;
int key_int, status, is_core_tag, number_of_tags, i;
// This list also exists in TiffTags.py
const int tags[] = {
256, 257, 258, 259, 262, 263, 266, 269, 274, 277, 278, 280, 281, 340,
341, 282, 283, 284, 286, 287, 296, 297, 321, 338, 32995, 32998, 32996,
339, 32997, 330, 531, 530
};
Py_ssize_t d_size;
PyObject *keys, *values;
@ -843,23 +855,36 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args)
return NULL;
}
number_of_tags = sizeof(tags) / sizeof(int);
for (pos = 0; pos < d_size; pos++) {
key = PyList_GetItem(keys, pos);
key_int = (int)PyInt_AsLong(key);
value = PyList_GetItem(values, pos);
status = 0;
TRACE(("Attempting to set key: %d\n", (int)PyInt_AsLong(key)));
is_core_tag = 0;
for (i=0; i<number_of_tags; i++) {
if (tags[i] == key_int) {
is_core_tag = 1;
break;
}
}
TRACE(("Attempting to set key: %d\n", key_int));
if (PyInt_Check(value)) {
TRACE(("Setting from Int: %d %ld \n", (int)PyInt_AsLong(key),PyInt_AsLong(value)));
status = ImagingLibTiffSetField(&encoder->state,
(ttag_t) PyInt_AsLong(key),
PyInt_AsLong(value));
TRACE(("Setting from Int: %d %ld \n", key_int, PyInt_AsLong(value)));
if (is_core_tag || !ImagingLibTiffMergeFieldInfo(&encoder->state, TIFF_LONG, key_int)) {
status = ImagingLibTiffSetField(&encoder->state,
(ttag_t) PyInt_AsLong(key),
PyInt_AsLong(value));
}
} else if (PyFloat_Check(value)) {
TRACE(("Setting from Float: %d, %f \n", (int)PyInt_AsLong(key),PyFloat_AsDouble(value)));
status = ImagingLibTiffSetField(&encoder->state,
(ttag_t) PyInt_AsLong(key),
(float)PyFloat_AsDouble(value));
TRACE(("Setting from Float: %d, %f \n", key_int, PyFloat_AsDouble(value)));
if (is_core_tag || !ImagingLibTiffMergeFieldInfo(&encoder->state, TIFF_DOUBLE, key_int)) {
status = ImagingLibTiffSetField(&encoder->state,
(ttag_t) PyInt_AsLong(key),
(double)PyFloat_AsDouble(value));
}
} else if (PyBytes_Check(value)) {
TRACE(("Setting from Bytes: %d, %s \n", (int)PyInt_AsLong(key),PyBytes_AsString(value)));
TRACE(("Setting from Bytes: %d, %s \n", key_int, PyBytes_AsString(value)));
status = ImagingLibTiffSetField(&encoder->state,
(ttag_t) PyInt_AsLong(key),
PyBytes_AsString(value));
@ -867,7 +892,7 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args)
Py_ssize_t len,i;
float *floatav;
int *intav;
TRACE(("Setting from Tuple: %d \n", (int)PyInt_AsLong(key)));
TRACE(("Setting from Tuple: %d \n", key_int));
len = PyTuple_Size(value);
if (len) {
if (PyInt_Check(PyTuple_GetItem(value,0))) {
@ -898,13 +923,13 @@ PyImaging_LibTiffEncoderNew(PyObject* self, PyObject* args)
}
} else {
TRACE(("Unhandled type in tuple for key %d : %s \n",
(int)PyInt_AsLong(key),
key_int,
PyBytes_AsString(PyObject_Str(value))));
}
}
} else {
TRACE(("Unhandled type for key %d : %s \n",
(int)PyInt_AsLong(key),
key_int,
PyBytes_AsString(PyObject_Str(value))));
}
if (!status) {

View File

@ -41,7 +41,9 @@ ImagingHistogramNew(Imaging im)
/* Create histogram descriptor */
h = calloc(1, sizeof(struct ImagingHistogramInstance));
strncpy(h->mode, im->mode, IMAGING_MODE_LENGTH);
strncpy(h->mode, im->mode, IMAGING_MODE_LENGTH-1);
h->mode[IMAGING_MODE_LENGTH-1] = 0;
h->bands = im->bands;
h->histogram = calloc(im->pixelsize, 256 * sizeof(long));
@ -80,8 +82,10 @@ ImagingGetHistogram(Imaging im, Imaging imMask, void* minmax)
h->histogram[im->image8[y][x]]++;
ImagingSectionLeave(&cookie);
} else { /* yes, we need the braces. C isn't Python! */
if (im->type != IMAGING_TYPE_UINT8)
if (im->type != IMAGING_TYPE_UINT8) {
ImagingHistogramDelete(h);
return ImagingError_ModeError();
}
ImagingSectionEnter(&cookie);
for (y = 0; y < im->ysize; y++) {
UINT8* in = (UINT8*) im->image32[y];
@ -120,8 +124,10 @@ ImagingGetHistogram(Imaging im, Imaging imMask, void* minmax)
ImagingSectionLeave(&cookie);
break;
case IMAGING_TYPE_INT32:
if (!minmax)
if (!minmax) {
ImagingHistogramDelete(h);
return ImagingError_ValueError("min/max not given");
}
if (!im->xsize || !im->ysize)
break;
imin = ((INT32*) minmax)[0];
@ -141,8 +147,10 @@ ImagingGetHistogram(Imaging im, Imaging imMask, void* minmax)
ImagingSectionLeave(&cookie);
break;
case IMAGING_TYPE_FLOAT32:
if (!minmax)
if (!minmax) {
ImagingHistogramDelete(h);
return ImagingError_ValueError("min/max not given");
}
if (!im->xsize || !im->ysize)
break;
fmin = ((FLOAT32*) minmax)[0];

View File

@ -37,7 +37,8 @@ ImagingPaletteNew(const char* mode)
if (!palette)
return (ImagingPalette) ImagingError_MemoryError();
strncpy(palette->mode, mode, IMAGING_MODE_LENGTH);
strncpy(palette->mode, mode, IMAGING_MODE_LENGTH-1);
palette->mode[IMAGING_MODE_LENGTH-1] = 0;
/* Initialize to ramp */
for (i = 0; i < 256; i++) {

View File

@ -568,6 +568,8 @@ split(BoxNode *node)
left=malloc(sizeof(BoxNode));
right=malloc(sizeof(BoxNode));
if (!left||!right) {
free(left);
free(right);
return 0;
}
for(i=0;i<3;i++) {

View File

@ -481,6 +481,7 @@ error:
free(qp);
free_color_cube(lookupCube);
free_color_cube(coarseLookupCube);
free(paletteBuckets);
free(paletteBucketsCoarse);
free(paletteBucketsFine);
free_color_cube(coarseCube);

View File

@ -621,6 +621,8 @@ ImagingResampleInner(Imaging imIn, int xsize, int ysize,
if ( ! ksize_vert) {
free(bounds_horiz);
free(kk_horiz);
free(bounds_vert);
free(kk_vert);
return NULL;
}

View File

@ -402,6 +402,26 @@ int ImagingLibTiffEncodeInit(ImagingCodecState state, char *filename, int fp) {
}
int ImagingLibTiffMergeFieldInfo(ImagingCodecState state, TIFFDataType field_type, int key){
TIFFSTATE *clientstate = (TIFFSTATE *)state->context;
char field_name[10];
uint32 n;
int status = 0;
const TIFFFieldInfo info[] = {
{ key, 0, 1, field_type, FIELD_CUSTOM, 1, 0, field_name }
};
n = sizeof(info) / sizeof(info[0]);
// Test for libtiff 4.0 or later, excluding libtiff 3.9.6 and 3.9.7
#if TIFFLIB_VERSION >= 20111221 && TIFFLIB_VERSION != 20120218 && TIFFLIB_VERSION != 20120922
status = TIFFMergeFieldInfo(clientstate->tiff, info, n);
#else
TIFFMergeFieldInfo(clientstate->tiff, info, n);
#endif
return status;
}
int ImagingLibTiffSetField(ImagingCodecState state, ttag_t tag, ...){
// after tif_dir.c->TIFFSetField.
TIFFSTATE *clientstate = (TIFFSTATE *)state->context;
@ -501,4 +521,11 @@ int ImagingLibTiffEncode(Imaging im, ImagingCodecState state, UINT8* buffer, int
state->errcode = IMAGING_CODEC_END;
return 0;
}
const char*
ImagingTiffVersion(void)
{
return TIFFGetVersion();
}
#endif

View File

@ -45,6 +45,7 @@ typedef struct {
extern int ImagingLibTiffInit(ImagingCodecState state, int fp, int offset);
extern int ImagingLibTiffEncodeInit(ImagingCodecState state, char *filename, int fp);
extern int ImagingLibTiffMergeFieldInfo(ImagingCodecState state, TIFFDataType field_type, int key);
extern int ImagingLibTiffSetField(ImagingCodecState state, ttag_t tag, ...);

View File

@ -82,12 +82,16 @@ path_new(Py_ssize_t count, double* xy, int duplicate)
xy = p;
}
if (PyType_Ready(&PyPathType) < 0)
if (PyType_Ready(&PyPathType) < 0) {
free(xy);
return NULL;
}
path = PyObject_New(PyPathObject, &PyPathType);
if (path == NULL)
if (path == NULL) {
free(xy);
return NULL;
}
path->count = count;
path->xy = xy;