Pillow/src/libImaging/RankFilter.c

133 lines
5.2 KiB
C
Raw Normal View History

2010-07-31 06:52:47 +04:00
/*
* 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 */
2021-01-03 06:17:51 +03:00
#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]; \
}
2010-07-31 06:52:47 +04:00
2021-01-03 06:17:51 +03:00
MakeRankFunction(UINT8) MakeRankFunction(INT32) MakeRankFunction(FLOAT32)
2010-07-31 06:52:47 +04:00
2021-01-03 06:17:51 +03:00
Imaging ImagingRankFilter(Imaging im, int size, int rank) {
2010-07-31 06:52:47 +04:00
Imaging imOut = NULL;
int x, y;
int i, margin, size2;
2020-05-10 12:56:36 +03:00
if (!im || im->bands != 1 || im->type == IMAGING_TYPE_SPECIAL) {
2021-01-03 06:17:51 +03:00
return (Imaging)ImagingError_ModeError();
2020-05-10 12:56:36 +03:00
}
2010-07-31 06:52:47 +04:00
2020-05-10 12:56:36 +03:00
if (!(size & 1)) {
2021-01-03 06:17:51 +03:00
return (Imaging)ImagingError_ValueError("bad filter size");
2020-05-10 12:56:36 +03:00
}
2016-09-03 05:23:42 +03:00
2016-03-16 14:47:18 +03:00
/* malloc check ok, for overflow in the define below */
2021-01-03 06:17:51 +03:00
if (size > INT_MAX / size || size > INT_MAX / (size * (int)sizeof(FLOAT32))) {
return (Imaging)ImagingError_ValueError("filter size too large");
2016-03-16 14:47:18 +03:00
}
2010-07-31 06:52:47 +04:00
size2 = size * size;
2021-01-03 06:17:51 +03:00
margin = (size - 1) / 2;
2010-07-31 06:52:47 +04:00
2020-05-10 12:56:36 +03:00
if (rank < 0 || rank >= size2) {
2021-01-03 06:17:51 +03:00
return (Imaging)ImagingError_ValueError("bad rank value");
2020-05-10 12:56:36 +03:00
}
2010-07-31 06:52:47 +04:00
2021-01-03 06:17:51 +03:00
imOut = ImagingNew(im->mode, im->xsize - 2 * margin, im->ysize - 2 * margin);
2020-05-10 12:56:36 +03:00
if (!imOut) {
2016-03-16 14:23:45 +03:00
return NULL;
2020-05-10 12:56:36 +03:00
}
2010-07-31 06:52:47 +04:00
2016-06-16 11:07:28 +03:00
/* malloc check ok, checked above */
2021-01-03 06:17:51 +03:00
#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)
2010-07-31 06:52:47 +04:00
2020-05-10 12:56:36 +03:00
if (im->image8) {
2010-07-31 06:52:47 +04:00
RANK_BODY(UINT8);
2020-05-10 12:56:36 +03:00
} else if (im->type == IMAGING_TYPE_INT32) {
2010-07-31 06:52:47 +04:00
RANK_BODY(INT32);
2020-05-10 12:56:36 +03:00
} else if (im->type == IMAGING_TYPE_FLOAT32) {
2010-07-31 06:52:47 +04:00
RANK_BODY(FLOAT32);
2020-05-10 12:56:36 +03:00
} else {
2010-07-31 06:52:47 +04:00
/* safety net (we shouldn't end up here) */
ImagingDelete(imOut);
2021-01-03 06:17:51 +03:00
return (Imaging)ImagingError_ModeError();
2010-07-31 06:52:47 +04:00
}
ImagingCopyPalette(imOut, im);
2010-07-31 06:52:47 +04:00
return imOut;
nomemory:
ImagingDelete(imOut);
2021-01-03 06:17:51 +03:00
return (Imaging)ImagingError_MemoryError();
2010-07-31 06:52:47 +04:00
}