Reptillian

So, there seem to be a problem with modulo calculation. (Solved)

Recommended Posts

I have this code right here I have made out of trying something new. And I find that there doesn't seem to be a easy way to preserve 0,255 ranges on Divisive Modulo.

 

// Name: Image Modulo Toolkit
// Submenu: Adjustments
// Author: Reptorian
// Title: Image Modulo Toolkit
// Version: .5
// Desc: Adjust image values based on the logics of Krita Modulo Blending Modes, or G'MIC 'modf' or 'modular_formula'.
// Keywords:
// URL:
// Help:
#region UICode
ListBoxControl Amount1 = 0; // Blending Mode | Modulo | Modulo Continuous | Divisive Modulo
IntSliderControl Amount2 = 255; // [1,255] Maximum Number
#endregion

void Render(Surface dst, Surface src, Rectangle rect)
{
    // Delete any of these lines you don't need
    Rectangle selection = EnvironmentParameters.GetSelection(src.Bounds).GetBoundsInt();
    int CenterX = ((selection.Right - selection.Left) / 2) + selection.Left;
    int CenterY = ((selection.Bottom - selection.Top) / 2) + selection.Top;
    ColorBgra PrimaryColor = EnvironmentParameters.PrimaryColor;
    ColorBgra SecondaryColor = EnvironmentParameters.SecondaryColor;
    int BrushWidth = (int)EnvironmentParameters.BrushWidth;

    ColorBgra CurrentPixel;
    for (int y = rect.Top; y < rect.Bottom; y++)
    {
        if (IsCancelRequested) return;
        for (int x = rect.Left; x < rect.Right; x++)
        {
            CurrentPixel = src[x,y];
            int R = (int)CurrentPixel.R;
            int G = (int)CurrentPixel.G;
            int B = (int)CurrentPixel.B;
            float DivMult= 255/Amount2;
            switch(Amount1)
            {
               case 0: R=(byte)(R%(Amount2+1));
                       G=(byte)(G%(Amount2+1));
                       B=(byte)(B%(Amount2+1));
                       break;
               case 1: int TR=R/(Amount2+1);
                       int TG=G/(Amount2+1);
                       int TB=B/(Amount2+1);
                       bool CR=TR%2==1;
                       bool CG=TG%2==1;
                       bool CB=TB%2==1;
                       if (CR) {R=(byte)(Amount2-(R%(Amount2+1)));} else {R=(byte)(R%(Amount2+1));}
                       if (CG) {G=(byte)(Amount2-(G%(Amount2+1)));} else {G=(byte)(G%(Amount2+1));}
                       if (CB) {B=(byte)(Amount2-(B%(Amount2+1)));} else {B=(byte)(R%(Amount2+1));}
                       break;
              case 2:  float MTR=R%(Amount2+1);
                       float MTG=G%(Amount2+1);
                       float MTB=B%(Amount2+1);
                       MTR*=(float)(DivMult);
                       MTG*=(float)(DivMult);
                       MTB*=(float)(DivMult);
                       int NMTR = (int)(MTR);
                       int NMTG = (int)(MTG);
                       int NMTB = (int)(MTB);
                       R=(byte)(NMTR);
                       G=(byte)(NMTG);
                       B=(byte)(NMTB);
                       break;         
            }
            CurrentPixel = ColorBgra.FromBgra((byte)(B),(byte)(G),(byte)(R),CurrentPixel.A);
            dst[x,y] = CurrentPixel;
        }
    }
}

I know the case 2 could be simpler, but haven't really figured it out.

Edited by Reptillian

Share this post


Link to post
Share on other sites
16 minutes ago, Reptillian said:

And I find that there doesn't seem to be a easy way to preserve 0,255 ranges on Divisive Modulo.

 

If you need to clamp the RGB values, you can do this:

CurrentPixel = ColorBgra.FromBgraClamped(B, G, R, CurrentPixel.A);

 

Or did I misunderstand your question?

Share this post


Link to post
Share on other sites
6 minutes ago, toe_head2001 said:

 

If you need to clamp the RGB values, you can do this:


CurrentPixel = ColorBgra.FromBgraClamped(B, G, R, CurrentPixel.A);

 

Or did I misunderstand your question?

 

You misunderstood. If you use 175 for Divisive Modulo, you'd note that the highest value is not 255, and the expected value is 255. While you shift value, it should behave similar to the first 2 modulo modes. That didn't really work as a solution.

Edited by Reptillian

Share this post


Link to post
Share on other sites

CodeLab has Debug Output capabilities; I suggest you use it. Click on the associated Checkbox at the bottom of CodeLab.

 

For example, if you want to evaluate your math expressions, you can do this:

void PreRender(Surface dst, Surface src)
{
    int R = 255;
    float DivMult = 255 / Amount2;
    Debug.WriteLine("DivMult: " + DivMult);

    float MTR = R % (Amount2 + 1);
    Debug.WriteLine("MTR: " + MTR);

    MTR *= (float)(DivMult);
    Debug.WriteLine("MTR: " + MTR);

    int NMTR = (int)(MTR);
    Debug.WriteLine("NMTR: " + NMTR);

    R = (byte)(NMTR);
    Debug.WriteLine("R: " + R);
}

 

  • Upvote 1

Share this post


Link to post
Share on other sites

I don't know if this will solve the problem you're referring to, but I doubt this line does what you want it to do:

float DivMult= 255/Amount2;

Amount2 is an int, as is 255, so an integer divide will be performed, and the (integer) result converted to a float. I suspect that's not what's intended.

 

Try:

float DivMult= 255.0 / (float)Amount2;

(Also, the line should be moved outside the loop. It can be computed once at the top.)

  • Like 1

Share this post


Link to post
Share on other sites

I should have mentioned I solved It. Anyways, when I was coding that, I realized that when coding for c#, it is not like c++ or the gmic scripting language and did not taken the account for the need of converting Amount2 into a float. I knew that I have to work with converting types. It was fun doing something different once in a while.

 

 

Share this post


Link to post
Share on other sites
3 hours ago, Reptillian said:

I realized that when coding for c#, it is not like c++

 

C++ does the same thing as C#. Both treat a division of two ints as an integer division, as does C.

Share this post


Link to post
Share on other sites
24 minutes ago, MJW said:

C++ does the same thing as C#. Both treat a division of two ints as an integer division, as does C.

I have checked, and yes you're correct. It seems that I have forgotten some fair bit of c++ after not using it in a while.

Share this post


Link to post
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.