This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project gfxprim.git.
The branch, master has been updated via f945311372cbe2b60435593398c7de612c492c75 (commit) via 21a67077f7274a807f784cebe146de9d9766c62b (commit) via 23962459d2101ec72e59cc66007264cbd860a215 (commit) from c790f88c116700214c4bd14a8d350f302ba12993 (commit)
Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below.
- Log ----------------------------------------------------------------- http://repo.or.cz/w/gfxprim.git/commit/f945311372cbe2b60435593398c7de612c492...
commit f945311372cbe2b60435593398c7de612c492c75 Author: Cyril Hrubis metan@ucw.cz Date: Wed Jul 25 16:53:43 2012 +0200
filters: Add simple weighted median filter.
diff --git a/demos/c_simple/Makefile b/demos/c_simple/Makefile index bfff75b..68cf89e 100644 --- a/demos/c_simple/Makefile +++ b/demos/c_simple/Makefile @@ -7,7 +7,7 @@ LDLIBS+=-lGP -lGP_backends -lSDL -L$(TOPDIR)/build/
APPS=backend_example loaders_example loaders filters_symmetry gfx_koch virtual_backend_example meta_data meta_data_dump tmp_file showimage- v4l2_show v4l2_grab convolution + v4l2_show v4l2_grab convolution weighted_median
v4l2_show: LDLIBS+=-lGP_grabbers v4l2_grab: LDLIBS+=-lGP_grabbers diff --git a/demos/c_simple/weighted_median.c b/demos/c_simple/weighted_median.c new file mode 100644 index 0000000..fbbd8c5 --- /dev/null +++ b/demos/c_simple/weighted_median.c @@ -0,0 +1,159 @@ +/***************************************************************************** + * This file is part of gfxprim library. * + * * + * Gfxprim is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * Gfxprim is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with gfxprim; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, * + * Boston, MA 02110-1301 USA * + * * + * Copyright (C) 2009-2012 Cyril Hrubis metan@ucw.cz * + * * + *****************************************************************************/ + + /* + + Convolution filter example. + + */ + +#include <stdio.h> +#include <string.h> +#include <errno.h> + +#include <GP.h> + +struct callback_priv { + char *op; + char *name; +}; + +static int progress_callback(GP_ProgressCallback *self) +{ + struct callback_priv *priv = self->priv; + + printf("r%s '%s' %3.1f%%", priv->op, priv->name, self->percentage); + fflush(stdout); + + /* + * It's important to return zero as non-zero return value + * aborts the operation. + */ + return 0; +} + +int main(int argc, char *argv[]) +{ + GP_Context *img; + struct callback_priv priv; + GP_ProgressCallback callback = {.callback = progress_callback, + .priv = &priv}; + + if (argc != 2) { + fprintf(stderr, "Takes an image as an parametern"); + return 1; + } + + priv.op = "Loading"; + priv.name = argv[1]; + + img = GP_LoadImage(argv[1], &callback); + + if (img == NULL) { + fprintf(stderr, "Failed to load image '%s': %sn", argv[1], + strerror(errno)); + return 1; + } + + printf("n"); + + unsigned int circle[] = { + 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, + 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, + }; + + unsigned int calpen[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + }; + + unsigned int cross[] = { + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, + 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + }; + + unsigned int crazy[] = { + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, + }; + + GP_MedianWeights weights = { + .w = 11, + .h = 11, + .weights = circle, + }; + + priv.op = "Weighted Median"; + + GP_Context *res = GP_FilterWeightedMedianAlloc(img, &weights, &callback); + + printf("n"); + + priv.op = "Saving"; + priv.name = "out.png"; + + if (GP_SavePNG(res, "out.png", &callback)) { + fprintf(stderr, "Failed to save image: %s", strerror(errno)); + return 1; + } + + printf("n"); + + return 0; +} diff --git a/include/filters/GP_Filters.h b/include/filters/GP_Filters.h index a6a6f92..451ec8c 100644 --- a/include/filters/GP_Filters.h +++ b/include/filters/GP_Filters.h @@ -68,4 +68,7 @@ /* Median filter */ #include "filters/GP_Median.h"
+/* Median filter */ +#include "filters/GP_WeightedMedian.h" + #endif /* GP_FILTERS_H */ diff --git a/include/filters/GP_WeightedMedian.h b/include/filters/GP_WeightedMedian.h new file mode 100644 index 0000000..8219abd --- /dev/null +++ b/include/filters/GP_WeightedMedian.h @@ -0,0 +1,70 @@ +/***************************************************************************** + * This file is part of gfxprim library. * + * * + * Gfxprim is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * Gfxprim is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with gfxprim; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, * + * Boston, MA 02110-1301 USA * + * * + * Copyright (C) 2009-2012 Cyril Hrubis metan@ucw.cz * + * * + *****************************************************************************/ + + /* + + + */ + +#ifndef GP_FILTERS_WEIGHTED_MEDIAN_H +#define GP_FILTERS_WEIGHTED_MEDIAN_H + +#include "GP_Filter.h" + +typedef struct GP_MedianWeights { + unsigned int w; + unsigned int h; + unsigned int *weights; +} GP_MedianWeights; + +int GP_FilterWeightedMedianEx(const GP_Context *src, + GP_Coord x_src, GP_Coord y_src, + GP_Size w_src, GP_Size h_src, + GP_Context *dst, + GP_Coord x_dst, GP_Coord y_dst, + GP_MedianWeights *weights, + GP_ProgressCallback *callback); + +GP_Context *GP_FilterWeightedMedianExAlloc(const GP_Context *src, + GP_Coord x_src, GP_Coord y_src, + GP_Size w_src, GP_Size h_src, + GP_MedianWeights *weights, + GP_ProgressCallback *callback); + +static inline int GP_FilterWeightedMedian(const GP_Context *src, + GP_Context *dst, + GP_MedianWeights *weights, + GP_ProgressCallback *callback) +{ + return GP_FilterWeightedMedianEx(src, 0, 0, src->w, src->h, + dst, 0, 0, weights, callback); +} + +static inline GP_Context *GP_FilterWeightedMedianAlloc(const GP_Context *src, + GP_MedianWeights *weights, + GP_ProgressCallback *callback) +{ + return GP_FilterWeightedMedianExAlloc(src, 0, 0, src->w, src->h, + weights, callback); +} + +#endif /* GP_FILTERS_MEDIAN_H */ diff --git a/libs/filters/GP_WeightedMedian.c b/libs/filters/GP_WeightedMedian.c new file mode 100644 index 0000000..a34193d --- /dev/null +++ b/libs/filters/GP_WeightedMedian.c @@ -0,0 +1,221 @@ +/***************************************************************************** + * This file is part of gfxprim library. * + * * + * Gfxprim is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Lesser General Public * + * License as published by the Free Software Foundation; either * + * version 2.1 of the License, or (at your option) any later version. * + * * + * Gfxprim is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * + * Lesser General Public License for more details. * + * * + * You should have received a copy of the GNU Lesser General Public * + * License along with gfxprim; if not, write to the Free Software * + * Foundation, Inc., 51 Franklin Street, Fifth Floor, * + * Boston, MA 02110-1301 USA * + * * + * Copyright (C) 2009-2012 Cyril Hrubis metan@ucw.cz * + * * + *****************************************************************************/ + +#include "core/GP_Context.h" +#include "core/GP_GetPutPixel.h" +#include "core/GP_TempAlloc.h" +#include "core/GP_Clamp.h" + +#include "core/GP_Debug.h" + +#include "GP_WeightedMedian.h" + +#include <string.h> + +static unsigned int sum_weights(GP_MedianWeights *weights) +{ + unsigned int i; + unsigned int sum = 0; + + for (i = 0; i < weights->w * weights->h; i++) + sum += weights->weights[i]; + + return sum; +} + +static inline void hist_add(unsigned int *hist, unsigned int val, + unsigned int count) +{ + hist[val] += count; +} + +static inline unsigned int hist_med(unsigned int *hist, unsigned int size, + unsigned int threshold) +{ + unsigned int i; + unsigned int acc = 0; + + for (i = 0; i < size; i++) { + acc += hist[i]; + if (acc >= threshold) + return i; + } + + GP_BUG("Threshold not reached"); + return 0; +} + +static inline void hist_clear(unsigned int *hist, unsigned int size) +{ + memset(hist, 0, sizeof(unsigned int) * size); +} + +static inline unsigned int get_weight(GP_MedianWeights *weights, + unsigned int x, unsigned int y) +{ + return weights->weights[y * weights->w + x]; +} + +static int GP_FilterWeightedMedian_Raw(const GP_Context *src, + GP_Coord x_src, GP_Coord y_src, + GP_Size w_src, GP_Size h_src, + GP_Context *dst, + GP_Coord x_dst, GP_Coord y_dst, + GP_MedianWeights *weights, + GP_ProgressCallback *callback) +{ + int x, y, sum = sum_weights(weights); + unsigned int x1, y1; + + GP_CHECK(src->pixel_type == GP_PIXEL_RGB888); + + GP_DEBUG(1, "Weighted Median filter size %ux%u xmed=%u ymed=%u sum=%u", + w_src, h_src, weights->w, weights->h, sum); + + unsigned int w = w_src + weights->w; + unsigned int size = w * weights->h; + + GP_TempAllocCreate(temp, 3 * size * sizeof(unsigned int)); + + unsigned int *R = GP_TempAllocGet(temp, size * sizeof(unsigned int)); + unsigned int *G = GP_TempAllocGet(temp, size * sizeof(unsigned int)); + unsigned int *B = GP_TempAllocGet(temp, size * sizeof(unsigned int)); + + /* prefil the sampled array */ + for (x = 0; x < (int)w; x++) { + int xi = GP_CLAMP(x_src + x - (int)weights->w/2, 0, (int)src->w - 1); + + for (y = 0; y < (int)weights->h; y++) { + int yi = GP_CLAMP(y_src + y - (int)weights->h, 0, (int)src->h - 1); + + GP_Pixel pix = GP_GetPixel_Raw_24BPP(src, xi, yi); + + R[y * w + x] = GP_Pixel_GET_R_RGB888(pix); + G[y * w + x] = GP_Pixel_GET_G_RGB888(pix); + B[y * w + x] = GP_Pixel_GET_B_RGB888(pix); + } + } + + unsigned int hist_R[256]; + unsigned int hist_G[256]; + unsigned int hist_B[256]; + + hist_clear(hist_R, 256); + hist_clear(hist_G, 256); + hist_clear(hist_B, 256); + + /* Apply the weighted median filter */ + for (y = 0; y < (int)h_src; y++) { + for (x = 0; x < (int)w_src; x++) { + /* compute weighted histogram and then median */ + for (x1 = 0; x1 < weights->w; x1++) { + for (y1 = 0; y1 < weights->h; y1++) { + unsigned int weight = get_weight(weights, x1, y1); + hist_add(hist_R, R[y1 * w + x + x1], weight); + hist_add(hist_G, G[y1 * w + x + x1], weight); + hist_add(hist_B, B[y1 * w + x + x1], weight); + } + } + + unsigned int r = hist_med(hist_R, 256, sum/2); + unsigned int g = hist_med(hist_G, 256, sum/2); + unsigned int b = hist_med(hist_B, 256, sum/2); + + GP_PutPixel_Raw_24BPP(dst, x_dst + x, y_dst + y, + GP_Pixel_CREATE_RGB888(r, g, b)); + + hist_clear(hist_R, 256); + hist_clear(hist_G, 256); + hist_clear(hist_B, 256); + } + + for (x = 0; x < (int)w; x++) { + int xi = GP_CLAMP(x_src + x - (int)weights->w/2, 0, (int)src->w - 1); + + for (y1 = 0; y1 < weights->h; y1++) { + int yi = GP_CLAMP(y_src + y + (int)y1 - (int)weights->h/2, 0, (int)src->h - 1); + + GP_Pixel pix = GP_GetPixel_Raw_24BPP(src, xi, yi); + + R[y1 * w + x] = GP_Pixel_GET_R_RGB888(pix); + G[y1 * w + x] = GP_Pixel_GET_G_RGB888(pix); + B[y1 * w + x] = GP_Pixel_GET_B_RGB888(pix); + } + } + + if (GP_ProgressCallbackReport(callback, y, h_src, w_src)) { + GP_TempAllocFree(temp); + return 1; + } + } + + GP_TempAllocFree(temp); + GP_ProgressCallbackDone(callback); + + return 0; +} + +int GP_FilterWeightedMedianEx(const GP_Context *src, + GP_Coord x_src, GP_Coord y_src, + GP_Size w_src, GP_Size h_src, + GP_Context *dst, + GP_Coord x_dst, GP_Coord y_dst, + GP_MedianWeights *weights, + GP_ProgressCallback *callback) +{ + GP_CHECK(src->pixel_type == dst->pixel_type); + + /* Check that destination is large enough */ + GP_CHECK(x_dst + (GP_Coord)w_src <= (GP_Coord)dst->w); + GP_CHECK(y_dst + (GP_Coord)h_src <= (GP_Coord)dst->h); + + //GP_CHECK(xmed >= 0 && ymed >= 0); + + return GP_FilterWeightedMedian_Raw(src, x_src, y_src, w_src, h_src, + dst, x_dst, y_dst, weights, callback); +} + +GP_Context *GP_FilterWeightedMedianExAlloc(const GP_Context *src, + GP_Coord x_src, GP_Coord y_src, + GP_Size w_src, GP_Size h_src, + GP_MedianWeights *weights, + GP_ProgressCallback *callback) +{ + int ret; + + //GP_CHECK(xmed >= 0 && ymed >= 0); + + GP_Context *dst = GP_ContextAlloc(w_src, h_src, src->pixel_type); + + if (dst == NULL) + return NULL; + + ret = GP_FilterWeightedMedian_Raw(src, x_src, y_src, w_src, h_src, + dst, 0, 0, weights, callback); + + if (ret) { + GP_ContextFree(dst); + return NULL; + } + + return dst; +}
http://repo.or.cz/w/gfxprim.git/commit/21a67077f7274a807f784cebe146de9d9766c...
commit 21a67077f7274a807f784cebe146de9d9766c62b Author: Cyril Hrubis metan@ucw.cz Date: Wed Jul 25 16:41:29 2012 +0200
doc: Fix median filter docs.
diff --git a/doc/images/median/lenna_med_3_3.png b/doc/images/median/lenna_med_3_3.png index abbc202..b1263d7 100644 Binary files a/doc/images/median/lenna_med_3_3.png and b/doc/images/median/lenna_med_3_3.png differ diff --git a/doc/images/median/lenna_med_5_5.png b/doc/images/median/lenna_med_5_5.png index f205d49..3a70498 100644 Binary files a/doc/images/median/lenna_med_5_5.png and b/doc/images/median/lenna_med_5_5.png differ diff --git a/doc/images/median/lenna_med_7_7.png b/doc/images/median/lenna_med_7_7.png index 5b11b19..15a5395 100644 Binary files a/doc/images/median/lenna_med_7_7.png and b/doc/images/median/lenna_med_7_7.png differ diff --git a/doc/images/median/lenna_med_9_9.png b/doc/images/median/lenna_med_9_9.png index f068dbb..94a62f1 100644 Binary files a/doc/images/median/lenna_med_9_9.png and b/doc/images/median/lenna_med_9_9.png differ diff --git a/doc/images/median/lenna_small_med_3_3.png b/doc/images/median/lenna_small_med_3_3.png index eef311d..c8703bc 100644 Binary files a/doc/images/median/lenna_small_med_3_3.png and b/doc/images/median/lenna_small_med_3_3.png differ diff --git a/doc/images/median/lenna_small_med_5_5.png b/doc/images/median/lenna_small_med_5_5.png index fca6ab4..8dbb616 100644 Binary files a/doc/images/median/lenna_small_med_5_5.png and b/doc/images/median/lenna_small_med_5_5.png differ diff --git a/doc/images/median/lenna_small_med_7_7.png b/doc/images/median/lenna_small_med_7_7.png index 8ba3aab..e06ddf5 100644 Binary files a/doc/images/median/lenna_small_med_7_7.png and b/doc/images/median/lenna_small_med_7_7.png differ diff --git a/doc/images/median/lenna_small_med_9_9.png b/doc/images/median/lenna_small_med_9_9.png index 0eec833..2fa7997 100644 Binary files a/doc/images/median/lenna_small_med_9_9.png and b/doc/images/median/lenna_small_med_9_9.png differ
http://repo.or.cz/w/gfxprim.git/commit/23962459d2101ec72e59cc66007264cbd860a...
commit 23962459d2101ec72e59cc66007264cbd860a215 Author: Cyril Hrubis metan@ucw.cz Date: Wed Jul 25 16:37:53 2012 +0200
filters: Median fix the trigger value.
diff --git a/libs/filters/GP_Median.c b/libs/filters/GP_Median.c index 88dd92c..e6dca7d 100644 --- a/libs/filters/GP_Median.c +++ b/libs/filters/GP_Median.c @@ -148,7 +148,7 @@ static inline unsigned int hist8_median(struct hist8u *h, struct hist8 *row, if (acc >= trigger) { acc -= h->coarse[i]; - + /* update fine on position i */ hist8_update(h, i, row, x, xmed);
@@ -174,6 +174,7 @@ static int GP_FilterMedian_Raw(const GP_Context *src, GP_ProgressCallback *callback) { int i, x, y; + unsigned int trigger = ((2*xmed+1)*(2*ymed+1))/2;
//TODO GP_CHECK(src->pixel_type == GP_PIXEL_RGB888); @@ -229,9 +230,9 @@ static int GP_FilterMedian_Raw(const GP_Context *src,
/* Generate row */ for (x = 0; x < (int)w_src; x++) { - int r = hist8_median(XR, R, x, xmed, (xmed + ymed + 1)); - int g = hist8_median(XG, G, x, xmed, (xmed + ymed + 1)); - int b = hist8_median(XB, B, x, xmed, (xmed + ymed + 1)); + int r = hist8_median(XR, R, x, xmed, trigger); + int g = hist8_median(XG, G, x, xmed, trigger); + int b = hist8_median(XB, B, x, xmed, trigger);
GP_PutPixel_Raw_24BPP(dst, x_dst + x, y_dst + y, GP_Pixel_CREATE_RGB888(r, g, b));
-----------------------------------------------------------------------
Summary of changes: demos/c_simple/Makefile | 2 +- .../c_simple/{convolution.c => weighted_median.c} | 80 ++++++-- doc/images/median/lenna_med_3_3.png | Bin 331859 -> 337110 bytes doc/images/median/lenna_med_5_5.png | Bin 275419 -> 289966 bytes doc/images/median/lenna_med_7_7.png | Bin 241894 -> 259580 bytes doc/images/median/lenna_med_9_9.png | Bin 218719 -> 239185 bytes doc/images/median/lenna_small_med_3_3.png | Bin 89004 -> 90434 bytes doc/images/median/lenna_small_med_5_5.png | Bin 74908 -> 78931 bytes doc/images/median/lenna_small_med_7_7.png | Bin 66044 -> 72126 bytes doc/images/median/lenna_small_med_9_9.png | Bin 59615 -> 67725 bytes include/filters/GP_Filters.h | 3 + .../filters/{GP_Median.h => GP_WeightedMedian.h} | 62 +++--- libs/filters/GP_Median.c | 9 +- libs/filters/GP_WeightedMedian.c | 221 ++++++++++++++++++++ 14 files changed, 323 insertions(+), 54 deletions(-) copy demos/c_simple/{convolution.c => weighted_median.c} (59%) copy include/filters/{GP_Median.h => GP_WeightedMedian.h} (50%) create mode 100644 libs/filters/GP_WeightedMedian.c
repo.or.cz automatic notification. Contact project admin jiri.bluebear.dluhos@gmail.com if you want to unsubscribe, or site admin admin@repo.or.cz if you receive no reply.