Jump to content

A painfully slow code in CodeLab


Reptillian

Recommended Posts

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 by Reptillian

G'MIC Filter Developer

Link to comment
Share on other sites

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 by Reptillian

G'MIC Filter Developer

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...