Hi, I just looked into bumpmap.c and tried to figure out if it can profit from blocking and played a bit with the code. It seems that there is some major (performance) problem with the gimp_pixel_rgn_get/set_row-calls in Gimp 1.2.1. The original bumpmap took for my 1400*1400 image about 30s, when I commented out one of the gimp_pixel_rgn_get/set_row() that access the source or the destination image, the whole stuff took only about 2.4s, while the calculations were still done! I experimented a bit, and found out, that apparently the "switch" between get and set seems to be the problem. I changed the code to get 32 rows, calculate them and the write the 32 back. It took only 3s overall, the resulting image is the same as with the 30s boiling time. That's a speedup of 10! Can someone please try the patch and confirm that I'm not dreaming? -- Georg Acher, acher@xxxxxxxxx http://www.in.tum.de/~acher/ "Oh no, not again !" The bowl of petunias
--- bumpmap.c.org Thu Apr 5 21:01:03 2001 +++ bumpmap.c Thu Apr 5 23:26:39 2001 @@ -500,6 +500,7 @@ gimp_drawable_detach (drawable); } +#define BLOCKS 32 static void bumpmap (void) { @@ -509,8 +510,8 @@ gint bm_width, bm_height, bm_bpp, bm_has_alpha; gint yofs1, yofs2, yofs3; guchar *bm_row1, *bm_row2, *bm_row3, *bm_tmprow; - guchar *src_row, *dest_row; - gint y; + guchar *src_row[BLOCKS], *dest_row[BLOCKS]; + gint y,n; gint progress; gint tmp; @@ -551,8 +552,11 @@ bm_row2 = g_new (guchar, bm_width * bm_bpp); bm_row3 = g_new (guchar, bm_width * bm_bpp); - src_row = g_new (guchar, sel_width * img_bpp); - dest_row = g_new (guchar, sel_width * img_bpp); + for(n=0;n<BLOCKS;n++) + { + src_row[n] = g_new (guchar, sel_width * img_bpp); + dest_row[n] = g_new (guchar, sel_width * img_bpp); + } /* Initialize pixel regions */ gimp_pixel_rgn_init (&src_rgn, drawable, @@ -576,32 +580,40 @@ progress = 0; - for (y = sel_y1; y < sel_y2; y++) + for (y = sel_y1; y < sel_y2; y+=BLOCKS) { - gimp_pixel_rgn_get_row (&src_rgn, src_row, sel_x1, y, sel_width); - - bumpmap_row (src_row, dest_row, sel_width, img_bpp, img_has_alpha, - bm_row1, bm_row2, bm_row3, bm_width, bmvals.xofs, - bmvals.tiled, - y == CLAMP (y, - bmvals.yofs, - bmvals.yofs + bm_height), - ¶ms); - - gimp_pixel_rgn_set_row (&dest_rgn, dest_row, sel_x1, y, sel_width); - - /* Next line */ - - bm_tmprow = bm_row1; - bm_row1 = bm_row2; - bm_row2 = bm_row3; - bm_row3 = bm_tmprow; - - if (++yofs3 == bm_height) - yofs3 = 0; - - gimp_pixel_rgn_get_row (&bm_rgn, bm_row3, 0, yofs3, bm_width); - bumpmap_convert_row (bm_row3, bm_width, bm_bpp, bm_has_alpha, params.lut); - - gimp_progress_update ((double) ++progress / sel_height); + + for(n=0;n<BLOCKS && (y+n) != sel_y2;n++) + { + gimp_pixel_rgn_get_row (&src_rgn, src_row[n], sel_x1, y+n, sel_width); + + bumpmap_row (src_row[n], dest_row[n], sel_width, img_bpp, img_has_alpha, + bm_row1, bm_row2, bm_row3, bm_width, bmvals.xofs, + bmvals.tiled, + (y+n) == CLAMP (y+n, - bmvals.yofs, - bmvals.yofs + bm_height), + ¶ms); + + /* Next line */ + + bm_tmprow = bm_row1; + bm_row1 = bm_row2; + bm_row2 = bm_row3; + bm_row3 = bm_tmprow; + + if (++yofs3 == bm_height) + yofs3 = 0; + + gimp_pixel_rgn_get_row (&bm_rgn, bm_row3, 0, yofs3, bm_width); + bumpmap_convert_row (bm_row3, bm_width, bm_bpp, bm_has_alpha, params.lut); + + } + + for(n=0;n<BLOCKS && (y+n) != sel_y2;n++) + { + gimp_pixel_rgn_set_row (&dest_rgn, dest_row[n], sel_x1, y+n, sel_width); + } + gimp_progress_update ((double) progress / sel_height); + progress+=BLOCKS; } /* Done */ @@ -609,9 +621,11 @@ g_free (bm_row1); g_free (bm_row2); g_free (bm_row3); - g_free (src_row); - g_free (dest_row); - + for(n=0;n<BLOCKS;n++) + { + g_free (src_row[n]); + g_free (dest_row[n]); + } if (bm_drawable != drawable) gimp_drawable_detach (bm_drawable);