Reptillian Posted December 17, 2021 Share Posted December 17, 2021 (edited) Why is this so slow? The other time I did something like this, it was much faster. It's on PreRender that's the problem. Take out the code in Render, and it's still slow. Spoiler // Name: Emboss / Relief + // Submenu: Stylize // Author: Reptorian // Title: Emboss / Relief + // Version: // Desc: // Keywords: // URL: // Help: #region UICode IntSliderControl radius = 5; // [5,100] Radius AngleControl var_angle = 45; // [-180,180] Angle DoubleSliderControl sigma = 0.5; // [0.5,4] Sigma DoubleSliderControl scale_value = 2; // [0.5,10] Value Scale ListBoxControl output = 0; // Output|Emboss|Relief #endregion double[] convolve_a; double[] convolve_b; int cut(int v,int image_max_index){ return Math.Max(0,Math.Min(v,image_max_index)); } int d2i(double v){ return (int)(Math.Round(v)); } // This single-threaded function is called after the UI changes and before the Render function is called // The purpose is to prepare anything you'll need in the Render function void PreRender(Surface dst, Surface src) { convolve_a = new double[radius]; convolve_b = new double[radius]; double d_radius = (double)(radius-1); double center_index = d_radius / 2; double sigma_exp = 2 * sigma * sigma; double sqrsig= sigma * Math.Sqrt(2*Math.PI); double M = 3* sigma; double vp,g,gp; double sum=0; for (int p = 0 ; p < radius ; radius++){ vp = (p - center_index)/center_index*M; g = Math.Exp(-(vp*vp)/sigma_exp)/sqrsig; gp = (vp / (sigma*sigma))*g; sum+=g; convolve_a[p]=g; convolve_b[p]=gp; } double scaling = sum / scale_value; for (int p = 0 ; p < radius ; radius++){ convolve_a[p]/=scaling; convolve_b[p]/=scaling; } } // Here is the main multi-threaded render function // The dst canvas is broken up into rectangles and // your job is to write to each pixel of that rectangle void Render(Surface dst, Surface src, Rectangle rect) { double theta = var_angle / 180 * Math.PI; double cos_theta = Math.Cos(theta); double sin_theta = Math.Sin(theta); int max_x = src.Width - 1; int max_y = src.Height - 1; int center = (int)(Math.Ceiling((double)(radius)/2)); double inner_convolve_a_r,inner_convolve_a_g,inner_convolve_a_b,inner_convolve_b_r,inner_convolve_b_g,inner_convolve_b_b; double outer_convolve_a_r,outer_convolve_a_g,outer_convolve_a_b,outer_convolve_b_r,outer_convolve_b_g,outer_convolve_b_b; double result_r,result_g,result_b; int new_r,new_g,new_b; int start_x,start_y; ColorBgra Reference_Color_A,Reference_Color_B; // Step through each row of the current rectangle for (int y = rect.Top; y < rect.Bottom; y++) { if (IsCancelRequested) return; // Step through each pixel on the current row of the rectangle for (int x = rect.Left; x < rect.Right; x++) { start_x=x-center; start_y=y-center; inner_convolve_a_r = inner_convolve_a_g = inner_convolve_a_b = inner_convolve_b_r = inner_convolve_b_g = inner_convolve_b_b = 0; outer_convolve_a_r = outer_convolve_a_g = outer_convolve_a_b = outer_convolve_b_r = outer_convolve_b_g = outer_convolve_b_b = 0; for (int p = 0 ; p < radius ; p++) { for (int q = 0 ; q < radius ; q++) { Reference_Color_A = src[cut(start_x+q,max_x),cut(start_y+p,max_y)]; inner_convolve_a_r+=(double)(Reference_Color_A.R)*convolve_a[q]; inner_convolve_a_g+=(double)(Reference_Color_A.G)*convolve_a[q]; inner_convolve_a_b+=(double)(Reference_Color_A.B)*convolve_a[q]; Reference_Color_B = src[cut(start_x+p,max_x),cut(start_y+q,max_y)]; inner_convolve_b_r+=(double)(Reference_Color_B.R)*convolve_b[q]; inner_convolve_b_g+=(double)(Reference_Color_B.G)*convolve_b[q]; inner_convolve_b_b+=(double)(Reference_Color_B.B)*convolve_b[q]; } outer_convolve_a_r += inner_convolve_a_r * convolve_b[p]; outer_convolve_a_g += inner_convolve_a_r * convolve_b[p]; outer_convolve_a_b += inner_convolve_a_r * convolve_b[p]; outer_convolve_b_r += inner_convolve_a_r * convolve_a[p]; outer_convolve_b_g += inner_convolve_a_r * convolve_a[p]; outer_convolve_b_b += inner_convolve_a_r * convolve_a[p]; inner_convolve_a_r = inner_convolve_a_g = inner_convolve_a_b = inner_convolve_b_r = inner_convolve_b_g = inner_convolve_b_b = 0; } result_r = cos_theta * outer_convolve_a_r + sin_theta * outer_convolve_b_r ; result_g = cos_theta * outer_convolve_a_g + sin_theta * outer_convolve_b_g ; result_b = cos_theta * outer_convolve_a_b + sin_theta * outer_convolve_b_b ; if (output == 1) { new_r = src[x,y].R + d2i(result_r); new_g = src[x,y].G + d2i(result_g); new_b = src[x,y].B + d2i(result_b); dst[x,y] = ColorBgra.FromBgraClamped(new_b,new_g,new_r,src[x,y].A); } else { new_r = 128 + d2i(result_r); new_g = 128 + d2i(result_g); new_b = 128 + d2i(result_b); dst[x,y] = ColorBgra.FromBgraClamped(new_b,new_g,new_r,src[x,y].A); } } } } Edited December 17, 2021 by Reptillian Quote G'MIC Filter Developer Link to comment Share on other sites More sharing options...
otuncelli Posted December 17, 2021 Share Posted December 17, 2021 (edited) For both loops in PreRender method. for (int p = 0 ; p < radius ; radius++){ // <-------- p++ ... } Edited December 17, 2021 by otuncelli 1 1 Quote Link to comment Share on other sites More sharing options...
Reptillian Posted December 17, 2021 Author Share Posted December 17, 2021 (edited) Oh, I did not saw that! Thanks! Also, it seems the that convolution did not work as expected. Rotate either gives too high or low value. Oh well, I tried. Edited December 17, 2021 by Reptillian Quote G'MIC Filter Developer Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.