mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-28 02:46:18 +03:00
133 lines
5.2 KiB
C
133 lines
5.2 KiB
C
/*
|
|
* The Python Imaging Library
|
|
* $Id$
|
|
*
|
|
* min, max, median filters
|
|
*
|
|
* history:
|
|
* 2002-06-08 fl Created
|
|
*
|
|
* Copyright (c) Secret Labs AB 2002. All rights reserved.
|
|
*
|
|
* See the README file for information on usage and redistribution.
|
|
*/
|
|
|
|
#include "Imaging.h"
|
|
|
|
/* Fast rank algorithm (due to Wirth), based on public domain code
|
|
by Nicolas Devillard, available at http://ndevilla.free.fr */
|
|
|
|
#define SWAP(type, a, b) \
|
|
{ \
|
|
register type t = (a); \
|
|
(a) = (b); \
|
|
(b) = t; \
|
|
}
|
|
|
|
#define MakeRankFunction(type) \
|
|
static type Rank##type(type a[], int n, int k) { \
|
|
register int i, j, l, m; \
|
|
register type x; \
|
|
l = 0; \
|
|
m = n - 1; \
|
|
while (l < m) { \
|
|
x = a[k]; \
|
|
i = l; \
|
|
j = m; \
|
|
do { \
|
|
while (a[i] < x) { \
|
|
i++; \
|
|
} \
|
|
while (x < a[j]) { \
|
|
j--; \
|
|
} \
|
|
if (i <= j) { \
|
|
SWAP(type, a[i], a[j]); \
|
|
i++; \
|
|
j--; \
|
|
} \
|
|
} while (i <= j); \
|
|
if (j < k) { \
|
|
l = i; \
|
|
} \
|
|
if (k < i) { \
|
|
m = j; \
|
|
} \
|
|
} \
|
|
return a[k]; \
|
|
}
|
|
|
|
MakeRankFunction(UINT8) MakeRankFunction(INT32) MakeRankFunction(FLOAT32)
|
|
|
|
Imaging ImagingRankFilter(Imaging im, int size, int rank) {
|
|
Imaging imOut = NULL;
|
|
int x, y;
|
|
int i, margin, size2;
|
|
|
|
if (!im || im->bands != 1 || im->type == IMAGING_TYPE_SPECIAL) {
|
|
return (Imaging)ImagingError_ModeError();
|
|
}
|
|
|
|
if (!(size & 1)) {
|
|
return (Imaging)ImagingError_ValueError("bad filter size");
|
|
}
|
|
|
|
/* malloc check ok, for overflow in the define below */
|
|
if (size > INT_MAX / size || size > INT_MAX / (size * (int)sizeof(FLOAT32))) {
|
|
return (Imaging)ImagingError_ValueError("filter size too large");
|
|
}
|
|
|
|
size2 = size * size;
|
|
margin = (size - 1) / 2;
|
|
|
|
if (rank < 0 || rank >= size2) {
|
|
return (Imaging)ImagingError_ValueError("bad rank value");
|
|
}
|
|
|
|
imOut = ImagingNew(im->mode, im->xsize - 2 * margin, im->ysize - 2 * margin);
|
|
if (!imOut) {
|
|
return NULL;
|
|
}
|
|
|
|
/* malloc check ok, checked above */
|
|
#define RANK_BODY(type) \
|
|
do { \
|
|
type *buf = malloc(size2 * sizeof(type)); \
|
|
if (!buf) { \
|
|
goto nomemory; \
|
|
} \
|
|
for (y = 0; y < imOut->ysize; y++) { \
|
|
for (x = 0; x < imOut->xsize; x++) { \
|
|
for (i = 0; i < size; i++) { \
|
|
memcpy( \
|
|
buf + i * size, \
|
|
&IMAGING_PIXEL_##type(im, x, y + i), \
|
|
size * sizeof(type)); \
|
|
} \
|
|
IMAGING_PIXEL_##type(imOut, x, y) = Rank##type(buf, size2, rank); \
|
|
} \
|
|
} \
|
|
free(buf); \
|
|
} while (0)
|
|
|
|
if (im->image8) {
|
|
RANK_BODY(UINT8);
|
|
} else if (im->type == IMAGING_TYPE_INT32) {
|
|
RANK_BODY(INT32);
|
|
} else if (im->type == IMAGING_TYPE_FLOAT32) {
|
|
RANK_BODY(FLOAT32);
|
|
} else {
|
|
/* safety net (we shouldn't end up here) */
|
|
ImagingDelete(imOut);
|
|
return (Imaging)ImagingError_ModeError();
|
|
}
|
|
|
|
ImagingCopyPalette(imOut, im);
|
|
|
|
return imOut;
|
|
|
|
nomemory:
|
|
ImagingDelete(imOut);
|
|
return (Imaging)ImagingError_MemoryError();
|
|
}
|