mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-24 00:46:16 +03:00
commit
e16ee15f2c
|
@ -24,7 +24,7 @@ Changelog (Pillow)
|
|||
- Use PyQt4 if it has already been imported, otherwise prefer PyQt5. #1003
|
||||
[AurelienBallier]
|
||||
|
||||
- Speedup stretch implementation up to 2.5 times. #977
|
||||
- Speedup resample implementation up to 2.5 times. #977
|
||||
[homm]
|
||||
|
||||
- Speed up rotation by using cache aware loops, added transpose to rotations. #994
|
||||
|
|
41
PIL/Image.py
41
PIL/Image.py
|
@ -879,7 +879,7 @@ class Image:
|
|||
elif self.mode == 'P' and mode == 'RGBA':
|
||||
t = self.info['transparency']
|
||||
delete_trns = True
|
||||
|
||||
|
||||
if isinstance(t, bytes):
|
||||
self.im.putpalettealphas(t)
|
||||
elif isinstance(t, int):
|
||||
|
@ -1523,9 +1523,8 @@ class Image:
|
|||
(width, height).
|
||||
:param resample: An optional resampling filter. This can be
|
||||
one of :py:attr:`PIL.Image.NEAREST` (use nearest neighbour),
|
||||
:py:attr:`PIL.Image.BILINEAR` (linear interpolation in a 2x2
|
||||
environment), :py:attr:`PIL.Image.BICUBIC` (cubic spline
|
||||
interpolation in a 4x4 environment), or
|
||||
:py:attr:`PIL.Image.BILINEAR` (linear interpolation),
|
||||
:py:attr:`PIL.Image.BICUBIC` (cubic spline interpolation), or
|
||||
:py:attr:`PIL.Image.ANTIALIAS` (a high-quality downsampling filter).
|
||||
If omitted, or if the image has mode "1" or "P", it is
|
||||
set :py:attr:`PIL.Image.NEAREST`.
|
||||
|
@ -1547,16 +1546,7 @@ class Image:
|
|||
if self.mode == 'RGBA':
|
||||
return self.convert('RGBa').resize(size, resample).convert('RGBA')
|
||||
|
||||
if resample == ANTIALIAS:
|
||||
# requires stretch support (imToolkit & PIL 1.1.3)
|
||||
try:
|
||||
im = self.im.stretch(size, resample)
|
||||
except AttributeError:
|
||||
raise ValueError("unsupported resampling filter")
|
||||
else:
|
||||
im = self.im.resize(size, resample)
|
||||
|
||||
return self._new(im)
|
||||
return self._new(self.im.resize(size, resample))
|
||||
|
||||
def rotate(self, angle, resample=NEAREST, expand=0):
|
||||
"""
|
||||
|
@ -1772,12 +1762,7 @@ class Image:
|
|||
:py:meth:`~PIL.Image.Image.draft` method to configure the file reader
|
||||
(where applicable), and finally resizes the image.
|
||||
|
||||
Note that the bilinear and bicubic filters in the current
|
||||
version of PIL are not well-suited for thumbnail generation.
|
||||
You should use :py:attr:`PIL.Image.ANTIALIAS` unless speed is much more
|
||||
important than quality.
|
||||
|
||||
Also note that this function modifies the :py:class:`~PIL.Image.Image`
|
||||
Note that this function modifies the :py:class:`~PIL.Image.Image`
|
||||
object in place. If you need to use the full resolution image as well,
|
||||
apply this method to a :py:meth:`~PIL.Image.Image.copy` of the original
|
||||
image.
|
||||
|
@ -1785,10 +1770,9 @@ class Image:
|
|||
:param size: Requested size.
|
||||
:param resample: Optional resampling filter. This can be one
|
||||
of :py:attr:`PIL.Image.NEAREST`, :py:attr:`PIL.Image.BILINEAR`,
|
||||
:py:attr:`PIL.Image.BICUBIC`, or :py:attr:`PIL.Image.ANTIALIAS`
|
||||
(best quality). If omitted, it defaults to
|
||||
:py:attr:`PIL.Image.ANTIALIAS`. (was :py:attr:`PIL.Image.NEAREST`
|
||||
prior to version 2.5.0)
|
||||
:py:attr:`PIL.Image.BICUBIC`, or :py:attr:`PIL.Image.ANTIALIAS`.
|
||||
If omitted, it defaults to :py:attr:`PIL.Image.ANTIALIAS`.
|
||||
(was :py:attr:`PIL.Image.NEAREST` prior to version 2.5.0)
|
||||
:returns: None
|
||||
"""
|
||||
|
||||
|
@ -1807,14 +1791,7 @@ class Image:
|
|||
|
||||
self.draft(None, size)
|
||||
|
||||
self.load()
|
||||
|
||||
try:
|
||||
im = self.resize(size, resample)
|
||||
except ValueError:
|
||||
if resample != ANTIALIAS:
|
||||
raise
|
||||
im = self.resize(size, NEAREST) # fallback
|
||||
im = self.resize(size, resample)
|
||||
|
||||
self.im = im.im
|
||||
self.mode = im.mode
|
||||
|
|
|
@ -1,5 +1,91 @@
|
|||
"""
|
||||
Tests for resize functionality.
|
||||
"""
|
||||
from itertools import permutations
|
||||
|
||||
from helper import unittest, PillowTestCase, hopper
|
||||
|
||||
from PIL import Image
|
||||
|
||||
|
||||
class TestImagingCoreResize(PillowTestCase):
|
||||
|
||||
def resize(self, im, size, f):
|
||||
# Image class independent version of resize.
|
||||
im.load()
|
||||
return im._new(im.im.resize(size, f))
|
||||
|
||||
def test_nearest_mode(self):
|
||||
for mode in ["1", "P", "L", "I", "F", "RGB", "RGBA", "CMYK", "YCbCr",
|
||||
"I;16"]: # exotic mode
|
||||
im = hopper(mode)
|
||||
r = self.resize(im, (15, 12), Image.NEAREST)
|
||||
self.assertEqual(r.mode, mode)
|
||||
self.assertEqual(r.size, (15, 12) )
|
||||
self.assertEqual(r.im.bands, im.im.bands)
|
||||
|
||||
def test_convolution_modes(self):
|
||||
self.assertRaises(ValueError, self.resize, hopper("1"),
|
||||
(15, 12), Image.BILINEAR)
|
||||
self.assertRaises(ValueError, self.resize, hopper("P"),
|
||||
(15, 12), Image.BILINEAR)
|
||||
self.assertRaises(ValueError, self.resize, hopper("I;16"),
|
||||
(15, 12), Image.BILINEAR)
|
||||
for mode in ["L", "I", "F", "RGB", "RGBA", "CMYK", "YCbCr"]:
|
||||
im = hopper(mode)
|
||||
r = self.resize(im, (15, 12), Image.BILINEAR)
|
||||
self.assertEqual(r.mode, mode)
|
||||
self.assertEqual(r.size, (15, 12) )
|
||||
self.assertEqual(r.im.bands, im.im.bands)
|
||||
|
||||
def test_reduce_filters(self):
|
||||
for f in [Image.LINEAR, Image.BILINEAR, Image.BICUBIC, Image.ANTIALIAS]:
|
||||
r = self.resize(hopper("RGB"), (15, 12), f)
|
||||
self.assertEqual(r.mode, "RGB")
|
||||
self.assertEqual(r.size, (15, 12))
|
||||
|
||||
def test_enlarge_filters(self):
|
||||
for f in [Image.LINEAR, Image.BILINEAR, Image.BICUBIC, Image.ANTIALIAS]:
|
||||
r = self.resize(hopper("RGB"), (212, 195), f)
|
||||
self.assertEqual(r.mode, "RGB")
|
||||
self.assertEqual(r.size, (212, 195))
|
||||
|
||||
def test_endianness(self):
|
||||
# Make an image with one colored pixel, in one channel.
|
||||
# When resized, that channel should be the same as a GS image.
|
||||
# Other channels should be unaffected.
|
||||
# The R and A channels should not swap, which is indicitive of
|
||||
# an endianness issues.
|
||||
|
||||
samples = {
|
||||
'blank': Image.new('L', (2, 2), 0),
|
||||
'filled': Image.new('L', (2, 2), 255),
|
||||
'dirty': Image.new('L', (2, 2), 0),
|
||||
}
|
||||
samples['dirty'].putpixel((1, 1), 128)
|
||||
|
||||
for f in [Image.LINEAR, Image.BILINEAR, Image.BICUBIC, Image.ANTIALIAS]:
|
||||
# samples resized with current filter
|
||||
references = dict(
|
||||
(name, self.resize(ch, (4, 4), f))
|
||||
for name, ch in samples.items()
|
||||
)
|
||||
|
||||
for mode, channels_set in [
|
||||
('RGB', ('blank', 'filled', 'dirty')),
|
||||
('RGBA', ('blank', 'blank', 'filled', 'dirty')),
|
||||
('LA', ('filled', 'dirty')),
|
||||
]:
|
||||
for channels in set(permutations(channels_set)):
|
||||
# compile image from different channels permutations
|
||||
im = Image.merge(mode, [samples[ch] for ch in channels])
|
||||
resized = self.resize(im, (4, 4), f)
|
||||
|
||||
for i, ch in enumerate(resized.split()):
|
||||
# check what resized channel in image is the same
|
||||
# as separately resized channel
|
||||
self.assert_image_equal(ch, references[channels[i]])
|
||||
|
||||
|
||||
class TestImageResize(PillowTestCase):
|
||||
|
||||
|
@ -9,8 +95,8 @@ class TestImageResize(PillowTestCase):
|
|||
self.assertEqual(out.mode, mode)
|
||||
self.assertEqual(out.size, size)
|
||||
for mode in "1", "P", "L", "RGB", "I", "F":
|
||||
resize(mode, (100, 100))
|
||||
resize(mode, (200, 200))
|
||||
resize(mode, (112, 103))
|
||||
resize(mode, (188, 214))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -44,7 +44,9 @@ class TestImageTransform(PillowTestCase):
|
|||
w//2, h//2, w//2, 0),
|
||||
Image.BILINEAR)
|
||||
|
||||
scaled = im.resize((w*2, h*2), Image.BILINEAR).crop((0, 0, w, h))
|
||||
scaled = im.transform((w, h), Image.AFFINE,
|
||||
(.5, 0, 0, 0, .5, 0),
|
||||
Image.BILINEAR)
|
||||
|
||||
self.assert_image_equal(transformed, scaled)
|
||||
|
||||
|
@ -61,9 +63,9 @@ class TestImageTransform(PillowTestCase):
|
|||
w, h, w, 0))], # ul -> ccw around quad
|
||||
Image.BILINEAR)
|
||||
|
||||
# transformed.save('transformed.png')
|
||||
|
||||
scaled = im.resize((w//2, h//2), Image.BILINEAR)
|
||||
scaled = im.transform((w//2, h//2), Image.AFFINE,
|
||||
(2, 0, 0, 0, 2, 0),
|
||||
Image.BILINEAR)
|
||||
|
||||
checker = Image.new('RGBA', im.size)
|
||||
checker.paste(scaled, (0, 0))
|
||||
|
@ -128,7 +130,8 @@ class TestImageTransform(PillowTestCase):
|
|||
|
||||
foo = [
|
||||
Image.new('RGBA', (1024, 1024), (a, a, a, a))
|
||||
for a in range(1, 65)]
|
||||
for a in range(1, 65)
|
||||
]
|
||||
|
||||
# Yeah. Watch some JIT optimize this out.
|
||||
foo = None
|
||||
|
|
|
@ -1,86 +0,0 @@
|
|||
"""
|
||||
Tests for ImagingCore.stretch functionality.
|
||||
"""
|
||||
from itertools import permutations
|
||||
|
||||
from helper import unittest, PillowTestCase
|
||||
|
||||
from PIL import Image
|
||||
|
||||
|
||||
im = Image.open("Tests/images/hopper.ppm").copy()
|
||||
|
||||
|
||||
class TestImagingStretch(PillowTestCase):
|
||||
|
||||
def stretch(self, im, size, f):
|
||||
return im._new(im.im.stretch(size, f))
|
||||
|
||||
def test_modes(self):
|
||||
self.assertRaises(ValueError, im.convert("1").im.stretch,
|
||||
(15, 12), Image.ANTIALIAS)
|
||||
self.assertRaises(ValueError, im.convert("P").im.stretch,
|
||||
(15, 12), Image.ANTIALIAS)
|
||||
for mode in ["L", "I", "F", "RGB", "RGBA", "CMYK", "YCbCr"]:
|
||||
s = im.convert(mode).im
|
||||
r = s.stretch((15, 12), Image.ANTIALIAS)
|
||||
self.assertEqual(r.mode, mode)
|
||||
self.assertEqual(r.size, (15, 12))
|
||||
self.assertEqual(r.bands, s.bands)
|
||||
|
||||
def test_reduce_filters(self):
|
||||
# There is no Image.NEAREST because im.stretch implementation
|
||||
# is not NEAREST for reduction. It should be removed
|
||||
# or renamed to supersampling.
|
||||
for f in [Image.BILINEAR, Image.BICUBIC, Image.ANTIALIAS]:
|
||||
r = im.im.stretch((15, 12), f)
|
||||
self.assertEqual(r.mode, "RGB")
|
||||
self.assertEqual(r.size, (15, 12))
|
||||
|
||||
def test_enlarge_filters(self):
|
||||
for f in [Image.BILINEAR, Image.BICUBIC, Image.ANTIALIAS]:
|
||||
r = im.im.stretch((764, 414), f)
|
||||
self.assertEqual(r.mode, "RGB")
|
||||
self.assertEqual(r.size, (764, 414))
|
||||
|
||||
def test_endianness(self):
|
||||
# Make an image with one colored pixel, in one channel.
|
||||
# When stretched, that channel should be the same as a GS image.
|
||||
# Other channels should be unaffected.
|
||||
# The R and A channels should not swap, which is indicitive of
|
||||
# an endianness issues.
|
||||
|
||||
samples = {
|
||||
'blank': Image.new('L', (2, 2), 0),
|
||||
'filled': Image.new('L', (2, 2), 255),
|
||||
'dirty': Image.new('L', (2, 2), 0),
|
||||
}
|
||||
samples['dirty'].putpixel((1, 1), 128)
|
||||
|
||||
for f in [Image.BILINEAR, Image.BICUBIC, Image.ANTIALIAS]:
|
||||
# samples resized with current filter
|
||||
resized = dict(
|
||||
(name, self.stretch(ch, (4, 4), f))
|
||||
for name, ch in samples.items()
|
||||
)
|
||||
|
||||
for mode, channels_set in [
|
||||
('RGB', ('blank', 'filled', 'dirty')),
|
||||
('RGBA', ('blank', 'blank', 'filled', 'dirty')),
|
||||
('LA', ('filled', 'dirty')),
|
||||
]:
|
||||
for channels in set(permutations(channels_set)):
|
||||
# compile image from different channels permutations
|
||||
im = Image.merge(mode, [samples[ch] for ch in channels])
|
||||
stretched = self.stretch(im, (4, 4), f)
|
||||
|
||||
for i, ch in enumerate(stretched.split()):
|
||||
# check what resized channel in image is the same
|
||||
# as separately resized channel
|
||||
self.assert_image_equal(ch, resized[channels[i]])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
||||
# End of file
|
46
_imaging.c
46
_imaging.c
|
@ -1514,9 +1514,26 @@ _resize(ImagingObject* self, PyObject* args)
|
|||
|
||||
imIn = self->image;
|
||||
|
||||
imOut = ImagingNew(imIn->mode, xsize, ysize);
|
||||
if (imOut)
|
||||
(void) ImagingResize(imOut, imIn, filter);
|
||||
if (imIn->xsize == xsize && imIn->ysize == ysize) {
|
||||
imOut = ImagingCopy(imIn);
|
||||
}
|
||||
else if ( ! filter) {
|
||||
double a[6];
|
||||
|
||||
memset(a, 0, sizeof a);
|
||||
a[1] = (double) imIn->xsize / xsize;
|
||||
a[5] = (double) imIn->ysize / ysize;
|
||||
|
||||
imOut = ImagingNew(imIn->mode, xsize, ysize);
|
||||
|
||||
imOut = ImagingTransformAffine(
|
||||
imOut, imIn,
|
||||
0, 0, xsize, ysize,
|
||||
a, filter, 1);
|
||||
}
|
||||
else {
|
||||
imOut = ImagingResample(imIn, xsize, ysize, filter);
|
||||
}
|
||||
|
||||
return PyImagingNew(imOut);
|
||||
}
|
||||
|
@ -1610,25 +1627,6 @@ im_setmode(ImagingObject* self, PyObject* args)
|
|||
return Py_None;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
_stretch(ImagingObject* self, PyObject* args)
|
||||
{
|
||||
Imaging imIn, imOut;
|
||||
|
||||
int xsize, ysize;
|
||||
int filter = IMAGING_TRANSFORM_NEAREST;
|
||||
if (!PyArg_ParseTuple(args, "(ii)|i", &xsize, &ysize, &filter))
|
||||
return NULL;
|
||||
|
||||
imIn = self->image;
|
||||
|
||||
imOut = ImagingStretch(imIn, xsize, ysize, filter);
|
||||
if ( ! imOut) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return PyImagingNew(imOut);
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
_transform2(ImagingObject* self, PyObject* args)
|
||||
|
@ -3031,8 +3029,10 @@ static struct PyMethodDef methods[] = {
|
|||
{"rankfilter", (PyCFunction)_rankfilter, 1},
|
||||
#endif
|
||||
{"resize", (PyCFunction)_resize, 1},
|
||||
// There were two methods for image resize before.
|
||||
// Starting from Pillow 2.7.0 stretch is depreciated.
|
||||
{"stretch", (PyCFunction)_resize, 1},
|
||||
{"rotate", (PyCFunction)_rotate, 1},
|
||||
{"stretch", (PyCFunction)_stretch, 1},
|
||||
{"transpose", (PyCFunction)_transpose, 1},
|
||||
{"transform2", (PyCFunction)_transform2, 1},
|
||||
|
||||
|
|
|
@ -89,25 +89,21 @@ pixel, the Python Imaging Library provides four different resampling *filters*.
|
|||
Pick the nearest pixel from the input image. Ignore all other input pixels.
|
||||
|
||||
``BILINEAR``
|
||||
Use linear interpolation over a 2x2 environment in the input image. Note
|
||||
that in the current version of PIL, this filter uses a fixed input
|
||||
environment when downsampling.
|
||||
For resize calculate the output pixel value using linear interpolation
|
||||
on all pixels that may contribute to the output value.
|
||||
For other transformations linear interpolation over a 2x2 environment
|
||||
in the input image is used.
|
||||
|
||||
``BICUBIC``
|
||||
Use cubic interpolation over a 4x4 environment in the input image. Note
|
||||
that in the current version of PIL, this filter uses a fixed input
|
||||
environment when downsampling.
|
||||
For resize calculate the output pixel value using cubic interpolation
|
||||
on all pixels that may contribute to the output value.
|
||||
For other transformations cubic interpolation over a 4x4 environment
|
||||
in the input image is used.
|
||||
|
||||
``ANTIALIAS``
|
||||
Calculate the output pixel value using a high-quality resampling filter (a
|
||||
Calculate the output pixel value using a high-quality Lanczos filter (a
|
||||
truncated sinc) on all pixels that may contribute to the output value. In
|
||||
the current version of PIL, this filter can only be used with the resize
|
||||
and thumbnail methods.
|
||||
|
||||
.. versionadded:: 1.1.3
|
||||
|
||||
Note that in the current version of PIL, the ``ANTIALIAS`` filter is the only
|
||||
filter that behaves properly when downsampling (that is, when converting a
|
||||
large image to a small one). The ``BILINEAR`` and ``BICUBIC`` filters use a
|
||||
fixed input environment, and are best used for scale-preserving geometric
|
||||
transforms and upsamping.
|
||||
|
|
|
@ -979,30 +979,6 @@ ImagingTransformQuad(Imaging imOut, Imaging imIn,
|
|||
/* -------------------------------------------------------------------- */
|
||||
/* Convenience functions */
|
||||
|
||||
Imaging
|
||||
ImagingResize(Imaging imOut, Imaging imIn, int filterid)
|
||||
{
|
||||
double a[6];
|
||||
|
||||
if (imOut->xsize == imIn->xsize && imOut->ysize == imIn->ysize)
|
||||
return ImagingCopy2(imOut, imIn);
|
||||
|
||||
memset(a, 0, sizeof a);
|
||||
a[1] = (double) imIn->xsize / imOut->xsize;
|
||||
a[5] = (double) imIn->ysize / imOut->ysize;
|
||||
|
||||
if (!filterid && imIn->type != IMAGING_TYPE_SPECIAL)
|
||||
return ImagingScaleAffine(
|
||||
imOut, imIn,
|
||||
0, 0, imOut->xsize, imOut->ysize,
|
||||
a, 1);
|
||||
|
||||
return ImagingTransformAffine(
|
||||
imOut, imIn,
|
||||
0, 0, imOut->xsize, imOut->ysize,
|
||||
a, filterid, 1);
|
||||
}
|
||||
|
||||
Imaging
|
||||
ImagingRotate(Imaging imOut, Imaging imIn, double theta, int filterid)
|
||||
{
|
||||
|
|
|
@ -286,13 +286,12 @@ extern Imaging ImagingPointTransform(
|
|||
Imaging imIn, double scale, double offset);
|
||||
extern Imaging ImagingPutBand(Imaging im, Imaging imIn, int band);
|
||||
extern Imaging ImagingRankFilter(Imaging im, int size, int rank);
|
||||
extern Imaging ImagingResize(Imaging imOut, Imaging imIn, int filter);
|
||||
extern Imaging ImagingRotate(
|
||||
Imaging imOut, Imaging imIn, double theta, int filter);
|
||||
extern Imaging ImagingRotate90(Imaging imOut, Imaging imIn);
|
||||
extern Imaging ImagingRotate180(Imaging imOut, Imaging imIn);
|
||||
extern Imaging ImagingRotate270(Imaging imOut, Imaging imIn);
|
||||
extern Imaging ImagingStretch(Imaging imIn, int xsize, int ysize, int filter);
|
||||
extern Imaging ImagingResample(Imaging imIn, int xsize, int ysize, int filter);
|
||||
extern Imaging ImagingTranspose(Imaging imOut, Imaging imIn);
|
||||
extern Imaging ImagingTransposeToNew(Imaging imIn);
|
||||
extern Imaging ImagingTransformPerspective(
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* The Python Imaging Library
|
||||
* $Id$
|
||||
*
|
||||
* pilopen antialiasing support
|
||||
* Pillow image resamling support
|
||||
*
|
||||
* history:
|
||||
* 2002-03-09 fl Created (for PIL 1.1.3)
|
||||
|
@ -17,8 +17,6 @@
|
|||
|
||||
#include <math.h>
|
||||
|
||||
/* resampling filters (from antialias.py) */
|
||||
|
||||
struct filter {
|
||||
float (*filter)(float x);
|
||||
float support;
|
||||
|
@ -42,15 +40,6 @@ static inline float antialias_filter(float x)
|
|||
|
||||
static struct filter ANTIALIAS = { antialias_filter, 3.0 };
|
||||
|
||||
static inline float nearest_filter(float x)
|
||||
{
|
||||
if (-0.5 <= x && x < 0.5)
|
||||
return 1.0;
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
static struct filter NEAREST = { nearest_filter, 0.5 };
|
||||
|
||||
static inline float bilinear_filter(float x)
|
||||
{
|
||||
if (x < 0.0)
|
||||
|
@ -106,7 +95,7 @@ static float inline i2f(int v) { return (float) v; }
|
|||
|
||||
|
||||
Imaging
|
||||
ImagingStretchHorizontal(Imaging imIn, int xsize, int filter)
|
||||
ImagingResampleHorizontal(Imaging imIn, int xsize, int filter)
|
||||
{
|
||||
ImagingSectionCookie cookie;
|
||||
Imaging imOut;
|
||||
|
@ -119,9 +108,6 @@ ImagingStretchHorizontal(Imaging imIn, int xsize, int filter)
|
|||
|
||||
/* check filter */
|
||||
switch (filter) {
|
||||
case IMAGING_TRANSFORM_NEAREST:
|
||||
filterp = &NEAREST;
|
||||
break;
|
||||
case IMAGING_TRANSFORM_ANTIALIAS:
|
||||
filterp = &ANTIALIAS;
|
||||
break;
|
||||
|
@ -152,7 +138,7 @@ ImagingStretchHorizontal(Imaging imIn, int xsize, int filter)
|
|||
/* maximum number of coofs */
|
||||
kmax = (int) ceil(support) * 2 + 1;
|
||||
|
||||
/* coefficient buffer (with rounding safety margin) */
|
||||
/* coefficient buffer */
|
||||
kk = malloc(xsize * kmax * sizeof(float));
|
||||
if ( ! kk)
|
||||
return (Imaging) ImagingError_MemoryError();
|
||||
|
@ -208,7 +194,7 @@ ImagingStretchHorizontal(Imaging imIn, int xsize, int filter)
|
|||
ss += i2f(imIn->image8[yy][x]) * k[x - xmin];
|
||||
imOut->image8[yy][xx] = clip8(ss);
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
switch(imIn->type) {
|
||||
case IMAGING_TYPE_UINT8:
|
||||
/* n-bit grayscale */
|
||||
|
@ -283,13 +269,8 @@ ImagingStretchHorizontal(Imaging imIn, int xsize, int filter)
|
|||
IMAGING_PIXEL_F(imOut, xx, yy) = ss;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ImagingSectionLeave(&cookie);
|
||||
ImagingDelete(imOut);
|
||||
free(kk);
|
||||
free(xbounds);
|
||||
return (Imaging) ImagingError_ModeError();
|
||||
}
|
||||
}
|
||||
}
|
||||
ImagingSectionLeave(&cookie);
|
||||
free(kk);
|
||||
|
@ -299,7 +280,7 @@ ImagingStretchHorizontal(Imaging imIn, int xsize, int filter)
|
|||
|
||||
|
||||
Imaging
|
||||
ImagingStretch(Imaging imIn, int xsize, int ysize, int filter)
|
||||
ImagingResample(Imaging imIn, int xsize, int ysize, int filter)
|
||||
{
|
||||
Imaging imTemp1, imTemp2, imTemp3;
|
||||
Imaging imOut;
|
||||
|
@ -307,8 +288,11 @@ ImagingStretch(Imaging imIn, int xsize, int ysize, int filter)
|
|||
if (strcmp(imIn->mode, "P") == 0 || strcmp(imIn->mode, "1") == 0)
|
||||
return (Imaging) ImagingError_ModeError();
|
||||
|
||||
if (imIn->type == IMAGING_TYPE_SPECIAL)
|
||||
return (Imaging) ImagingError_ModeError();
|
||||
|
||||
/* two-pass resize, first pass */
|
||||
imTemp1 = ImagingStretchHorizontal(imIn, xsize, filter);
|
||||
imTemp1 = ImagingResampleHorizontal(imIn, xsize, filter);
|
||||
if ( ! imTemp1)
|
||||
return NULL;
|
||||
|
||||
|
@ -319,7 +303,7 @@ ImagingStretch(Imaging imIn, int xsize, int ysize, int filter)
|
|||
return NULL;
|
||||
|
||||
/* second pass */
|
||||
imTemp3 = ImagingStretchHorizontal(imTemp2, ysize, filter);
|
||||
imTemp3 = ImagingResampleHorizontal(imTemp2, ysize, filter);
|
||||
ImagingDelete(imTemp2);
|
||||
if ( ! imTemp3)
|
||||
return NULL;
|
2
setup.py
2
setup.py
|
@ -26,7 +26,7 @@ _IMAGING = (
|
|||
"decode", "encode", "map", "display", "outline", "path")
|
||||
|
||||
_LIB_IMAGING = (
|
||||
"Access", "AlphaComposite", "Antialias", "Bands", "BitDecode", "Blend",
|
||||
"Access", "AlphaComposite", "Resample", "Bands", "BitDecode", "Blend",
|
||||
"Chops", "Convert", "ConvertYCbCr", "Copy", "Crc32", "Crop", "Dib", "Draw",
|
||||
"Effects", "EpsEncode", "File", "Fill", "Filter", "FliDecode",
|
||||
"Geometry", "GetBBox", "GifDecode", "GifEncode", "HexDecode",
|
||||
|
|
Loading…
Reference in New Issue
Block a user