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 *****************************************************************************/
26 #include <core/GP_Pixmap.h>
27 #include <core/GP_GetPutPixel.h>
28 #include <core/GP_TempAlloc.h>
29 #include <core/GP_Clamp.h>
30 #include <core/GP_Common.h>
31 #include <core/GP_Debug.h>
32 #include <filters/GP_Sigma.h>
34 static int gp_filter_sigma_raw(const gp_pixmap
*src
,
35 gp_coord x_src
, gp_coord y_src
,
36 gp_size w_src
, gp_size h_src
,
38 gp_coord x_dst
, gp_coord y_dst
,
40 unsigned int min
, float sigma
,
41 gp_progress_cb
*callback
)
46 if (src
->pixel_type
!= GP_PIXEL_RGB888
) {
51 GP_DEBUG(1, "Sigma Mean filter size %ux%u xrad=%u yrad=%u sigma=%.2f",
52 w_src
, h_src
, xrad
, yrad
, sigma
);
54 unsigned int R_sigma
= 255 * sigma
;
55 unsigned int G_sigma
= 255 * sigma
;
56 unsigned int B_sigma
= 255 * sigma
;
58 unsigned int xdiam
= 2 * xrad
+ 1;
59 unsigned int ydiam
= 2 * yrad
+ 1;
61 unsigned int w
= w_src
+ xdiam
;
62 unsigned int size
= w
* ydiam
;
64 gp_temp_alloc_create(temp
, 3 * size
* sizeof(unsigned int));
66 unsigned int *R
= gp_temp_alloc_get(temp
, size
* sizeof(unsigned int));
67 unsigned int *G
= gp_temp_alloc_get(temp
, size
* sizeof(unsigned int));
68 unsigned int *B
= gp_temp_alloc_get(temp
, size
* sizeof(unsigned int));
70 /* prefil the sampled array */
71 for (x
= 0; x
< (int)w
; x
++) {
72 int xi
= GP_CLAMP(x_src
+ x
- xrad
, 0, (int)src
->w
- 1);
74 for (y
= 0; y
< (int)ydiam
; y
++) {
75 int yi
= GP_CLAMP(y_src
+ y
- yrad
, 0, (int)src
->h
- 1);
77 gp_pixel pix
= gp_getpixel_raw_24BPP(src
, xi
, yi
);
79 R
[y
* w
+ x
] = GP_PIXEL_GET_R_RGB888(pix
);
80 G
[y
* w
+ x
] = GP_PIXEL_GET_G_RGB888(pix
);
81 B
[y
* w
+ x
] = GP_PIXEL_GET_B_RGB888(pix
);
97 unsigned int cnt
= xdiam
* ydiam
- 1;
99 /* center pixel ypsilon in the buffer */
100 unsigned int yc
= yrad
;
101 /* last sampled ypsilon in the buffer */
104 /* Apply the sigma mean filter */
105 for (y
= 0; y
< (int)h_src
; y
++) {
106 for (x
= 0; x
< (int)w_src
; x
++) {
107 /* Get center pixel */
108 unsigned int R_center
= R
[yc
* w
+ x
+ xrad
];
109 unsigned int G_center
= G
[yc
* w
+ x
+ xrad
];
110 unsigned int B_center
= B
[yc
* w
+ x
+ xrad
];
112 /* Reset sum counters */
125 for (x1
= 0; x1
< xdiam
; x1
++) {
126 for (y1
= 0; y1
< ydiam
; y1
++) {
127 unsigned int R_cur
= R
[y1
* w
+ x
+ x1
];
128 unsigned int G_cur
= G
[y1
* w
+ x
+ x1
];
129 unsigned int B_cur
= B
[y1
* w
+ x
+ x1
];
135 if (abs(R_cur
- R_center
) < R_sigma
) {
140 if (abs(G_cur
- G_center
) < G_sigma
) {
145 if (abs(B_cur
- B_center
) < B_sigma
) {
175 gp_putpixel_raw_24BPP(dst
, x_dst
+ x
, y_dst
+ y
,
176 GP_PIXEL_CREATE_RGB888(r
, g
, b
));
179 int yi
= GP_CLAMP(y_src
+ y
+ yrad
+ 1, 0, (int)src
->h
- 1);
181 for (x
= 0; x
< (int)w
; x
++) {
182 int xi
= GP_CLAMP(x_src
+ x
- xrad
, 0, (int)src
->w
- 1);
184 gp_pixel pix
= gp_getpixel_raw_24BPP(src
, xi
, yi
);
186 R
[yl
* w
+ x
] = GP_PIXEL_GET_R_RGB888(pix
);
187 G
[yl
* w
+ x
] = GP_PIXEL_GET_G_RGB888(pix
);
188 B
[yl
* w
+ x
] = GP_PIXEL_GET_B_RGB888(pix
);
194 if (gp_progress_cb_report(callback
, y
, h_src
, w_src
)) {
195 gp_temp_alloc_free(temp
);
200 gp_temp_alloc_free(temp
);
201 gp_progress_cb_done(callback
);
206 int gp_filter_sigma_ex(const gp_pixmap
*src
,
207 gp_coord x_src
, gp_coord y_src
,
208 gp_size w_src
, gp_size h_src
,
210 gp_coord x_dst
, gp_coord y_dst
,
212 unsigned int min
, float sigma
,
213 gp_progress_cb
*callback
)
215 GP_CHECK(src
->pixel_type
== dst
->pixel_type
);
217 /* Check that destination is large enough */
218 GP_CHECK(x_dst
+ (gp_coord
)w_src
<= (gp_coord
)dst
->w
);
219 GP_CHECK(y_dst
+ (gp_coord
)h_src
<= (gp_coord
)dst
->h
);
221 GP_CHECK(xrad
>= 0 && yrad
>= 0);
223 return gp_filter_sigma_raw(src
, x_src
, y_src
, w_src
, h_src
,
224 dst
, x_dst
, y_dst
, xrad
, yrad
, min
, sigma
,
228 gp_pixmap
*gp_filter_sigma_ex_alloc(const gp_pixmap
*src
,
229 gp_coord x_src
, gp_coord y_src
,
230 gp_size w_src
, gp_size h_src
,
232 unsigned int min
, float sigma
,
233 gp_progress_cb
*callback
)
237 GP_CHECK(xrad
>= 0 && yrad
>= 0);
239 gp_pixmap
*dst
= gp_pixmap_alloc(w_src
, h_src
, src
->pixel_type
);
244 ret
= gp_filter_sigma_raw(src
, x_src
, y_src
, w_src
, h_src
,
245 dst
, 0, 0, xrad
, yrad
, min
, sigma
, callback
);