Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/Imaging/libImaging/RankFilter.c
diff options
context:
space:
mode:
Diffstat (limited to 'Imaging/libImaging/RankFilter.c')
-rw-r--r--Imaging/libImaging/RankFilter.c105
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();
+}