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, generate has been updated via d291a122c53ce9d70a5777b380ae9ca82978987b (commit) via 2754045bba9b30539121e3a860de208463511fe3 (commit) via a26979d8c8abdbf13131422e59e055e4abf39918 (commit) via 871fb9ebb0895f698f22e2ad4cbe983e78d5c194 (commit) from b51b045c4d615a275513234d727bb99d90ecfa80 (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/d291a122c53ce9d70a5777b380ae9ca829789...
commit d291a122c53ce9d70a5777b380ae9ca82978987b Author: Cyril Hrubis metan@ucw.cz Date: Tue Oct 4 20:14:27 2011 +0200
Make grinder parameter parsing little more robust.
diff --git a/demos/grinder/grinder.c b/demos/grinder/grinder.c index a0e8f2c..26d6d0d 100644 --- a/demos/grinder/grinder.c +++ b/demos/grinder/grinder.c @@ -428,11 +428,11 @@ static const char *app_help = { " n" " <<<<<<<<<< Bitmap Grinder >>>>>>>>>>> n" " n" - " +-+-----+ n" - " / | +-+| .11. n" + " +~+-----+ n" + " /| | +-+| .11. n" " +-{ D| |010101011. n" - " | \ | +-.0100101. n" - " O=+ +-+-----+ .10110101. n" + " | | | +-.0100101. n" + " O=+ +~+-----+ .10110101. n" " .010101. n" " .1. n" " n" @@ -481,7 +481,16 @@ int main(int argc, char *argv[]) return 0; break; case 'v': - GP_SetDebugLevel(atoi(optarg)); + i = atoi(optarg); + + if (i == 0) { + fprintf(stderr, "ERROR: invalid debug level " + "'%s', expected number > 0n", + optarg); + return 1; + } + + GP_SetDebugLevel(i); break; case 'f': add_filter(optarg); @@ -496,8 +505,7 @@ int main(int argc, char *argv[]) }
if (optind >= argc) { - fprintf(stderr, "Expected bitmap filenamesn"); - print_help(); + fprintf(stderr, "ERROR: Expected bitmap filenamesn"); return 1; }
http://repo.or.cz/w/gfxprim.git/commit/2754045bba9b30539121e3a860de208463511...
commit 2754045bba9b30539121e3a860de208463511fe3 Author: Cyril Hrubis metan@ucw.cz Date: Tue Oct 4 20:09:24 2011 +0200
Fixed error value from GP_LoadImage.
Fixed error value from GP_LoadImage in case file doesn't exist/user has no permisssion to read it.
diff --git a/libs/loaders/GP_Loaders.c b/libs/loaders/GP_Loaders.c index 72e2a31..63f1da5 100644 --- a/libs/loaders/GP_Loaders.c +++ b/libs/loaders/GP_Loaders.c @@ -27,6 +27,10 @@ */
#include <string.h> +#include <unistd.h> +#include <errno.h> + +#include <GP_Debug.h>
#include "GP_Loaders.h"
@@ -35,6 +39,12 @@ GP_RetCode GP_LoadImage(const char *src_path, GP_Context **res) int len = strlen(src_path); GP_RetCode ret = GP_ENOIMPL;
+ if (access(src_path, R_OK)) { + GP_DEBUG(1, "Failed to access file '%s' : %s", + src_path, strerror(errno)); + return GP_EBADFILE; + } + switch (src_path[len - 1]) { /* PNG, JPG, JPEG */ case 'g':
http://repo.or.cz/w/gfxprim.git/commit/a26979d8c8abdbf13131422e59e055e4abf39...
commit a26979d8c8abdbf13131422e59e055e4abf39918 Author: Cyril Hrubis metan@ucw.cz Date: Tue Oct 4 19:48:39 2011 +0200
Added some more info to grinder README.
diff --git a/demos/grinder/README b/demos/grinder/README index 749485f..ad2c2e7 100644 --- a/demos/grinder/README +++ b/demos/grinder/README @@ -10,3 +10,35 @@ grinder -f filter_name:filter_params... -f filter_name:filter_params... -f filte Which will apply pipeline of filters to each image and store results to out_X.ppm
see grinder -h for list of filters and options + + +COOL EFECTS +~~~~~~~~~~~ + +Pixelize yourself +----------------- + +This filter creates pixelated image of the input (for example photograph of your head). + +grinder -p -f resize:ratio=0.2 -f blur:sigma=4 -f resize:ratio=0.1 -f resize:alg=nn:ratio=4 head.png + +And now, what it does: + +* The first resize just resizes down the image as the images that gets out a + digital camera are usually too big and too noisy. This only prepares the + image so it has reasonable size. Ideally there should be a low-pass filter + (eg. gaussian blur) before each downscaling but as we are scaling the image + further, we don't care now. + +* The blur does low-pass filter (cuts off all high frequencies). If you are not + familiar with digital signal processing, think of this just as smoothing the + image after the interpolation (which works only on a few neighbour pixels so + on downscaling some of the pixels may not be used for the interpolation at + all). + +* The second resize resizes the image to be really small (and the result is + quite good looking as we used low-pass filter beforhand). + +* The last resize scales the image up, but this time we used nearest neighbour + interpolation, which just picks up one pixel which is nearest to the + interpolated value. This actually creates the 'pixel' effect.
http://repo.or.cz/w/gfxprim.git/commit/871fb9ebb0895f698f22e2ad4cbe983e78d5c...
commit 871fb9ebb0895f698f22e2ad4cbe983e78d5c194 Author: Cyril Hrubis metan@ucw.cz Date: Tue Oct 4 19:45:57 2011 +0200
Optimized convolution, made it non static.
* Optimized convolution for separable filters - that leads to 10-30% faster gaussian blur
* Made the convolution declarations public
diff --git a/include/filters/GP_Linear.h b/include/filters/GP_Linear.h index ae0debd..3194cb8 100644 --- a/include/filters/GP_Linear.h +++ b/include/filters/GP_Linear.h @@ -36,7 +36,10 @@ * * The sigma parameters defines the blur radii in horizontal and vertical * direction. - * + * + * Internaly this is implemented as separable linear filter (calls vertical and + * horizontal convolution with generated gaussian kernel). + * * This variant could work in-place so it's perectly okay to call * * GP_FilterGaussianBlur_Raw(context, context, ...); @@ -49,4 +52,41 @@ GP_Context *GP_FilterGaussianBlur(GP_Context *src, GP_ProgressCallback *callback, float sigma_x, float sigma_y);
+/* + * Linear convolution. + * + * The kernel is array of kw * kh floats and is indexed as two directional array. + * + * To define 3x3 average filter + * + * kernel[] = { + * 1, 1, 1, + * 1, 1, 1, + * 1, 1, 1, + * }; + * + * kw = kh = 3 + * + * This function works also in-place. + */ +void GP_FilterLinearConvolution_Raw(const GP_Context *src, GP_Context *res, + GP_ProgressCallback *callback, + float kernel[], uint32_t kw, uint32_t kh); + +/* + * Special cases for convolution only in horizontal/vertical direction. + * + * These are about 10-30% faster than the generic implementation (depending on + * the kernel size, bigger kernel == more savings). + * + * Both works also in-place. + */ +void GP_FilterHLinearConvolution_Raw(const GP_Context *src, GP_Context *res, + GP_ProgressCallback *callback, + float kernel[], uint32_t kw); + +void GP_FilterVLinearConvolution_Raw(const GP_Context *src, GP_Context *res, + GP_ProgressCallback *callback, + float kernel[], uint32_t kh); + #endif /* GP_LINEAR_H */ diff --git a/libs/filters/GP_Linear.c b/libs/filters/GP_Linear.c index 48dc0ee..8f7c2a3 100644 --- a/libs/filters/GP_Linear.c +++ b/libs/filters/GP_Linear.c @@ -29,10 +29,6 @@
#include <GP_Linear.h>
-static void GP_FilterLinearConvolution(const GP_Context *src, GP_Context *res, - GP_ProgressCallback *callback, - float kernel[], uint32_t kw, uint32_t kh); - static inline unsigned int gaussian_kernel_size(float sigma) { int center = 3 * sigma; @@ -83,21 +79,25 @@ void GP_FilterGaussianBlur_Raw(GP_Context *src, GP_Context *res, if (callback != NULL) new_callback = &gaussian_callback;
- /* compute kernel and apply on horizontal direction */ + /* compute kernel and apply in horizontal direction */ if (sigma_x > 0) { float kernel_x[size_x]; gaussian_kernel_init(sigma_x, kernel_x); - GP_FilterLinearConvolution(src, res, new_callback, kernel_x, size_x, 1); + + GP_FilterHLinearConvolution_Raw(src, res, new_callback, + kernel_x, size_x); } if (new_callback != NULL) new_callback->callback = gaussian_callback_2;
- /* compute kernel and apply on vertical direction */ + /* compute kernel and apply in vertical direction */ if (sigma_y > 0) { float kernel_y[size_y]; gaussian_kernel_init(sigma_y, kernel_y); - GP_FilterLinearConvolution(res, res, new_callback, kernel_y, 1, size_y); + + GP_FilterVLinearConvolution_Raw(res, res, new_callback, + kernel_y, size_y); }
GP_ProgressCallbackDone(callback); @@ -124,9 +124,220 @@ GP_Context *GP_FilterGaussianBlur(GP_Context *src, return res; }
-static void GP_FilterLinearConvolution(const GP_Context *src, GP_Context *res, - GP_ProgressCallback *callback, - float kernel[], uint32_t kw, uint32_t kh) +void GP_FilterHLinearConvolution_Raw(const GP_Context *src, GP_Context *res, + GP_ProgressCallback *callback, + float kernel[], uint32_t kw) +{ + float kernel_sum = 0; + GP_Coord x, y; + uint32_t i; + + GP_DEBUG(1, "Horizontal linear convolution kernel width %i image %ux%u", + kw, src->w, src->h); + + /* count kernel sum for normalization */ + for (i = 0; i < kw; i++) + kernel_sum += kernel[i]; + + /* do linear convolution */ + for (y = 0; y < (GP_Coord)res->h; y++) { + GP_Pixel pix; + uint32_t R[kw], G[kw], B[kw]; + + /* prefill the buffer on the start */ + for (i = 0; i < kw - 1; i++) { + int cx = i - kw/2; + + if (cx < 0) + cx = 0; + + pix = GP_GetPixel_Raw_24BPP(src, cx, y); + + R[i] = GP_Pixel_GET_R_RGB888(pix); + G[i] = GP_Pixel_GET_G_RGB888(pix); + B[i] = GP_Pixel_GET_B_RGB888(pix); + } + + int idx = kw - 1; + + for (x = 0; x < (GP_Coord)res->w; x++) { + float r = 0, g = 0, b = 0; + + int cx = x + kw/2; + + if (cx >= (int)src->w) + cx = src->w - 1; + + pix = GP_GetPixel_Raw_24BPP(src, cx, y); + + R[idx] = GP_Pixel_GET_R_RGB888(pix); + G[idx] = GP_Pixel_GET_G_RGB888(pix); + B[idx] = GP_Pixel_GET_B_RGB888(pix); + + /* count the pixel value from neighbours weighted by kernel */ + for (i = 0; i < kw; i++) { + int k; + + if ((int)i < idx + 1) + k = kw - idx - 1 + i; + else + k = i - idx - 1; + + r += R[i] * kernel[k]; + g += G[i] * kernel[k]; + b += B[i] * kernel[k]; + } + + /* normalize the result */ + r /= kernel_sum; + g /= kernel_sum; + b /= kernel_sum; + + /* and clamp just to be extra sure */ + if (r > 255) + r = 255; + if (r < 0) + r = 0; + if (g > 255) + g = 255; + if (g < 0) + g = 0; + if (b > 255) + b = 255; + if (b < 0) + b = 0; + + pix = GP_Pixel_CREATE_RGB888((uint32_t)r, (uint32_t)g, (uint32_t)b); + + GP_PutPixel_Raw_24BPP(res, x, y, pix); + + idx++; + + if (idx >= (int)kw) + idx = 0; + } + + if (callback != NULL && y % 100 == 0) + GP_ProgressCallbackReport(callback, 100.00 * y/res->h); + } + + GP_ProgressCallbackDone(callback); +} + +/* + * Special case for vertical only kernel (10-30% faster). + * + * Can be used in-place. + */ +void GP_FilterVLinearConvolution_Raw(const GP_Context *src, GP_Context *res, + GP_ProgressCallback *callback, + float kernel[], uint32_t kh) +{ + float kernel_sum = 0; + GP_Coord x, y; + uint32_t i; + + GP_DEBUG(1, "Vertical linear convolution kernel width %i image %ux%u", + kh, src->w, src->h); + + /* count kernel sum for normalization */ + for (i = 0; i < kh; i++) + kernel_sum += kernel[i]; + + /* do linear convolution */ + for (x = 0; x < (GP_Coord)res->w; x++) { + GP_Pixel pix; + uint32_t R[kh], G[kh], B[kh]; + + /* prefill the buffer on the start */ + for (i = 0; i < kh - 1; i++) { + int cy = i - kh/2; + + if (cy < 0) + cy = 0; + + pix = GP_GetPixel_Raw_24BPP(src, x, cy); + + R[i] = GP_Pixel_GET_R_RGB888(pix); + G[i] = GP_Pixel_GET_G_RGB888(pix); + B[i] = GP_Pixel_GET_B_RGB888(pix); + } + + int idx = kh - 1; + + for (y = 0; y < (GP_Coord)res->h; y++) { + float r = 0, g = 0, b = 0; + + int cy = y + kh/2; + + if (cy >= (int)src->h) + cy = src->h - 1; + + pix = GP_GetPixel_Raw_24BPP(src, x, cy); + + R[idx] = GP_Pixel_GET_R_RGB888(pix); + G[idx] = GP_Pixel_GET_G_RGB888(pix); + B[idx] = GP_Pixel_GET_B_RGB888(pix); + + /* count the pixel value from neighbours weighted by kernel */ + for (i = 0; i < kh; i++) { + int k; + + if ((int)i < idx + 1) + k = kh - idx - 1 + i; + else + k = i - idx - 1; + + r += R[i] * kernel[k]; + g += G[i] * kernel[k]; + b += B[i] * kernel[k]; + } + + /* normalize the result */ + r /= kernel_sum; + g /= kernel_sum; + b /= kernel_sum; + + /* and clamp just to be extra sure */ + if (r > 255) + r = 255; + if (r < 0) + r = 0; + if (g > 255) + g = 255; + if (g < 0) + g = 0; + if (b > 255) + b = 255; + if (b < 0) + b = 0; + + pix = GP_Pixel_CREATE_RGB888((uint32_t)r, (uint32_t)g, (uint32_t)b); + + GP_PutPixel_Raw_24BPP(res, x, y, pix); + + idx++; + + if (idx >= (int)kh) + idx = 0; + } + + if (callback != NULL && x % 100 == 0) + GP_ProgressCallbackReport(callback, 100.00 * x/res->w); + } + + GP_ProgressCallbackDone(callback); +} + + +/* + * Linear convolution. + * + * Can be used in-place. + */ +void GP_FilterLinearConvolution_Raw(const GP_Context *src, GP_Context *res, + GP_ProgressCallback *callback, + float kernel[], uint32_t kw, uint32_t kh) { float kernel_sum = 0; GP_Coord x, y; @@ -216,10 +427,16 @@ static void GP_FilterLinearConvolution(const GP_Context *src, GP_Context *res, /* and clamp just to be extra sure */ if (r > 255) r = 255; + if (r < 0) + r = 0; if (g > 255) g = 255; + if (g < 0) + g = 0; if (b > 255) b = 255; + if (b < 0) + b = 0;
pix = GP_Pixel_CREATE_RGB888((uint32_t)r, (uint32_t)g, (uint32_t)b);
-----------------------------------------------------------------------
Summary of changes: demos/grinder/README | 32 ++++++ demos/grinder/grinder.c | 22 +++-- include/filters/GP_Linear.h | 42 ++++++++- libs/filters/GP_Linear.c | 239 +++++++++++++++++++++++++++++++++++++++++-- libs/loaders/GP_Loaders.c | 10 ++ 5 files changed, 326 insertions(+), 19 deletions(-)
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.