diff options
Diffstat (limited to 'Imaging/libImaging/RankFilter.c')
-rw-r--r-- | Imaging/libImaging/RankFilter.c | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/Imaging/libImaging/RankFilter.c b/Imaging/libImaging/RankFilter.c new file mode 100644 index 0000000..a0f13cd --- /dev/null +++ b/Imaging/libImaging/RankFilter.c @@ -0,0 +1,105 @@ +/* + * The Python Imaging Library + * $Id: RankFilter.c 2929 2006-11-22 21:12:55Z fredrik $ + * + * 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"); + + 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; + +#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);\ + }\ +} 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(); + } + + ImagingCopyInfo(imOut, im); + + return imOut; + +nomemory: + ImagingDelete(imOut); + return (Imaging) ImagingError_MemoryError(); +} |