mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-04-29 13:33:43 +03:00
update tests and docs
This commit is contained in:
parent
9f805f9e69
commit
81c115825b
|
@ -309,6 +309,8 @@ class TestCoreResampleAlphaCorrect:
|
|||
self.run_levels_case(case.resize((512, 32), Image.Resampling.HAMMING))
|
||||
self.run_levels_case(case.resize((512, 32), Image.Resampling.BICUBIC))
|
||||
self.run_levels_case(case.resize((512, 32), Image.Resampling.LANCZOS))
|
||||
self.run_levels_case(case.resize((512, 32), Image.Resampling.MKS2013))
|
||||
self.run_levels_case(case.resize((512, 32), Image.Resampling.MKS2021))
|
||||
|
||||
@pytest.mark.xfail(reason="Current implementation isn't precise enough")
|
||||
def test_levels_la(self) -> None:
|
||||
|
@ -318,6 +320,8 @@ class TestCoreResampleAlphaCorrect:
|
|||
self.run_levels_case(case.resize((512, 32), Image.Resampling.HAMMING))
|
||||
self.run_levels_case(case.resize((512, 32), Image.Resampling.BICUBIC))
|
||||
self.run_levels_case(case.resize((512, 32), Image.Resampling.LANCZOS))
|
||||
self.run_levels_case(case.resize((512, 32), Image.Resampling.MKS2013))
|
||||
self.run_levels_case(case.resize((512, 32), Image.Resampling.MKS2021))
|
||||
|
||||
def make_dirty_case(
|
||||
self, mode: str, clean_pixel: tuple[int, ...], dirty_pixel: tuple[int, ...]
|
||||
|
@ -360,6 +364,12 @@ class TestCoreResampleAlphaCorrect:
|
|||
self.run_dirty_case(
|
||||
case.resize((20, 20), Image.Resampling.LANCZOS), (255, 255, 0)
|
||||
)
|
||||
self.run_dirty_case(
|
||||
case.resize((20, 20), Image.Resampling.MKS2013), (255, 255, 0)
|
||||
)
|
||||
self.run_dirty_case(
|
||||
case.resize((20, 20), Image.Resampling.MKS2021), (255, 255, 0)
|
||||
)
|
||||
|
||||
def test_dirty_pixels_la(self) -> None:
|
||||
case = self.make_dirty_case("LA", (255, 128), (0, 0))
|
||||
|
@ -368,6 +378,8 @@ class TestCoreResampleAlphaCorrect:
|
|||
self.run_dirty_case(case.resize((20, 20), Image.Resampling.HAMMING), (255,))
|
||||
self.run_dirty_case(case.resize((20, 20), Image.Resampling.BICUBIC), (255,))
|
||||
self.run_dirty_case(case.resize((20, 20), Image.Resampling.LANCZOS), (255,))
|
||||
self.run_dirty_case(case.resize((20, 20), Image.Resampling.MKS2013), (255,))
|
||||
self.run_dirty_case(case.resize((20, 20), Image.Resampling.MKS2021), (255,))
|
||||
|
||||
|
||||
class TestCoreResamplePasses:
|
||||
|
@ -453,6 +465,8 @@ class TestCoreResampleBox:
|
|||
Image.Resampling.HAMMING,
|
||||
Image.Resampling.BICUBIC,
|
||||
Image.Resampling.LANCZOS,
|
||||
Image.Resampling.MKS2013,
|
||||
Image.Resampling.MKS2021,
|
||||
),
|
||||
)
|
||||
def test_wrong_arguments(self, resample: Image.Resampling) -> None:
|
||||
|
|
|
@ -72,6 +72,8 @@ class TestImagingCoreResize:
|
|||
Image.Resampling.HAMMING,
|
||||
Image.Resampling.BICUBIC,
|
||||
Image.Resampling.LANCZOS,
|
||||
Image.Resampling.MKS2013,
|
||||
Image.Resampling.MKS2021,
|
||||
),
|
||||
)
|
||||
def test_reduce_filters(self, resample: Image.Resampling) -> None:
|
||||
|
@ -88,6 +90,8 @@ class TestImagingCoreResize:
|
|||
Image.Resampling.HAMMING,
|
||||
Image.Resampling.BICUBIC,
|
||||
Image.Resampling.LANCZOS,
|
||||
Image.Resampling.MKS2013,
|
||||
Image.Resampling.MKS2021,
|
||||
),
|
||||
)
|
||||
def test_enlarge_filters(self, resample: Image.Resampling) -> None:
|
||||
|
@ -104,6 +108,8 @@ class TestImagingCoreResize:
|
|||
Image.Resampling.HAMMING,
|
||||
Image.Resampling.BICUBIC,
|
||||
Image.Resampling.LANCZOS,
|
||||
Image.Resampling.MKS2013,
|
||||
Image.Resampling.MKS2021,
|
||||
),
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
|
@ -154,6 +160,8 @@ class TestImagingCoreResize:
|
|||
Image.Resampling.HAMMING,
|
||||
Image.Resampling.BICUBIC,
|
||||
Image.Resampling.LANCZOS,
|
||||
Image.Resampling.MKS2013,
|
||||
Image.Resampling.MKS2021,
|
||||
),
|
||||
)
|
||||
def test_enlarge_zero(self, resample: Image.Resampling) -> None:
|
||||
|
|
|
@ -195,6 +195,23 @@ pixel, the Python Imaging Library provides different resampling *filters*.
|
|||
|
||||
.. versionadded:: 1.1.3
|
||||
|
||||
.. data:: Resampling.MKS2013
|
||||
:noindex:
|
||||
|
||||
Calculate the output pixel value using the Magic Kernel Sharp 2013 filter
|
||||
(a quadratic B-spline composed with a sharpening kernel) on all pixels that
|
||||
may contribute to the output value. This filter can only be used with the
|
||||
:py:meth:`~PIL.Image.Image.resize` and :py:meth:`~PIL.Image.Image.thumbnail`
|
||||
methods.
|
||||
|
||||
.. data:: Resampling.MKS2021
|
||||
:noindex:
|
||||
|
||||
Calculate the output pixel value using the Magic Kernel Sharp 2021 filter
|
||||
(a quadratic B-spline composed with a sharpening kernel) on all pixels that
|
||||
may contribute to the output value. This filter can only be used with the
|
||||
:py:meth:`~PIL.Image.Image.resize` and :py:meth:`~PIL.Image.Image.thumbnail`
|
||||
methods.
|
||||
|
||||
Filters comparison table
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -215,3 +232,7 @@ Filters comparison table
|
|||
+---------------------------+-------------+-----------+-------------+
|
||||
|:data:`Resampling.LANCZOS` | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐ |
|
||||
+---------------------------+-------------+-----------+-------------+
|
||||
|:data:`Resampling.MKS2013` | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | ⭐ |
|
||||
+---------------------------+-------------+-----------+-------------+
|
||||
|:data:`Resampling.MKS2021` | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ⭐ |
|
||||
+---------------------------+-------------+-----------+-------------+
|
|
@ -169,7 +169,8 @@ class Resampling(IntEnum):
|
|||
HAMMING = 5
|
||||
BICUBIC = 3
|
||||
LANCZOS = 1
|
||||
MKS2021 = 6
|
||||
MKS2013 = 6
|
||||
MKS2021 = 7
|
||||
|
||||
|
||||
_filters_support = {
|
||||
|
@ -178,6 +179,7 @@ _filters_support = {
|
|||
Resampling.HAMMING: 1.0,
|
||||
Resampling.BICUBIC: 2.0,
|
||||
Resampling.LANCZOS: 3.0,
|
||||
Resampling.MKS2013: 2.5,
|
||||
Resampling.MKS2021: 4.5,
|
||||
}
|
||||
|
||||
|
@ -2209,7 +2211,8 @@ class Image:
|
|||
:param resample: An optional resampling filter. This can be
|
||||
one of :py:data:`Resampling.NEAREST`, :py:data:`Resampling.BOX`,
|
||||
:py:data:`Resampling.BILINEAR`, :py:data:`Resampling.HAMMING`,
|
||||
:py:data:`Resampling.BICUBIC` or :py:data:`Resampling.LANCZOS`.
|
||||
:py:data:`Resampling.BICUBIC`, :py:data:`Resampling.LANCZOS`,
|
||||
:py:data:`Resampling.MKS2013`, or :py:data:`Resampling.MKS2021`.
|
||||
If the image has mode "1" or "P", it is always set to
|
||||
:py:data:`Resampling.NEAREST`. If the image mode is "BGR;15",
|
||||
"BGR;16" or "BGR;24", then the default filter is
|
||||
|
@ -2244,6 +2247,7 @@ class Image:
|
|||
Resampling.LANCZOS,
|
||||
Resampling.BOX,
|
||||
Resampling.HAMMING,
|
||||
Resampling.MKS2013,
|
||||
Resampling.MKS2021,
|
||||
):
|
||||
msg = f"Unknown resampling filter ({resample})."
|
||||
|
@ -2257,6 +2261,7 @@ class Image:
|
|||
(Resampling.BICUBIC, "Image.Resampling.BICUBIC"),
|
||||
(Resampling.BOX, "Image.Resampling.BOX"),
|
||||
(Resampling.HAMMING, "Image.Resampling.HAMMING"),
|
||||
(Resampling.MKS2013, "Image.Resampling.MKS2013"),
|
||||
(Resampling.MKS2021, "Image.Resampling.MKS2021"),
|
||||
)
|
||||
]
|
||||
|
@ -2694,7 +2699,8 @@ class Image:
|
|||
:param resample: Optional resampling filter. This can be one
|
||||
of :py:data:`Resampling.NEAREST`, :py:data:`Resampling.BOX`,
|
||||
:py:data:`Resampling.BILINEAR`, :py:data:`Resampling.HAMMING`,
|
||||
:py:data:`Resampling.BICUBIC` or :py:data:`Resampling.LANCZOS`.
|
||||
:py:data:`Resampling.BICUBIC`, :py:data:`Resampling.LANCZOS`,
|
||||
:py:data:`Resampling.MKS2013`, or :py:data:`Resampling.MKS2021`.
|
||||
If omitted, it defaults to :py:data:`Resampling.BICUBIC`.
|
||||
(was :py:data:`Resampling.NEAREST` prior to version 2.5.0).
|
||||
See: :ref:`concept-filters`.
|
||||
|
@ -2912,12 +2918,14 @@ class Image:
|
|||
Resampling.BOX,
|
||||
Resampling.HAMMING,
|
||||
Resampling.LANCZOS,
|
||||
Resampling.MKS2013,
|
||||
Resampling.MKS2021,
|
||||
):
|
||||
unusable: dict[int, str] = {
|
||||
Resampling.BOX: "Image.Resampling.BOX",
|
||||
Resampling.HAMMING: "Image.Resampling.HAMMING",
|
||||
Resampling.LANCZOS: "Image.Resampling.LANCZOS",
|
||||
Resampling.MKS2013: "Image.Resampling.MKS2013",
|
||||
Resampling.MKS2021: "Image.Resampling.MKS2021",
|
||||
}
|
||||
msg = unusable[resample] + f" ({resample}) cannot be used."
|
||||
|
|
|
@ -269,7 +269,8 @@ ImagingError_Clear(void);
|
|||
#define IMAGING_TRANSFORM_HAMMING 5
|
||||
#define IMAGING_TRANSFORM_BICUBIC 3
|
||||
#define IMAGING_TRANSFORM_LANCZOS 1
|
||||
#define IMAGING_TRANSFORM_MKS2021 6
|
||||
#define IMAGING_TRANSFORM_MKS2013 6
|
||||
#define IMAGING_TRANSFORM_MKS2021 7
|
||||
|
||||
typedef int (*ImagingTransformMap)(double *X, double *Y, int x, int y, void *data);
|
||||
typedef int (*ImagingTransformFilter)(void *out, Imaging im, double x, double y);
|
||||
|
|
|
@ -79,6 +79,20 @@ lanczos_filter(double x) {
|
|||
return 0.0;
|
||||
}
|
||||
|
||||
static inline double
|
||||
mks_2013_filter(double x) {
|
||||
/* https://johncostella.com/magic/ */
|
||||
if (x < 0.0)
|
||||
x = -x;
|
||||
if (x < 0.5)
|
||||
return 17.0 / 16.0 - 7.0 / 4.0 * pow(x, 2.0);
|
||||
if (x < 1.5)
|
||||
return (1.0 - x) * (7.0/4.0 - x);
|
||||
if (x < 2.5)
|
||||
return -1.0 / 8.0 * pow(x - 5.0 / 2.0, 2.0);
|
||||
return (0.0);
|
||||
}
|
||||
|
||||
static inline double
|
||||
mks_2021_filter(double x) {
|
||||
/* https://johncostella.com/magic/ */
|
||||
|
@ -102,6 +116,7 @@ static struct filter BILINEAR = {bilinear_filter, 1.0};
|
|||
static struct filter HAMMING = {hamming_filter, 1.0};
|
||||
static struct filter BICUBIC = {bicubic_filter, 2.0};
|
||||
static struct filter LANCZOS = {lanczos_filter, 3.0};
|
||||
static struct filter MKS2013 = {mks_2013_filter, 2.5};
|
||||
static struct filter MKS2021 = {mks_2021_filter, 4.5};
|
||||
|
||||
/* 8 bits for result. Filter can have negative areas.
|
||||
|
@ -712,6 +727,9 @@ ImagingResample(Imaging imIn, int xsize, int ysize, int filter, float box[4]) {
|
|||
case IMAGING_TRANSFORM_LANCZOS:
|
||||
filterp = &LANCZOS;
|
||||
break;
|
||||
case IMAGING_TRANSFORM_MKS2013:
|
||||
filterp = &MKS2013;
|
||||
break;
|
||||
case IMAGING_TRANSFORM_MKS2021:
|
||||
filterp = &MKS2021;
|
||||
break;
|
||||
|
|
Loading…
Reference in New Issue
Block a user