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 */
|
|
|
|
|
|
|
|
#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)
|
2016-03-16 14:23:45 +03:00
|
|
|
return (Imaging) ImagingError_ModeError();
|
2010-07-31 06:52:47 +04:00
|
|
|
|
|
|
|
if (!(size & 1))
|
2016-03-16 14:23:45 +03:00
|
|
|
return (Imaging) ImagingError_ValueError("bad filter size");
|
2016-03-16 14:47:18 +03:00
|
|
|
|
|
|
|
/* malloc check ok, for overflow in the define below */
|
2016-05-21 17:31:19 +03:00
|
|
|
if (size > INT_MAX / size ||
|
|
|
|
size > INT_MAX / (size * sizeof(FLOAT32))) {
|
2016-03-16 14:47:18 +03:00
|
|
|
return (Imaging) ImagingError_ValueError("filter size too large");
|
|
|
|
}
|
2010-07-31 06:52:47 +04:00
|
|
|
|
|
|
|
size2 = size * size;
|
|
|
|
margin = (size-1) / 2;
|
|
|
|
|
|
|
|
if (rank < 0 || rank >= size2)
|
2016-03-16 14:23:45 +03:00
|
|
|
return (Imaging) ImagingError_ValueError("bad rank value");
|
2010-07-31 06:52:47 +04:00
|
|
|
|
|
|
|
imOut = ImagingNew(im->mode, im->xsize - 2*margin, im->ysize - 2*margin);
|
|
|
|
if (!imOut)
|
2016-03-16 14:23:45 +03:00
|
|
|
return NULL;
|
2010-07-31 06:52:47 +04:00
|
|
|
|
2016-06-16 11:07:28 +03:00
|
|
|
/* malloc check ok, checked above */
|
2010-07-31 06:52:47 +04: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);\
|
|
|
|
}\
|
2013-03-18 03:54:02 +04:00
|
|
|
free(buf); \
|
2010-07-31 06:52:47 +04:00
|
|
|
} 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();
|
|
|
|
}
|
2013-07-01 02:42:19 +04:00
|
|
|
|
2010-07-31 06:52:47 +04:00
|
|
|
ImagingCopyInfo(imOut, im);
|
|
|
|
|
|
|
|
return imOut;
|
|
|
|
|
|
|
|
nomemory:
|
|
|
|
ImagingDelete(imOut);
|
|
|
|
return (Imaging) ImagingError_MemoryError();
|
|
|
|
}
|