1 /*****************************************************************************
2 * This file is part of gfxprim library. *
4 * Gfxprim is free software; you can redistribute it and/or *
5 * modify it under the terms of the GNU Lesser General Public *
6 * License as published by the Free Software Foundation; either *
7 * version 2.1 of the License, or (at your option) any later version. *
9 * Gfxprim is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
12 * Lesser General Public License for more details. *
14 * You should have received a copy of the GNU Lesser General Public *
15 * License along with gfxprim; if not, write to the Free Software *
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
17 * Boston, MA 02110-1301 USA *
19 * Copyright (C) 2009-2013 Cyril Hrubis <metan@ucw.cz> *
21 *****************************************************************************/
25 #include "core/GP_Pixmap.h"
26 #include "core/GP_GetPutPixel.h"
27 #include "core/GP_TempAlloc.h"
28 #include "core/GP_Clamp.h"
29 #include "core/GP_Common.h"
31 #include "core/GP_Debug.h"
37 static int GP_FilterSigma_Raw(const GP_Pixmap
*src
,
38 GP_Coord x_src
, GP_Coord y_src
,
39 GP_Size w_src
, GP_Size h_src
,
41 GP_Coord x_dst
, GP_Coord y_dst
,
43 unsigned int min
, float sigma
,
44 GP_ProgressCallback
*callback
)
49 if (src
->pixel_type
!= GP_PIXEL_RGB888
) {
54 GP_DEBUG(1, "Sigma Mean filter size %ux%u xrad=%u yrad=%u sigma=%.2f",
55 w_src
, h_src
, xrad
, yrad
, sigma
);
57 unsigned int R_sigma
= 255 * sigma
;
58 unsigned int G_sigma
= 255 * sigma
;
59 unsigned int B_sigma
= 255 * sigma
;
61 unsigned int xdiam
= 2 * xrad
+ 1;
62 unsigned int ydiam
= 2 * yrad
+ 1;
64 unsigned int w
= w_src
+ xdiam
;
65 unsigned int size
= w
* ydiam
;
67 GP_TempAllocCreate(temp
, 3 * size
* sizeof(unsigned int));
69 unsigned int *R
= GP_TempAllocGet(temp
, size
* sizeof(unsigned int));
70 unsigned int *G
= GP_TempAllocGet(temp
, size
* sizeof(unsigned int));
71 unsigned int *B
= GP_TempAllocGet(temp
, size
* sizeof(unsigned int));
73 /* prefil the sampled array */
74 for (x
= 0; x
< (int)w
; x
++) {
75 int xi
= GP_CLAMP(x_src
+ x
- xrad
, 0, (int)src
->w
- 1);
77 for (y
= 0; y
< (int)ydiam
; y
++) {
78 int yi
= GP_CLAMP(y_src
+ y
- yrad
, 0, (int)src
->h
- 1);
80 GP_Pixel pix
= GP_GetPixel_Raw_24BPP(src
, xi
, yi
);
82 R
[y
* w
+ x
] = GP_Pixel_GET_R_RGB888(pix
);
83 G
[y
* w
+ x
] = GP_Pixel_GET_G_RGB888(pix
);
84 B
[y
* w
+ x
] = GP_Pixel_GET_B_RGB888(pix
);
100 unsigned int cnt
= xdiam
* ydiam
- 1;
102 /* center pixel ypsilon in the buffer */
103 unsigned int yc
= yrad
;
104 /* last sampled ypsilon in the buffer */
107 /* Apply the sigma mean filter */
108 for (y
= 0; y
< (int)h_src
; y
++) {
109 for (x
= 0; x
< (int)w_src
; x
++) {
110 /* Get center pixel */
111 unsigned int R_center
= R
[yc
* w
+ x
+ xrad
];
112 unsigned int G_center
= G
[yc
* w
+ x
+ xrad
];
113 unsigned int B_center
= B
[yc
* w
+ x
+ xrad
];
115 /* Reset sum counters */
128 for (x1
= 0; x1
< xdiam
; x1
++) {
129 for (y1
= 0; y1
< ydiam
; y1
++) {
130 unsigned int R_cur
= R
[y1
* w
+ x
+ x1
];
131 unsigned int G_cur
= G
[y1
* w
+ x
+ x1
];
132 unsigned int B_cur
= B
[y1
* w
+ x
+ x1
];
138 if (abs(R_cur
- R_center
) < R_sigma
) {
143 if (abs(G_cur
- G_center
) < G_sigma
) {
148 if (abs(B_cur
- B_center
) < B_sigma
) {
178 GP_PutPixel_Raw_24BPP(dst
, x_dst
+ x
, y_dst
+ y
,
179 GP_Pixel_CREATE_RGB888(r
, g
, b
));
182 int yi
= GP_CLAMP(y_src
+ y
+ yrad
+ 1, 0, (int)src
->h
- 1);
184 for (x
= 0; x
< (int)w
; x
++) {
185 int xi
= GP_CLAMP(x_src
+ x
- xrad
, 0, (int)src
->w
- 1);
187 GP_Pixel pix
= GP_GetPixel_Raw_24BPP(src
, xi
, yi
);
189 R
[yl
* w
+ x
] = GP_Pixel_GET_R_RGB888(pix
);
190 G
[yl
* w
+ x
] = GP_Pixel_GET_G_RGB888(pix
);
191 B
[yl
* w
+ x
] = GP_Pixel_GET_B_RGB888(pix
);
197 if (GP_ProgressCallbackReport(callback
, y
, h_src
, w_src
)) {
198 GP_TempAllocFree(temp
);
203 GP_TempAllocFree(temp
);
204 GP_ProgressCallbackDone(callback
);
209 int GP_FilterSigmaEx(const GP_Pixmap
*src
,
210 GP_Coord x_src
, GP_Coord y_src
,
211 GP_Size w_src
, GP_Size h_src
,
213 GP_Coord x_dst
, GP_Coord y_dst
,
215 unsigned int min
, float sigma
,
216 GP_ProgressCallback
*callback
)
218 GP_CHECK(src
->pixel_type
== dst
->pixel_type
);
220 /* Check that destination is large enough */
221 GP_CHECK(x_dst
+ (GP_Coord
)w_src
<= (GP_Coord
)dst
->w
);
222 GP_CHECK(y_dst
+ (GP_Coord
)h_src
<= (GP_Coord
)dst
->h
);
224 GP_CHECK(xrad
>= 0 && yrad
>= 0);
226 return GP_FilterSigma_Raw(src
, x_src
, y_src
, w_src
, h_src
,
227 dst
, x_dst
, y_dst
, xrad
, yrad
, min
, sigma
,
231 GP_Pixmap
*GP_FilterSigmaExAlloc(const GP_Pixmap
*src
,
232 GP_Coord x_src
, GP_Coord y_src
,
233 GP_Size w_src
, GP_Size h_src
,
235 unsigned int min
, float sigma
,
236 GP_ProgressCallback
*callback
)
240 GP_CHECK(xrad
>= 0 && yrad
>= 0);
242 GP_Pixmap
*dst
= GP_PixmapAlloc(w_src
, h_src
, src
->pixel_type
);
247 ret
= GP_FilterSigma_Raw(src
, x_src
, y_src
, w_src
, h_src
,
248 dst
, 0, 0, xrad
, yrad
, min
, sigma
, callback
);