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 cdf4a7d83af42ed412a8b705b3ad50cb43a9ecb9 (commit) via 76e823c5cd0ff172cb3649655b468b920a861f06 (commit) via 3b60a5fe873cde45782b7ef870ecc94bfbc209d2 (commit) via 667776d0fdc6195be8c9ad201f48bb6a4b4da460 (commit) via d3f29ef699671a32207092195cc96926ed2937e3 (commit) via 0223a7dca0a58c112f3b60100e0e5f66de5263d1 (commit) via 5bc6361309104e85c8a54add16ca23554bf65827 (commit) from 4dad87b8900261ecaadbc43dedb932683089b414 (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/cdf4a7d83af42ed412a8b705b3ad50cb43a9e...
commit cdf4a7d83af42ed412a8b705b3ad50cb43a9ecb9 Author: Cyril Hrubis metan@ucw.cz Date: Sun Jun 17 20:09:43 2012 +0200
filters: resize: Fix off-by-one for rest of the algorithms.
diff --git a/libs/filters/GP_Resize.c b/libs/filters/GP_Resize.c index 6fbd5eb..b453ffd 100644 --- a/libs/filters/GP_Resize.c +++ b/libs/filters/GP_Resize.c @@ -130,7 +130,7 @@ int GP_FilterInterpolate_Cubic(const GP_Context *src, GP_Context *dst, 1.00 * dst->w / src->w, 1.00 * dst->h / src->h);
for (i = 0; i < dst->w; i++) { - float x = (1.00 * i / dst->w) * src->w; + float x = (1.00 * i / (dst->w - 1)) * (src->w - 1); v4f cvx; int xi[4]; @@ -189,7 +189,7 @@ int GP_FilterInterpolate_Cubic(const GP_Context *src, GP_Context *dst,
/* now interpolate column for new image */ for (j = 0; j < dst->h; j++) { - float y = (1.00 * j / dst->h) * src->h; + float y = (1.00 * j / (dst->h - 1)) * (src->h - 1); v4f cvy, rv, gv, bv; float r, g, b; int yi[4]; @@ -295,7 +295,7 @@ int GP_FilterInterpolate_CubicInt(const GP_Context *src, GP_Context *dst, }
for (i = 0; i < dst->h; i++) { - float y = (1.00 * i / dst->h) * src->h; + float y = (1.00 * i / (dst->h - 1)) * (src->h - 1); int32_t cvy[4]; int yi[4]; @@ -312,9 +312,6 @@ int GP_FilterInterpolate_CubicInt(const GP_Context *src, GP_Context *dst, if (yi[0] < 0) yi[0] = 0; - if (yi[2] >= (int)src->h) - yi[2] = src->h - 1; - if (yi[3] >= (int)src->h) yi[3] = src->h - 1;
@@ -372,7 +369,7 @@ int GP_FilterInterpolate_CubicInt(const GP_Context *src, GP_Context *dst,
/* now interpolate column for new image */ for (j = 0; j < dst->w; j++) { - float x = (1.00 * j / dst->w) * src->w; + float x = (1.00 * j / (dst->w - 1)) * (src->w - 1); int32_t cvx[4], rv[4], gv[4], bv[4]; int32_t r, g, b; int xi[4]; @@ -390,9 +387,6 @@ int GP_FilterInterpolate_CubicInt(const GP_Context *src, GP_Context *dst, if (xi[0] < 0) xi[0] = 0;
- if (xi[2] >= (int)src->w) - xi[2] = src->w - 1; - if (xi[3] >= (int)src->w) xi[3] = src->w - 1;
@@ -537,8 +531,8 @@ static int interpolate_linear_lp_xy(const GP_Context *src, GP_Context *dst, uint32_t i, j; /* Pre-compute mapping for interpolation */ - uint32_t xstep = (src->w << 16) / dst->w; - uint32_t xpix_dist = (dst->w << 14) / src->w; + uint32_t xstep = ((src->w - 1) << 16) / (dst->w - 1); + uint32_t xpix_dist = ((dst->w - 1) << 14) / (src->w - 1);
for (i = 0; i < dst->w + 1; i++) { uint32_t val = i * xstep; @@ -546,8 +540,8 @@ static int interpolate_linear_lp_xy(const GP_Context *src, GP_Context *dst, xoff[i] = ((255 - ((val >> 8) & 0xff)) * xpix_dist)>>8; }
- uint32_t ystep = (src->h << 16) / dst->h; - uint32_t ypix_dist = (dst->h << 14) / src->h; + uint32_t ystep = ((src->h - 1) << 16) / (dst->h - 1); + uint32_t ypix_dist = ((dst->h - 1) << 14) / (src->h - 1);
for (i = 0; i < dst->h + 1; i++) { uint32_t val = i * ystep; @@ -634,7 +628,7 @@ int GP_FilterInterpolate_LinearInt(const GP_Context *src, GP_Context *dst, 1.00 * dst->w / src->w, 1.00 * dst->h / src->h);
/* Pre-compute mapping for interpolation */ - uint32_t xstep = (src->w << 16) / dst->w; + uint32_t xstep = ((src->w - 1) << 16) / (dst->w - 1);
for (i = 0; i < dst->w + 1; i++) { uint32_t val = i * xstep; @@ -642,7 +636,7 @@ int GP_FilterInterpolate_LinearInt(const GP_Context *src, GP_Context *dst, xoff[i] = (val >> 8) & 0xff; }
- uint32_t ystep = (src->h << 16) / dst->h; + uint32_t ystep = ((src->h - 1) << 16) / (dst->h - 1);
for (i = 0; i < dst->h + 1; i++) { uint32_t val = i * ystep;
http://repo.or.cz/w/gfxprim.git/commit/76e823c5cd0ff172cb3649655b468b920a861...
commit 76e823c5cd0ff172cb3649655b468b920a861f06 Author: Cyril Hrubis metan@ucw.cz Date: Sun Jun 17 19:54:12 2012 +0200
filters: resize NN, fix off-by-one in coordinates mapping.
diff --git a/libs/filters/GP_ResizeNN.gen.c.t b/libs/filters/GP_ResizeNN.gen.c.t index 7719efb..7c7bd51 100644 --- a/libs/filters/GP_ResizeNN.gen.c.t +++ b/libs/filters/GP_ResizeNN.gen.c.t @@ -27,15 +27,14 @@ static int GP_FilterResizeNN_{{ pt.name }}_Raw(const GP_Context *src, 1.00 * dst->w / src->w, 1.00 * dst->h / src->h);
/* Pre-compute mapping for interpolation */ - uint32_t xstep = (src->w << 16) / dst->w; - - for (i = 0; i < dst->w + 1; i++) - xmap[i] = ((i * xstep) + (1<<15)) >> 16; - - uint32_t ystep = (src->h << 16) / dst->h; + for (i = 0; i < dst->w; i++) { + xmap[i] = ((((i * (src->w - 1))<<8) + (dst->w - 1)/2) / (dst->w - 1) + (1<<7))>>8; + printf("%i-%i ", i, xmap[i]); + } + printf("n%i -> %in", src->w, dst->w);
- for (i = 0; i < dst->h + 1; i++) - ymap[i] = ((i * ystep) + (1<<15)) >> 16; + for (i = 0; i < dst->h; i++) + ymap[i] = ((((i * (src->h - 1))<<8) + (dst->h - 1)/2) / (dst->h - 1) + (1<<7))>>8;
/* Interpolate */ for (y = 0; y < (GP_Coord)dst->h; y++) {
http://repo.or.cz/w/gfxprim.git/commit/3b60a5fe873cde45782b7ef870ecc94bfbc20...
commit 3b60a5fe873cde45782b7ef870ecc94bfbc209d2 Author: Cyril Hrubis metan@ucw.cz Date: Sun Jun 17 19:37:27 2012 +0200
spiv: A few fixes and features.
* Adds keys to change resampling at runtime. - left and right square brackets change resampling - l forces to turn on/off low pass filter
diff --git a/demos/spiv/spiv.c b/demos/spiv/spiv.c index 43c9f8d..19f6d56 100644 --- a/demos/spiv/spiv.c +++ b/demos/spiv/spiv.c @@ -47,7 +47,33 @@ static GP_Backend *backend = NULL; /* image loader thread */ static int abort_flag = 0; static int show_progress = 0; -static int resampling_method = GP_INTERP_LINEAR_LF_INT; + +struct loader_params { + /* current image path */ + const char *img_path; + /* current resize ratio */ + float rat; + + /* show loader progress */ + long show_progress:1; + long show_progress_once:2; + /* show image info in topleft corner */ + long show_info:3; + /* use nearest neighbour resampling first */ + long show_nn_first:4; + /* use dithering when blitting to display */ + long use_dithering:5; + /* use low pass before resampling */ + long use_low_pass:6; + /* image orientation 0, 90, 180, 270 */ + int rotate; + /* resampling method */ + int resampling_method; + + /* caches for loaded images */ + struct image_cache *img_resized_cache; + struct image_cache *img_orig_cache; +};
static int image_loader_callback(GP_ProgressCallback *self) { @@ -81,26 +107,6 @@ static int image_loader_callback(GP_ProgressCallback *self) return 0; }
-struct loader_params { - const char *img_path; - - /* Show loader progress */ - long show_progress:1; - long show_progress_once:2; - /* show image info in topleft corner */ - long show_info:3; - /* use nearest neighbour resampling first */ - long show_nn_first:4; - /* use dithering when blitting to display */ - long use_dithering:5; - - /* Image orientation */ - int rotate; - - /* cached loaded images */ - struct image_cache *img_resized_cache; - struct image_cache *img_orig_cache; -};
static float calc_img_size(uint32_t img_w, uint32_t img_h, uint32_t src_w, uint32_t src_h) @@ -182,7 +188,7 @@ GP_Context *load_image(struct loader_params *params, int elevate) /* * Updates display. */ -static void update_display(struct loader_params *params, GP_Context *img, float rat) +static void update_display(struct loader_params *params, GP_Context *img) { GP_Context *context = backend->context; struct cpu_timer timer; @@ -235,7 +241,7 @@ static void update_display(struct loader_params *params, GP_Context *img, float GP_FillRectXYWH(context, img->w + cx, 0, context->w - img->w - cx, context->h, black_pixel); GP_FillRectXYWH(context, 0, img->h + cy, context->w, context->h - img->h - cy, black_pixel); - set_caption(params->img_path, rat); + set_caption(params->img_path, params->rat);
if (!params->show_info) { GP_BackendFlip(backend); @@ -251,10 +257,10 @@ static void update_display(struct loader_params *params, GP_Context *img, float white_pixel, black_pixel, "%ux%u", img->w, img->h); GP_Print(context, NULL, 11, 13 + th, GP_ALIGN_RIGHT|GP_VALIGN_BOTTOM, - black_pixel, white_pixel, "1:%3.3f", rat); + black_pixel, white_pixel, "1:%3.3f", params->rat); GP_Print(context, NULL, 10, 12 + th, GP_ALIGN_RIGHT|GP_VALIGN_BOTTOM, - white_pixel, black_pixel, "1:%3.3f", rat); + white_pixel, black_pixel, "1:%3.3f", params->rat); GP_Print(context, NULL, 11, 15 + 2 * th, GP_ALIGN_RIGHT|GP_VALIGN_BOTTOM, black_pixel, white_pixel, "%s", img_name(params->img_path)); @@ -262,18 +268,30 @@ static void update_display(struct loader_params *params, GP_Context *img, float GP_Print(context, NULL, 10, 14 + 2 * th, GP_ALIGN_RIGHT|GP_VALIGN_BOTTOM, white_pixel, black_pixel, "%s", img_name(params->img_path)); + GP_Print(context, NULL, 11, 17 + 3 * th, GP_ALIGN_RIGHT|GP_VALIGN_BOTTOM, + black_pixel, white_pixel, "%s%s", + params->use_low_pass && params->rat < 1 ? "Gaussian LP + " : "", + GP_InterpolationTypeName(params->resampling_method)); + + GP_Print(context, NULL, 10, 16 + 3 * th, GP_ALIGN_RIGHT|GP_VALIGN_BOTTOM, + white_pixel, black_pixel, "%s%s", + params->use_low_pass && params->rat < 1 ? "Gaussian LP + " : "", + GP_InterpolationTypeName(params->resampling_method)); + GP_BackendFlip(backend); }
-GP_Context *load_resized_image(struct loader_params *params, GP_Size w, GP_Size h, float rat) +GP_Context *load_resized_image(struct loader_params *params, GP_Size w, GP_Size h) { long cookie = (w & 0xffff) | (h & 0xffff)<<16; GP_Context *img, *res = NULL; struct cpu_timer timer; GP_ProgressCallback callback = {.callback = image_loader_callback}; + + int key = (params->resampling_method<<1) | !!(params->use_low_pass);
/* Try to get resized cached image */ - img = image_cache_get(params->img_resized_cache, params->img_path, cookie, resampling_method, 1); + img = image_cache_get(params->img_resized_cache, params->img_path, cookie, key, 1);
if (img != NULL) return img; @@ -286,35 +304,34 @@ GP_Context *load_resized_image(struct loader_params *params, GP_Size w, GP_Size /* Do simple interpolation and blit the result */ GP_Context *nn = GP_FilterResizeNNAlloc(img, w, h, NULL); if (nn != NULL) { - update_display(params, nn, rat); + update_display(params, nn); GP_ContextFree(nn); } }
/* Do low pass filter */ - if (resampling_method != GP_INTERP_LINEAR_LF_INT && rat < 1) { + if (params->use_low_pass && params->rat < 1) { cpu_timer_start(&timer, "Blur"); callback.priv = "Blurring Image"; - res = GP_FilterGaussianBlur(img, NULL, 0.4/rat, 0.4/rat, &callback); - + res = GP_FilterGaussianBlur(img, NULL, + 0.3/params->rat, 0.3/params->rat, + &callback); if (res == NULL) return NULL; img = res; - // img->gamma = GP_GammaAcquire(img->pixel_type, 2.2); - cpu_timer_stop(&timer); - } else { - // img->gamma = GP_GammaAcquire(img->pixel_type, 2.2); } + +// img->gamma = GP_GammaAcquire(img->pixel_type, 2.2);
cpu_timer_start(&timer, "Resampling"); callback.priv = "Resampling Image"; - GP_Context *i1 = GP_FilterResize(img, NULL, resampling_method, w, h, &callback); + GP_Context *i1 = GP_FilterResize(img, NULL, params->resampling_method, w, h, &callback); // img->gamma = NULL; -// GP_Context *i2 = GP_FilterResize(img, NULL, resampling_method, w, h, &callback); +// GP_Context *i2 = GP_FilterResize(img, NULL, params->resampling_method, w, h, &callback); // img = GP_FilterDifferenceAlloc(i2, i1, NULL); // img = GP_FilterInvert(img, NULL, NULL); img = i1; @@ -326,7 +343,7 @@ GP_Context *load_resized_image(struct loader_params *params, GP_Size w, GP_Size if (img == NULL) return NULL;
- image_cache_put(params->img_resized_cache, img, params->img_path, cookie, resampling_method); + image_cache_put(params->img_resized_cache, img, params->img_path, cookie, key); return img; } @@ -380,12 +397,12 @@ static void *image_loader(void *ptr) if ((img = load_image(params, 0)) == NULL) return NULL;
- float rat = calc_img_size(img->w, img->h, w, h); + params->rat = calc_img_size(img->w, img->h, w, h);
w = img->w; h = img->h;
- img = load_resized_image(params, w * rat + 0.5, h * rat + 0.5, rat); + img = load_resized_image(params, w * params->rat + 0.5, h * params->rat + 0.5);
if (img == NULL) return NULL; @@ -393,7 +410,7 @@ static void *image_loader(void *ptr) image_cache_print(params->img_resized_cache); image_cache_print(params->img_orig_cache);
- update_display(params, img, rat); + update_display(params, img); cpu_timer_stop(&sum_timer); @@ -552,13 +569,13 @@ int main(int argc, char *argv[]) struct loader_params params = { .img_path = NULL, - .rotate = 0, - .show_progress = 0, .show_progress_once = 0, .show_info = 0, .show_nn_first = 0, .use_dithering = 0, + .rotate = 0, + .resampling_method = GP_INTERP_LINEAR_LF_INT,
.img_resized_cache = NULL, .img_orig_cache = NULL, @@ -579,7 +596,9 @@ int main(int argc, char *argv[]) sleep_sec = atoi(optarg); break; case 'c': - resampling_method = GP_INTERP_CUBIC_INT; + params.resampling_method = GP_INTERP_CUBIC_INT; + /* Cubic resampling needs low pass */ + params.use_low_pass = 1; /* Cubic resampling is slow, show nn first */ params.show_nn_first = 1; break; @@ -679,6 +698,46 @@ int main(int argc, char *argv[]) params.show_progress_once = 1; show_image(¶ms, NULL); break; + case GP_KEY_RIGHT_BRACE: + params.resampling_method++; + + if (params.resampling_method > GP_INTERP_MAX) + params.resampling_method = 0; + + if (params.resampling_method == GP_INTERP_LINEAR_LF_INT) { + params.use_low_pass = 0; + params.show_nn_first = 0; + } else { + params.use_low_pass = 1; + params.show_nn_first = 1; + } + + params.show_progress_once = 1; + show_image(¶ms, argv[argn]); + break; + case GP_KEY_LEFT_BRACE: + if (params.resampling_method == 0) + params.resampling_method = GP_INTERP_MAX; + else + params.resampling_method--; + + if (params.resampling_method == GP_INTERP_LINEAR_LF_INT) { + params.use_low_pass = 0; + params.show_nn_first = 0; + } else { + params.use_low_pass = 1; + params.show_nn_first = 1; + } + + params.show_progress_once = 1; + show_image(¶ms, argv[argn]); + break; + case GP_KEY_L: + params.use_low_pass = !params.use_low_pass; + + params.show_progress_once = 1; + show_image(¶ms, argv[argn]); + break; case GP_KEY_D: image_cache_drop(params.img_resized_cache); image_cache_drop(params.img_orig_cache);
http://repo.or.cz/w/gfxprim.git/commit/667776d0fdc6195be8c9ad201f48bb6a4b4da...
commit 667776d0fdc6195be8c9ad201f48bb6a4b4da460 Author: Cyril Hrubis metan@ucw.cz Date: Sun Jun 17 19:34:21 2012 +0200
filters: resize: Add GP_InterpolationTypeName().
diff --git a/include/filters/GP_Resize.h b/include/filters/GP_Resize.h index 1c84f2c..7b1473c 100644 --- a/include/filters/GP_Resize.h +++ b/include/filters/GP_Resize.h @@ -71,8 +71,11 @@ typedef enum GP_InterpolationType { GP_INTERP_LINEAR_LF_INT, /* Bilinear + low pass filter on downscaling */ GP_INTERP_CUBIC, /* Bicubic */ GP_INTERP_CUBIC_INT, /* Bicubic - fixed point arithmetics */ + GP_INTERP_MAX = GP_INTERP_CUBIC_INT, } GP_InterpolationType;
+const char *GP_InterpolationTypeName(enum GP_InterpolationType interp_type); + /* * Just interpolate the source context into destination context. */ diff --git a/libs/filters/GP_Resize.c b/libs/filters/GP_Resize.c index a1c0d71..6fbd5eb 100644 --- a/libs/filters/GP_Resize.c +++ b/libs/filters/GP_Resize.c @@ -58,6 +58,21 @@ GP_Context *GP_FilterResizeNNAlloc(const GP_Context *src, return res; }
+static const char *interp_types[] = { + "Nearest Neighbour", + "Linear (Int)", + "Linear with Low Pass (Int)", + "Cubic (Float)", + "Cubic (Int)", +}; + +const char *GP_InterpolationTypeName(enum GP_InterpolationType interp_type) +{ + if (interp_type > GP_INTERP_MAX) + return "Unknown"; + + return interp_types[interp_type]; +}
#define A 0.5
http://repo.or.cz/w/gfxprim.git/commit/d3f29ef699671a32207092195cc96926ed293...
commit d3f29ef699671a32207092195cc96926ed2937e3 Author: Cyril Hrubis metan@ucw.cz Date: Sun Jun 17 18:18:16 2012 +0200
spiv: Make use of the Nearest Neighbour resampling.
diff --git a/demos/spiv/spiv.c b/demos/spiv/spiv.c index d6b3da3..43c9f8d 100644 --- a/demos/spiv/spiv.c +++ b/demos/spiv/spiv.c @@ -46,10 +46,8 @@ static GP_Backend *backend = NULL;
/* image loader thread */ static int abort_flag = 0; -static int rotate = 0; static int show_progress = 0; static int resampling_method = GP_INTERP_LINEAR_LF_INT; -static int dithering = 0;
static int image_loader_callback(GP_ProgressCallback *self) { @@ -86,9 +84,18 @@ static int image_loader_callback(GP_ProgressCallback *self) struct loader_params { const char *img_path; - int show_progress; - int show_progress_once; - int show_info; + /* Show loader progress */ + long show_progress:1; + long show_progress_once:2; + /* show image info in topleft corner */ + long show_info:3; + /* use nearest neighbour resampling first */ + long show_nn_first:4; + /* use dithering when blitting to display */ + long use_dithering:5; + + /* Image orientation */ + int rotate;
/* cached loaded images */ struct image_cache *img_resized_cache; @@ -144,6 +151,10 @@ GP_Context *load_image(struct loader_params *params, int elevate)
cpu_timer_start(&timer, "Loading"); if ((img = GP_LoadImage(params->img_path, &callback)) == NULL) { + + if (errno == ECANCELED) + return NULL; + GP_Fill(context, black_pixel); GP_Print(context, NULL, context->w/2, context->h/2, GP_ALIGN_CENTER|GP_VALIGN_CENTER, white_pixel, black_pixel, @@ -168,6 +179,92 @@ GP_Context *load_image(struct loader_params *params, int elevate) return img; }
+/* + * Updates display. + */ +static void update_display(struct loader_params *params, GP_Context *img, float rat) +{ + GP_Context *context = backend->context; + struct cpu_timer timer; + GP_ProgressCallback callback = {.callback = image_loader_callback}; + + switch (params->rotate) { + case 0: + break; + case 90: + callback.priv = "Rotating image (90)"; + img = GP_FilterRotate90_Alloc(img, &callback); + break; + case 180: + callback.priv = "Rotating image (180)"; + img = GP_FilterRotate180_Alloc(img, &callback); + break; + case 270: + callback.priv = "Rotating image (270)"; + img = GP_FilterRotate270_Alloc(img, &callback); + break; + } + + if (img == NULL) + return; + + uint32_t cx = (context->w - img->w)/2; + uint32_t cy = (context->h - img->h)/2; + + GP_Context sub_display; + + cpu_timer_start(&timer, "Blitting"); + + if (params->use_dithering) { + callback.priv = "Dithering"; + GP_SubContext(context, &sub_display, cx, cy, img->w, img->h); + GP_FilterFloydSteinberg_RGB888(img, &sub_display, NULL); + // GP_FilterHilbertPeano_RGB888(img, &sub_display, NULL); + } else { + GP_Blit_Raw(img, 0, 0, img->w, img->h, context, cx, cy); + } + + cpu_timer_stop(&timer); + + if (params->rotate) + GP_ContextFree(img); + + /* clean up the rest of the display */ + GP_FillRectXYWH(context, 0, 0, cx, context->h, black_pixel); + GP_FillRectXYWH(context, 0, 0, context->w, cy, black_pixel); + GP_FillRectXYWH(context, img->w + cx, 0, context->w - img->w - cx, context->h, black_pixel); + GP_FillRectXYWH(context, 0, img->h + cy, context->w, context->h - img->h - cy, black_pixel); + + set_caption(params->img_path, rat); + + if (!params->show_info) { + GP_BackendFlip(backend); + return; + } + + GP_Size th = GP_TextHeight(NULL); + + GP_Print(context, NULL, 11, 11, GP_ALIGN_RIGHT|GP_VALIGN_BOTTOM, + black_pixel, white_pixel, "%ux%u", img->w, img->h); + + GP_Print(context, NULL, 10, 10, GP_ALIGN_RIGHT|GP_VALIGN_BOTTOM, + white_pixel, black_pixel, "%ux%u", img->w, img->h); + + GP_Print(context, NULL, 11, 13 + th, GP_ALIGN_RIGHT|GP_VALIGN_BOTTOM, + black_pixel, white_pixel, "1:%3.3f", rat); + + GP_Print(context, NULL, 10, 12 + th, GP_ALIGN_RIGHT|GP_VALIGN_BOTTOM, + white_pixel, black_pixel, "1:%3.3f", rat); + + GP_Print(context, NULL, 11, 15 + 2 * th, GP_ALIGN_RIGHT|GP_VALIGN_BOTTOM, + black_pixel, white_pixel, "%s", img_name(params->img_path)); + + GP_Print(context, NULL, 10, 14 + 2 * th, GP_ALIGN_RIGHT|GP_VALIGN_BOTTOM, + white_pixel, black_pixel, "%s", img_name(params->img_path)); + + GP_BackendFlip(backend); +} + GP_Context *load_resized_image(struct loader_params *params, GP_Size w, GP_Size h, float rat) { long cookie = (w & 0xffff) | (h & 0xffff)<<16; @@ -185,6 +282,15 @@ GP_Context *load_resized_image(struct loader_params *params, GP_Size w, GP_Size if ((img = load_image(params, 1)) == NULL) return NULL;
+ if (params->show_nn_first) { + /* Do simple interpolation and blit the result */ + GP_Context *nn = GP_FilterResizeNNAlloc(img, w, h, NULL); + if (nn != NULL) { + update_display(params, nn, rat); + GP_ContextFree(nn); + } + } + /* Do low pass filter */ if (resampling_method != GP_INTERP_LINEAR_LF_INT && rat < 1) { cpu_timer_start(&timer, "Blur"); @@ -246,9 +352,8 @@ static int resize_backend_and_blit(struct loader_params *params) static void *image_loader(void *ptr) { struct loader_params *params = ptr; - struct cpu_timer timer, sum_timer; + struct cpu_timer sum_timer; GP_Context *img, *context = backend->context; - GP_ProgressCallback callback = {.callback = image_loader_callback};
cpu_timer_start(&sum_timer, "sum"); @@ -258,7 +363,7 @@ static void *image_loader(void *ptr) /* Figure out rotation */ GP_Size w, h;
- switch (rotate) { + switch (params->rotate) { case 0: case 180: default: @@ -288,84 +393,10 @@ static void *image_loader(void *ptr) image_cache_print(params->img_resized_cache); image_cache_print(params->img_orig_cache);
- switch (rotate) { - case 0: - break; - case 90: - callback.priv = "Rotating image (90)"; - img = GP_FilterRotate90_Alloc(img, &callback); - break; - case 180: - callback.priv = "Rotating image (180)"; - img = GP_FilterRotate180_Alloc(img, &callback); - break; - case 270: - callback.priv = "Rotating image (270)"; - img = GP_FilterRotate270_Alloc(img, &callback); - break; - } - - if (img == NULL) - return NULL; - - uint32_t cx = (context->w - img->w)/2; - uint32_t cy = (context->h - img->h)/2; - - GP_Context sub_display; - - cpu_timer_start(&timer, "Blitting"); + update_display(params, img, rat); - if (dithering) { - callback.priv = "Dithering"; - GP_SubContext(context, &sub_display, cx, cy, img->w, img->h); - // GP_FilterFloydSteinberg_RGB888(ret, &sub_display, NULL); - GP_FilterHilbertPeano_RGB888(img, &sub_display, NULL); - } else { - GP_Blit_Raw(img, 0, 0, img->w, img->h, context, cx, cy); - } - - cpu_timer_stop(&timer); - - if (rotate) - GP_ContextFree(img); - - /* clean up the rest of the display */ - GP_FillRectXYWH(context, 0, 0, cx, context->h, black_pixel); - GP_FillRectXYWH(context, 0, 0, context->w, cy, black_pixel); - GP_FillRectXYWH(context, img->w + cx, 0, context->w - img->w - cx, context->h, black_pixel); - GP_FillRectXYWH(context, 0, img->h + cy, context->w, context->h - img->h - cy, black_pixel); - cpu_timer_stop(&sum_timer); - - set_caption(params->img_path, rat); - - if (!params->show_info) { - GP_BackendFlip(backend); - return NULL; - } - - GP_Size th = GP_TextHeight(NULL); - - GP_Print(context, NULL, 11, 11, GP_ALIGN_RIGHT|GP_VALIGN_BOTTOM, - black_pixel, white_pixel, "%ux%u", w, h); - - GP_Print(context, NULL, 10, 10, GP_ALIGN_RIGHT|GP_VALIGN_BOTTOM, - white_pixel, black_pixel, "%ux%u", w, h); - GP_Print(context, NULL, 11, 13 + th, GP_ALIGN_RIGHT|GP_VALIGN_BOTTOM, - black_pixel, white_pixel, "1:%3.3f", rat); - - GP_Print(context, NULL, 10, 12 + th, GP_ALIGN_RIGHT|GP_VALIGN_BOTTOM, - white_pixel, black_pixel, "1:%3.3f", rat); - - GP_Print(context, NULL, 11, 15 + 2 * th, GP_ALIGN_RIGHT|GP_VALIGN_BOTTOM, - black_pixel, white_pixel, "%s", img_name(params->img_path)); - - GP_Print(context, NULL, 10, 14 + 2 * th, GP_ALIGN_RIGHT|GP_VALIGN_BOTTOM, - white_pixel, black_pixel, "%s", img_name(params->img_path)); - - GP_BackendFlip(backend); - return NULL; }
@@ -505,6 +536,9 @@ static void init_caches(struct loader_params *params)
params->img_resized_cache = image_cache_create(resized_size); params->img_orig_cache = image_cache_create(orig_size); + +// params->img_resized_cache = NULL; +// params->img_orig_cache = NULL; }
int main(int argc, char *argv[]) @@ -512,9 +546,23 @@ int main(int argc, char *argv[]) GP_Context *context = NULL; const char *backend_opts = "X11"; int sleep_sec = -1; - struct loader_params params = {NULL, 0, 0, 0, NULL, NULL}; int opt, debug_level = 0; GP_PixelType emul_type = GP_PIXEL_UNKNOWN; + + struct loader_params params = { + .img_path = NULL, + + .rotate = 0, + + .show_progress = 0, + .show_progress_once = 0, + .show_info = 0, + .show_nn_first = 0, + .use_dithering = 0, + + .img_resized_cache = NULL, + .img_orig_cache = NULL, + };
while ((opt = getopt(argc, argv, "b:cd:e:fIPs:r:")) != -1) { switch (opt) { @@ -525,13 +573,15 @@ int main(int argc, char *argv[]) params.show_progress = 1; break; case 'f': - dithering = 1; + params.use_dithering = 1; break; case 's': sleep_sec = atoi(optarg); break; case 'c': resampling_method = GP_INTERP_CUBIC_INT; + /* Cubic resampling is slow, show nn first */ + params.show_nn_first = 1; break; case 'd': debug_level = atoi(optarg); @@ -546,11 +596,11 @@ int main(int argc, char *argv[]) break; case 'r': if (!strcmp(optarg, "90")) - rotate = 90; + params.rotate = 90; else if (!strcmp(optarg, "180")) - rotate = 180; + params.rotate = 180; else if (!strcmp(optarg, "270")) - rotate = 270; + params.rotate = 270; case 'b': backend_opts = optarg; break; @@ -622,9 +672,9 @@ int main(int argc, char *argv[]) params.show_progress = !params.show_progress; break; case GP_KEY_R: - rotate += 90; - if (rotate > 270) - rotate = 0; + params.rotate += 90; + if (params.rotate > 270) + params.rotate = 0; params.show_progress_once = 1; show_image(¶ms, NULL);
http://repo.or.cz/w/gfxprim.git/commit/0223a7dca0a58c112f3b60100e0e5f66de526...
commit 0223a7dca0a58c112f3b60100e0e5f66de5263d1 Author: Cyril Hrubis metan@ucw.cz Date: Sun Jun 17 18:16:30 2012 +0200
filters: Add generated Nearest Neighbour filter.
diff --git a/include/filters/GP_Resize.h b/include/filters/GP_Resize.h index fe6afbf..1c84f2c 100644 --- a/include/filters/GP_Resize.h +++ b/include/filters/GP_Resize.h @@ -56,6 +56,15 @@
#include "GP_Filter.h"
+/* Nearest Neighbour */ +int GP_FilterResizeNN(const GP_Context *src, GP_Context *dst, + GP_ProgressCallback *callback); + +GP_Context *GP_FilterResizeNNAlloc(const GP_Context *src, + GP_Size w, GP_Size h, + GP_ProgressCallback *callback); + + typedef enum GP_InterpolationType { GP_INTERP_NN, /* Nearest Neighbour */ GP_INTERP_LINEAR_INT, /* Bilinear - fixed point arithmetics */ diff --git a/libs/core/GP_Context.c b/libs/core/GP_Context.c index 88a0298..85530d1 100644 --- a/libs/core/GP_Context.c +++ b/libs/core/GP_Context.c @@ -276,7 +276,7 @@ void GP_ContextPrintInfo(const GP_Context *self) printf("Offsett%u (only unaligned pixel types)n", self->offset); printf("Flagstaxes_swap=%u x_swap=%u y_swap=%u free_pixels=%un", self->axes_swap, self->x_swap, self->y_swap, self->free_pixels); - printf("Gamma table %p", self->gamma); + printf("Gamma table %pn", self->gamma); }
/* diff --git a/libs/filters/GP_Resize.c b/libs/filters/GP_Resize.c index 5f42da5..a1c0d71 100644 --- a/libs/filters/GP_Resize.c +++ b/libs/filters/GP_Resize.c @@ -30,45 +30,35 @@
#include "GP_Resize.h"
-int GP_FilterInterpolate_NN(const GP_Context *src, GP_Context *dst, - GP_ProgressCallback *callback) -{ - uint32_t xmap[dst->w]; - uint32_t ymap[dst->h]; - uint32_t i; - GP_Coord x, y; - - GP_DEBUG(1, "Scaling image %ux%u -> %ux%u %2.2f %2.2f", - src->w, src->h, dst->w, dst->h, - 1.00 * dst->w / src->w, 1.00 * dst->h / src->h); +int GP_FilterResizeNN_Raw(const GP_Context *src, GP_Context *dst, + GP_ProgressCallback *callback);
- /* Pre-compute mapping for interpolation */ - uint32_t xstep = (src->w << 16) / dst->w; +int GP_FilterResizeNN(const GP_Context *src, GP_Context *dst, + GP_ProgressCallback *callback) +{ + GP_ASSERT(src->pixel_type == dst->pixel_type);
- for (i = 0; i < dst->w + 1; i++) - xmap[i] = ((i * xstep) + (1<<15)) >> 16; - - uint32_t ystep = (src->h << 16) / dst->h; + return GP_FilterResizeNN_Raw(src, dst, callback); +}
- for (i = 0; i < dst->h + 1; i++) - ymap[i] = ((i * ystep) + (1<<15)) >> 16; +GP_Context *GP_FilterResizeNNAlloc(const GP_Context *src, + GP_Size w, GP_Size h, + GP_ProgressCallback *callback) +{ + GP_Context *res = GP_ContextAlloc(w, h, src->pixel_type);
- /* Interpolate */ - for (y = 0; y < (GP_Coord)dst->h; y++) { - for (x = 0; x < (GP_Coord)dst->w; x++) { - GP_Pixel pix = GP_GetPixel_Raw_24BPP(src, xmap[x], ymap[y]); + if (res == NULL) + return NULL;
- GP_PutPixel_Raw_24BPP(dst, x, y, pix); - } - - if (GP_ProgressCallbackReport(callback, y, dst->h, dst->w)) - return 1; + if (GP_FilterResizeNN_Raw(src, res, callback)) { + GP_ContextFree(res); + return NULL; }
- GP_ProgressCallbackDone(callback); - return 0; + return res; }
+ #define A 0.5
static float cubic(float x) @@ -725,7 +715,7 @@ int GP_FilterResize_Raw(const GP_Context *src, GP_Context *dst, { switch (type) { case GP_INTERP_NN: - return GP_FilterInterpolate_NN(src, dst, callback); + return GP_FilterResizeNN_Raw(src, dst, callback); case GP_INTERP_LINEAR_INT: return GP_FilterInterpolate_LinearInt(src, dst, callback); case GP_INTERP_LINEAR_LF_INT: diff --git a/libs/filters/GP_ResizeNN.gen.c.t b/libs/filters/GP_ResizeNN.gen.c.t new file mode 100644 index 0000000..7719efb --- /dev/null +++ b/libs/filters/GP_ResizeNN.gen.c.t @@ -0,0 +1,75 @@ +%% extends "filter.c.t" + +{% block descr %}Nearest Neighbour resampling{% endblock %} + +%% block body + +#include "core/GP_Context.h" +#include "core/GP_GetPutPixel.h" + +#include "core/GP_Debug.h" + +#include "GP_Resize.h" + +%% for pt in pixeltypes +%% if not pt.is_unknown() + +static int GP_FilterResizeNN_{{ pt.name }}_Raw(const GP_Context *src, + GP_Context *dst, GP_ProgressCallback *callback) +{ + uint32_t xmap[dst->w]; + uint32_t ymap[dst->h]; + uint32_t i; + GP_Coord x, y; + + GP_DEBUG(1, "Scaling image %ux%u -> %ux%u %2.2f %2.2f", + src->w, src->h, dst->w, dst->h, + 1.00 * dst->w / src->w, 1.00 * dst->h / src->h); + + /* Pre-compute mapping for interpolation */ + uint32_t xstep = (src->w << 16) / dst->w; + + for (i = 0; i < dst->w + 1; i++) + xmap[i] = ((i * xstep) + (1<<15)) >> 16; + + uint32_t ystep = (src->h << 16) / dst->h; + + for (i = 0; i < dst->h + 1; i++) + ymap[i] = ((i * ystep) + (1<<15)) >> 16; + + /* Interpolate */ + for (y = 0; y < (GP_Coord)dst->h; y++) { + for (x = 0; x < (GP_Coord)dst->w; x++) { + GP_Pixel pix = GP_GetPixel_Raw_{{ pt.pixelsize.suffix }}(src, xmap[x], ymap[y]); + + GP_PutPixel_Raw_{{ pt.pixelsize.suffix }}(dst, x, y, pix); + } + + if (GP_ProgressCallbackReport(callback, y, dst->h, dst->w)) + return 1; + } + + GP_ProgressCallbackDone(callback); + return 0; +} + +%% endif +%% endfor + +int GP_FilterResizeNN_Raw(const GP_Context *src, GP_Context *dst, + GP_ProgressCallback *callback) +{ + switch (src->pixel_type) { + %% for pt in pixeltypes + %% if not pt.is_unknown() + case GP_PIXEL_{{ pt.name }}: + return GP_FilterResizeNN_{{ pt.name }}_Raw(src, dst, callback); + break; + %% endif + %% endfor + default: + return -1; + } +} + +%% endblock body diff --git a/libs/filters/Makefile b/libs/filters/Makefile index 49993aa..1470e55 100644 --- a/libs/filters/Makefile +++ b/libs/filters/Makefile @@ -8,8 +8,10 @@ POINT_FILTERS=GP_Contrast.gen.c GP_Brightness.gen.c GP_Invert.gen.c ARITHMETIC_FILTERS=GP_Difference.gen.c GP_Addition.gen.c GP_Min.gen.c GP_Max.gen.c GP_Multiply.gen.c
+RESAMPLING_FILTERS=GP_ResizeNN.gen.c + GENSOURCES=GP_MirrorV.gen.c GP_Rotate.gen.c GP_FloydSteinberg.gen.c GP_HilbertPeano.gen.c- $(POINT_FILTERS) $(ARITHMETIC_FILTERS) $(STATS_FILTERS) + $(POINT_FILTERS) $(ARITHMETIC_FILTERS) $(STATS_FILTERS) $(RESAMPLING_FILTERS)
CSOURCES=$(filter-out $(wildcard *.gen.c),$(wildcard *.c)) LIBNAME=filters
http://repo.or.cz/w/gfxprim.git/commit/5bc6361309104e85c8a54add16ca23554bf65...
commit 5bc6361309104e85c8a54add16ca23554bf65827 Author: Cyril Hrubis metan@ucw.cz Date: Sun Jun 17 17:37:27 2012 +0200
spiv: Make image cache functions No-Op when cache pointer is NULL.
Spiv is not ready for the change though.
diff --git a/demos/spiv/image_cache.c b/demos/spiv/image_cache.c index 4cb194f..924c392 100644 --- a/demos/spiv/image_cache.c +++ b/demos/spiv/image_cache.c @@ -155,6 +155,9 @@ GP_Context *image_cache_get(struct image_cache *self, const char *path, long cookie1, long cookie2, int elevate) { struct image *i; + + if (self == NULL) + return NULL;
GP_DEBUG(2, "Looking for image '%s:%10li:%10li'", path, cookie1, cookie2);
@@ -186,6 +189,11 @@ void image_cache_print(struct image_cache *self) { struct image *i;
+ if (self == NULL) { + printf("Image cache disabledn"); + return; + } + printf("Image cache size %u used %un", self->max_size, self->cur_size);
for (i = self->root; i != NULL; i = i->next) @@ -214,7 +222,12 @@ static int assert_size(struct image_cache *self, size_t size) int image_cache_put(struct image_cache *self, GP_Context *ctx, const char *path, long cookie1, long cookie2) { - size_t size = image_size2(ctx, path); + size_t size; + + if (self == NULL) + return 1; + + size = image_size2(ctx, path);
if (assert_size(self, size)) return 1; @@ -242,8 +255,11 @@ int image_cache_put(struct image_cache *self, GP_Context *ctx, const char *path,
void image_cache_drop(struct image_cache *self) { + if (self == NULL) + return; + GP_DEBUG(1, "Dropping images in cache"); - + while (self->end != NULL) remove_img_free(self, self->end, 0);
@@ -252,8 +268,11 @@ void image_cache_drop(struct image_cache *self)
void image_cache_destroy(struct image_cache *self) { + if (self == NULL) + return; + GP_DEBUG(1, "Destroying image cache"); - + while (self->end != NULL) remove_img_free(self, self->end, 0);
-----------------------------------------------------------------------
Summary of changes: demos/spiv/image_cache.c | 25 +++- demos/spiv/spiv.c | 339 +++++++++++++++++++++++++------------- include/filters/GP_Resize.h | 12 ++ libs/core/GP_Context.c | 2 +- libs/filters/GP_Resize.c | 93 +++++------ libs/filters/GP_ResizeNN.gen.c.t | 74 ++++++++ libs/filters/Makefile | 4 +- 7 files changed, 382 insertions(+), 167 deletions(-) create mode 100644 libs/filters/GP_ResizeNN.gen.c.t
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.