Jump to content

Felix The Ghost

Members
  • Posts

    20
  • Joined

  • Last visited

Posts posted by Felix The Ghost

  1. I just downloaded and tried the Paint.net 4 Beta and though I like the improvements, I am surprised there still isn't an option (that I see) to toggle selection edges.

     

    I did a forum search and it seems some users don't see the use of it, but as a Photoshop user I can personally attest to the convenience of hiding them when you have already made your selection and are experimenting with adjustments within the selection (e.g. color adjustments) It gives you a more accurate visual of the render while you are in the effect window before it is finalized.

     

    Currently in Paint.net I can make a selection, copy its contents into a new layer, then open the desired adjustment/filter window(s) without a selection as it will affect the entire layer (which only contains what we pasted in)

     

    But that is a lot of work around for what could be as easy as a keyboard shortcut and/or a menu item in View->Selection Edges

     

    And in implementation, I cannot imagine it being hard to add logic to NOT render the edges. You can even unset the option when the selection is modified if we are afraid it will confuse some users.

     

    I would like to see this implemented in the next beta release (assuming it's not there and I missed it)

     

    Thanks.

  2.  

    Since random is Psuedo Random Simply Seed the Random generator with the color in question and all the ROI's are in sync.

     

    Very clever!

     

    I see you got it to respect selections too!

     

    I still don't know what you use

    object sync = new object();
    

    for in the code though.

     

    I also like the reseed button but I can probably figure that out. I thought I posted this but I guess I closed the browser before posting.

  3. 1024X768 rendered at 1 minute 40 seconds like before

     

    I don't mean to sound repetitive but there isn't enough information there to judge speed.

    I can create a 1024x768 blank image, draw a gradient and posterize it to reduce colors (reduced to 43 colors in my test) and the plugin renders in less than three seconds. Since each pixel loops through colors[] the amount of unique colors greatly affects speed :)

     

    I will have to see if there is some c# container that retains order but has quick-access (keyword or something)

    Rick, does ConcurrentSet preserve order? There needs to be a copy of the container with tweaked colors. Maybe it can be a concurrentSet with a custom struct of two colors so order is no longer important?

     

    You should test on those linked images if you haven't yet (you can drag and drop into Paint.net)

  4. Will check it out when I can! Thanks for the help so far.

     

    Append: I think it is important to note that it is intended to be used on images with few colors like these (not my work, just illustrates my point)

    Large image, but few colors, renders in less than two seconds for me.

    and

    Less than one second on this one

     

    Maybe it is possible to build in a safety when there are over say 512 unique colors (or maybe a slider) to not render if it will be slow and take a long time to cancel.

     

    And you are right the multithreaded one has a different effect than I am aiming for. I am basically mutating colors into other colors randomly with a randomly generated "palette swap" so every instance of a specific color is changed the same way.

     

    I do not understand this code:

    Random rndm = new Random((int)Guid.NewGuid().GetHashCode());
    

    I thought RandomNumber was specifically created to be the best option for Code Lab?

     

    I also am not sure but wouldn't this

            Color[] colors = new Color[rect.Width * rect.Height];
            Color[] off_colors = new Color[rect.Width * rect.Height];
    

    negatively affect performance? It seems to assume each pixel of the image is a unique color rather than expanding in size as new unique colors are identified. I am not familiar with all the C# container classes but I do think the container should have a dynamic size (I do not know how that affects threading) Perhaps we can use ConcurrentSet as Rick recommends?

     

    This is what I am using to count unique colors in the image some images on google from older games that would be great examples have JPEG compression and you can see through the plugin it gives them many unique colors which slow down the effect. The posterize effect can help reduce color.

     

    Also, I noticed the effect ignores selections except in the preview and transparency is lost. I made a filter using CodeLab before and it respects selections, so I do not know what is wrong.

     

    I'll have to investigate further tomorrow but I wanted to give feedback  immediately as I appreciate your help.

  5. This is really frustrating. I keep changing code with poor version control so I'm posting this to see if anyone sees something obviously wrong that I don't.

    #region UICode
    int Amount1=1;    //[0,100]Hue Adjust
    int Amount2=1;    //[0,100]Saturation Adjust
    int Amount3=1;    //[0,100]Value Adjust
    byte Amount4 = 0; // [255] Reseed
    #endregion
    
    List<Color> colors = new List<Color>();
    List<Color> off_colors = new List<Color>();
    
    object sync = new object();
    
    void Render(Surface dst, Surface src, Rectangle rect)
    {
        bool match = false;
        ColorBgra CurrentPixel;
        
        //populate colors
            
        for (int y = rect.Top; y < rect.Bottom; y++)
        {
            for (int x = rect.Left; x < rect.Right; x++)
            {
                
                CurrentPixel = src[x,y];
                match = false;
                
                lock (sync)
                {
                    for (int i = 0; i < colors.Count; i++)
                    {                
                        if (CurrentPixel.ToColor().Equals(colors[i]))
                        {
                            match = true;
                            break;
                        }
                    }
                    if (!match)
                    {
                        colors.Add(CurrentPixel.ToColor());
                    }
                }
                    
            }
        }
        
        //tweak colors
        
        HsvColor hsv;
        int H = 0, S = 0, V = 0;
        
        for (int i = 0; i < colors.Count; i++)
        {                
            //hsv = HsvColor.FromColor(colors[i]);
                        
            //H = hsv.Hue;
            //S = hsv.Saturation;
            //V = hsv.Value;
                        
            //H -= (RandomNumber.Next(Amount1 * 180 / 100));
            //H += (RandomNumber.Next(Amount1 * 180 / 100));
                        
            //S -= (RandomNumber.Next(Amount2) / 2);
            //S += (RandomNumber.Next(Amount2) / 2);
                        
            //V -= RandomNumber.Next(Amount3) / 2;
            //V += RandomNumber.Next(Amount3) / 2;
                        
            //if (H < 0) H = 360;
            //if (H > 360) H = 360;
                    
            //if (S < 0) S = 0;
            //if (S > 100) S = 100;
                        
            //if (V < 0) V = 100;
            //if (V > 100) V = 100;
                        
            //hsv = new HsvColor(H,S,V);
                    
            //off_colors.Add(hsv.ToColor());
            off_colors.Add(colors[i]);
    
        }
        
        // Colorize
        
        for (int y = rect.Top; y < rect.Bottom; y++)
        {
            for (int x = rect.Left; x < rect.Right; x++)
            {           
            CurrentPixel = src[x,y];
                
            for (int i = 0; i < colors.Count; i++)
            {                
                if (CurrentPixel.ToColor().Equals(colors[i]))
                {
                    CurrentPixel = ColorBgra.FromColor(off_colors[i]);
                    break;
                }
            }
                dst[x,y] = CurrentPixel;
    
            }
        }
    }
    
  6. Looked good at a glance, but Paint.net uses int and not double for hsv.

     

    So what is the functional range of H, S, V?

     

    Edit: Going to guess based on the color window in Paint.net: 0..360 0..100 0..100

     

    Append: Seems to work well, but I have trouble accessing the user variables Amount1 etc within the lock() sections. It just returns the value they were initialized with :(

  7. One of my tutorials has a section on it.

    http://boltbait.com/pdn/CodeLab/help/tutorial4.asp

    Hope this helps.

    Thanks, I'm aware of that tutorial, but I'm surprised there isn't something somewhere that's more in-depth (Even just the source code for the data types would help) I don't even know the  functional ranges of H/S/B. (like R/G/B is 0-255) The tutorial does confirm my suspicions on the need to reassemble the structure each time a member is modified, though.

  8. This is what I have so far:

    #region UICode
    int Amount1=3;	//[0,255]Hue Variation
    #endregion
    
    List<ColorBgra> colors = new List<ColorBgra>();
    List<ColorBgra> off_colors = new List<ColorBgra>();
    HsvColor hsv = new HsvColor(0,0,0);
    int hue_plus = 0;
    int hue_minus = 0;
    
    bool match = false;
    object sync = new object();
    Random rnd = new Random();
    
    void Render(Surface dst, Surface src, Rectangle rect)
    {
        ColorBgra CurrentPixel;
        for (int y = rect.Top; y < rect.Bottom; y++)
        {
            for (int x = rect.Left; x < rect.Right; x++)
            {
                lock (sync)
                {
                CurrentPixel = src[x,y];
                
                for (int i = 0; i < colors.Count; i++)
                {                
                    if (CurrentPixel.Equals(colors[i]))
                    {
                        match = true;
                        CurrentPixel = off_colors[i];
                        break;
                    }
                }
                if (!match)
                {
                    colors.Add(CurrentPixel);
                    hsv = HsvColor.FromColor(CurrentPixel);
                    hue_plus = rnd.Next((Amount1/2));
                    hue_minus = rnd.Next((Amount1/2));
                    hsv.Hue += hue_plus;
                    hsv.Hue -= hue_minus;
                    off_colors.Add(ColorBgra.FromColor(hsv.ToColor()));
                    
                    CurrentPixel = ColorBgra.FromColor(hsv.ToColor());
                }
    
                
                dst[x,y] = CurrentPixel;
                match = false;
                }
            }
        }
    }
    
    

    Both Lists are increased in size at the same step so they should stay the same size.

    Lots of redundant code in the (!match) block because I guess I don't understand the ColorBgra/HsvColor data types; What was supposed to be a simple += turned into that experimental mess (still doesn't work -- guessing this kind of behavior is not allowed and the struct needs to be recreated each time instead of modifying its members directly?) Not sure where to read up on the datatypes Paint.net uses. I couldn't even tell you the data types of their members though I found out r,g,b,a are bytes.

     

    The goal is to be able to "tweak" colors in an image randomly to sort of mutate placeholder colors into something more desirable.

  9. Referring to your site (contains typo, by the way), "When Paint.NET is getting ready to render your effect, it breaks up the current selection into conveinent work units" -- I think this may be causing desynchronization across the units in a function I am developing.
     
    I am creating a List that all these work units read/modify realtime to index colors in an image (currently placing color for the first occurrence of a new color in the image) but sometimes it can index a few colors more than once.
     
    How might I modify this code to avoid this issue?
     

    #region UICode
    #endregion
    
    List<ColorBgra> colors = new List<ColorBgra>();
    
    bool match = false;
    
    void Render(Surface dst, Surface src, Rectangle rect)
    {
        ColorBgra CurrentPixel;
        for (int y = rect.Top; y < rect.Bottom; y++)
        {
            for (int x = rect.Left; x < rect.Right; x++)
            {
                CurrentPixel = src[x,y];
                
                for (int i = 0; i < colors.Count; i++)
                {                
                    if (CurrentPixel.Equals(colors[i]))
                    {
                        match = true;
                        break;
                    }
                }
                if (!match) //first occurrence of color
                {
                    colors.Add(CurrentPixel);
                    CurrentPixel.R = 255; //mark pixels so I can count the number of colors for debug purposes
                    CurrentPixel.G = 0;
                    CurrentPixel.B = 255;
                }
                
                dst[x,y] = CurrentPixel;
                match = false;
            }
        }
    }
    
    
  10. Hey, great work. Very easy to work with and well documented.

    However, I feel a feature this is lacking (or perhaps I missed the documentation of it) is utilizing the new drop-down feature for presets.

     

    I know, you technically can select and use psedo-presets but I'd like Codelab to have a method of updating the users sliders to reflect values set from a preset (or the randomize button)

     

    It appears the Amountx values are written to by the users sliders but not vice-versa (makes sense though I wish there was a way to write to the sliders)

     

    Example (ignoring that Amounts2-4 would keep getting reassigned without a hypothetical detectChange() and updateSliders() method.

    #region UICode
    byte Amount1 = 0; // Use Preset|Custom|First Preset
    ...
    
    if (Amount1 != 0) //not custom
        {
            Amount2 = 5; //preset values (does not update sliders intuitively for user to tweak)
            Amount3 = 10; //preset values (does not update sliders intuitively for user to tweak)
            Amount4 = 15; //preset values (does not update sliders intuitively for user to tweak)
        }
    

    Again hopefully there is a way I just failed to notice but if not this would be much appreciated functionality for many.

×
×
  • Create New...