mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-07-03 19:33:07 +03:00
Add support for Magic Kernel Sharp 2021 resampling
This commit is contained in:
parent
b965116982
commit
b430b02a31
|
@ -169,6 +169,7 @@ class Resampling(IntEnum):
|
||||||
HAMMING = 5
|
HAMMING = 5
|
||||||
BICUBIC = 3
|
BICUBIC = 3
|
||||||
LANCZOS = 1
|
LANCZOS = 1
|
||||||
|
MKS2021 = 6
|
||||||
|
|
||||||
|
|
||||||
_filters_support = {
|
_filters_support = {
|
||||||
|
@ -177,6 +178,7 @@ _filters_support = {
|
||||||
Resampling.HAMMING: 1.0,
|
Resampling.HAMMING: 1.0,
|
||||||
Resampling.BICUBIC: 2.0,
|
Resampling.BICUBIC: 2.0,
|
||||||
Resampling.LANCZOS: 3.0,
|
Resampling.LANCZOS: 3.0,
|
||||||
|
Resampling.MKS2021: 4.5,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2242,6 +2244,7 @@ class Image:
|
||||||
Resampling.LANCZOS,
|
Resampling.LANCZOS,
|
||||||
Resampling.BOX,
|
Resampling.BOX,
|
||||||
Resampling.HAMMING,
|
Resampling.HAMMING,
|
||||||
|
Resampling.MKS2021,
|
||||||
):
|
):
|
||||||
msg = f"Unknown resampling filter ({resample})."
|
msg = f"Unknown resampling filter ({resample})."
|
||||||
|
|
||||||
|
@ -2254,6 +2257,7 @@ class Image:
|
||||||
(Resampling.BICUBIC, "Image.Resampling.BICUBIC"),
|
(Resampling.BICUBIC, "Image.Resampling.BICUBIC"),
|
||||||
(Resampling.BOX, "Image.Resampling.BOX"),
|
(Resampling.BOX, "Image.Resampling.BOX"),
|
||||||
(Resampling.HAMMING, "Image.Resampling.HAMMING"),
|
(Resampling.HAMMING, "Image.Resampling.HAMMING"),
|
||||||
|
(Resampling.MKS2021, "Image.Resampling.MKS2021"),
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
msg += f" Use {', '.join(filters[:-1])} or {filters[-1]}"
|
msg += f" Use {', '.join(filters[:-1])} or {filters[-1]}"
|
||||||
|
@ -2904,11 +2908,12 @@ class Image:
|
||||||
Resampling.BILINEAR,
|
Resampling.BILINEAR,
|
||||||
Resampling.BICUBIC,
|
Resampling.BICUBIC,
|
||||||
):
|
):
|
||||||
if resample in (Resampling.BOX, Resampling.HAMMING, Resampling.LANCZOS):
|
if resample in (Resampling.BOX, Resampling.HAMMING, Resampling.LANCZOS, Resampling.MKS2021):
|
||||||
unusable: dict[int, str] = {
|
unusable: dict[int, str] = {
|
||||||
Resampling.BOX: "Image.Resampling.BOX",
|
Resampling.BOX: "Image.Resampling.BOX",
|
||||||
Resampling.HAMMING: "Image.Resampling.HAMMING",
|
Resampling.HAMMING: "Image.Resampling.HAMMING",
|
||||||
Resampling.LANCZOS: "Image.Resampling.LANCZOS",
|
Resampling.LANCZOS: "Image.Resampling.LANCZOS",
|
||||||
|
Resampling.MKS2021: "Image.Resampling.MKS2021",
|
||||||
}
|
}
|
||||||
msg = unusable[resample] + f" ({resample}) cannot be used."
|
msg = unusable[resample] + f" ({resample}) cannot be used."
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -269,6 +269,7 @@ ImagingError_Clear(void);
|
||||||
#define IMAGING_TRANSFORM_HAMMING 5
|
#define IMAGING_TRANSFORM_HAMMING 5
|
||||||
#define IMAGING_TRANSFORM_BICUBIC 3
|
#define IMAGING_TRANSFORM_BICUBIC 3
|
||||||
#define IMAGING_TRANSFORM_LANCZOS 1
|
#define IMAGING_TRANSFORM_LANCZOS 1
|
||||||
|
#define IMAGING_TRANSFORM_MKS2021 6
|
||||||
|
|
||||||
typedef int (*ImagingTransformMap)(double *X, double *Y, int x, int y, void *data);
|
typedef int (*ImagingTransformMap)(double *X, double *Y, int x, int y, void *data);
|
||||||
typedef int (*ImagingTransformFilter)(void *out, Imaging im, double x, double y);
|
typedef int (*ImagingTransformFilter)(void *out, Imaging im, double x, double y);
|
||||||
|
|
|
@ -79,11 +79,30 @@ lanczos_filter(double x) {
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline double
|
||||||
|
mks_2021_filter(double x) {
|
||||||
|
/* https://johncostella.com/magic/ */
|
||||||
|
if (x < 0.0)
|
||||||
|
x = -x;
|
||||||
|
if (x < 0.5)
|
||||||
|
return 577.0/576.0 - 239.0/144.0 * pow(x, 2.0);
|
||||||
|
if (x < 1.5)
|
||||||
|
return 35.0/36.0 * (x - 1.0) * (x - 239.0/140.0);
|
||||||
|
if (x < 2.5)
|
||||||
|
return 1.0/6.0 * (x - 2.0) * (65.0/24.0 - x);
|
||||||
|
if (x < 3.5)
|
||||||
|
return 1.0/36.0 * (x - 3.0) * (x - 15.0/4.0);
|
||||||
|
if (x < 4.5)
|
||||||
|
return -1.0/288.0 * pow(x - 9.0/2.0, 2.0);
|
||||||
|
return(0.0);
|
||||||
|
}
|
||||||
|
|
||||||
static struct filter BOX = {box_filter, 0.5};
|
static struct filter BOX = {box_filter, 0.5};
|
||||||
static struct filter BILINEAR = {bilinear_filter, 1.0};
|
static struct filter BILINEAR = {bilinear_filter, 1.0};
|
||||||
static struct filter HAMMING = {hamming_filter, 1.0};
|
static struct filter HAMMING = {hamming_filter, 1.0};
|
||||||
static struct filter BICUBIC = {bicubic_filter, 2.0};
|
static struct filter BICUBIC = {bicubic_filter, 2.0};
|
||||||
static struct filter LANCZOS = {lanczos_filter, 3.0};
|
static struct filter LANCZOS = {lanczos_filter, 3.0};
|
||||||
|
static struct filter MKS2021 = {mks_2021_filter, 4.5};
|
||||||
|
|
||||||
/* 8 bits for result. Filter can have negative areas.
|
/* 8 bits for result. Filter can have negative areas.
|
||||||
In one cases the sum of the coefficients will be negative,
|
In one cases the sum of the coefficients will be negative,
|
||||||
|
@ -693,6 +712,9 @@ ImagingResample(Imaging imIn, int xsize, int ysize, int filter, float box[4]) {
|
||||||
case IMAGING_TRANSFORM_LANCZOS:
|
case IMAGING_TRANSFORM_LANCZOS:
|
||||||
filterp = &LANCZOS;
|
filterp = &LANCZOS;
|
||||||
break;
|
break;
|
||||||
|
case IMAGING_TRANSFORM_MKS2021:
|
||||||
|
filterp = &MKS2021;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return (Imaging)ImagingError_ValueError("unsupported resampling filter");
|
return (Imaging)ImagingError_ValueError("unsupported resampling filter");
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user