Jump to content

Need Plugin: Reduce Image to very few colors


Recommended Posts

What am I looking for:

I am looking for a plugin that takes an image and reduces the colors to a very small number (e.g. <10). Additionally, large areas should have the same color (i am not interested in single pixel having a different color than the pixels around.

 

Where do I need this:

My wife bought an embroidery machine. On the internet we can look for cliparts as embroidery pattern (private usage only). Usually we find an image that looks good. If this image only consists of, lets say, 8 images, everything is fine. We import it into the stitching program, tell the program to stitch the red parts of the image in some way, the green parts in some other way and so on. However, the program relies on the pixel to have EXACTLY the same color.

The problem arises, if the image was saved as jpeg or if some antialializing smoothed black borders or something similar.

 

What we did so far:

Until now, I worked with gimp, used the function "Threshold" to make a black/white image essentially only containing the black borders and flood-filling everything again.

 

What might be special in my case:

I am not interested in single pixels. If, by antialializing, a pixel an a black border of a red area is somewhere between black and red i do not care how the plugin colors it, as long as it is either black or red.

However, I do not want small areas of pixels having a different color than its neighbourhood.

Link to comment
Share on other sites

Paint.net has a built-in effect that may do the trick. Try Adjustments > Posterize. Move the sliders down to, like, 2 or 3.

Or, you could try this plugin for 2 colors:

Stencil.zip

Once installed, it is under Effects > Color > Stencil

// Name: Stencil
// Submenu: Color
// Author: BoltBait
// Title: Stencil v1.0
// Desc: Reduce photograph down to 2 colors
// Keywords: posterize|stencil
// URL: http://www.BoltBait.com/pdn
#region UICode
int Amount1 = 10; // [-100,100] Balance
ColorBgra Amount2 = ColorBgra.FromBgr(255,255,255); // Bright Color
ColorBgra Amount3 = ColorBgra.FromBgr(0,0,0); // Dark Color
#endregion

// Setup for using pixel op
private UnaryPixelOps.Desaturate desaturateOp = new UnaryPixelOps.Desaturate();

// Here is the main render loop function
void Render(Surface dst, Surface src, Rectangle rect)
{
    // Setup for calling the Brightness and Contrast Adjustment function
    BrightnessAndContrastAdjustment bacAdjustment = new BrightnessAndContrastAdjustment();
    PropertyCollection bacProps = bacAdjustment.CreatePropertyCollection();
    PropertyBasedEffectConfigToken bacParameters = new PropertyBasedEffectConfigToken(bacProps);
    bacParameters.SetPropertyValue(BrightnessAndContrastAdjustment.PropertyNames.Brightness, Amount1);
    bacParameters.SetPropertyValue(BrightnessAndContrastAdjustment.PropertyNames.Contrast, 100);
    bacAdjustment.SetRenderInfo(bacParameters, new RenderArgs(dst), new RenderArgs(src));
    // Call the Brightness and Contrast Adjustment function
    bacAdjustment.Render(new Rectangle[1] {rect},0,1);

    // Now in the main render loop, the dst canvas has an adjusted version of the src canvas
    for (int y = rect.Top; y < rect.Bottom; y++)
    {
        if (IsCancelRequested) return;
        for (int x = rect.Left; x < rect.Right; x++)
        {
            ColorBgra CurrentPixel = dst[x,y];

            CurrentPixel = desaturateOp.Apply(CurrentPixel);
            if (CurrentPixel.R > 128)
            {
                CurrentPixel = Amount2;
            }
            else
            {
                CurrentPixel = Amount3;
            }

            dst[x,y] = CurrentPixel;
        }
    }
}

For a truly complicated, but amazing, color reduction effect, try this plugin: http://forums.getpaint.net/index.php?/topic/29428-z

  • Upvote 1

Click to play:
j.pngs.pngd.pnga.pngp.png
Download: BoltBait's Plugin Pack | CodeLab | and how about a Computer Dominos Game

Link to comment
Share on other sites

Hello!

 

Thank you for your answers!

However, I am not quite happy with these plugins. All of them (including the built-in function) seem to work pixel-wise, i.e. each pixel is rounded to the next color. By this I get artefacts as shown below. To an human it is quite clear that I do not want to have any orange inside the white region on the left, however there are some orange pixels inside...

 

zrqe8c.png  UA3qEu.png

Link to comment
Share on other sites

The color segmentation doesn't work pixel-wise.

 

I think what you want to do is difficult; perhaps nearly impossible do to automatically, since the program can't read your mind. If the small isolated color region is an eye in an image of a face, you'd want to keep it, tiny as it may be.

Link to comment
Share on other sites

Does the machine work only with jpegs? If the machine accepts vectors you may try some software that converts raster images to vectors. Vector Magic for example allows you to pick the number of colours you want to keep. You can save it in SVG format and do further edit with Inkscape.

Link to comment
Share on other sites

However, I am not quite happy with these plugins. All of them (including the built-in function) seem to work pixel-wise, i.e. each pixel is rounded to the next color. By this I get artefacts as shown below. To an human it is quite clear that I do not want to have any orange inside the white region on the left, however there are some orange pixels inside...

 

zrqe8c.png  UA3qEu.png

After the using the built-in effect, try this CodeLab script to eliminate stray pixels...

 

// Name: Stray Pixels
// Submenu: Color
// Author: BoltBait
// Title: Eliminate Stray Pixels
// URL: http://BoltBait.com/pdn
#region UICode
int Amount1 = 1; // [0,4] Size
#endregion

void Render(Surface dst, Surface src, Rectangle rect)
{
    for (int y = rect.Top; y < rect.Bottom; y++)
    {
        for (int x = rect.Left; x < rect.Right; x++)
        {
            ColorBgra CurrentPixel = src[x,y];
            ColorBgra newPixel = src[x,y];
            ColorBgra testPixel = src[x,y];
            int MatchCount = 0;
            for (int TestY = y - 1; TestY < y + 2; TestY++)
            {
                for (int TestX = x - 1; TestX < x + 2; TestX++)
                {
                    if ((TestX >= 0) && (TestX < src.Width) && (TestY >= 0) && (TestY < src.Height))
                    {
                        if ((TestX != x) || (TestY != y))
                        {
                            testPixel = src[TestX,TestY];
                            if (CurrentPixel != testPixel)
                            {
                                newPixel = testPixel;
                            }
                            else
                            {
                                MatchCount = MatchCount+1;
                            }
                        }
                    }
                }
            }
            if (MatchCount < Amount1)
            {
                CurrentPixel = newPixel;
            }
            dst[x,y] = CurrentPixel;
        }
    }
}
It is a bit rough as I wrote it in 5 minutes and haven't really tested it properly.

Click to play:
j.pngs.pngd.pnga.pngp.png
Download: BoltBait's Plugin Pack | CodeLab | and how about a Computer Dominos Game

Link to comment
Share on other sites

slightly off topic:

Thanks BoltBait - may have to play with that code! B)

There is already a plugin with a similar name for removing stray pixels on a transparent background.http://forums.getpaint.net/index.php?showtopic=26533

if you're not set on that name! ;)

 

I think any effect will need some manual 'tampering' to select what is relevant and what is noise? :/

 

Red ochre Plugin pack.............. Diabolical Drawings ................Real Paintings

 

PdnForumSig2.jpg

Link to comment
Share on other sites

Thank you for the replies. I did not manage to test further hints, but (when I have time) I will try to write my own plugin.

There are some Ideas that might heuristically solve the problem

* Increase each selection by, e.g. 1 pixel before coloring

* Removing stray pixel (each area of connected pixel with less than N pixel), color them by their neighbour color

 

Although i never wrote something related to image processing I am quite experienced in C# and coding of GUIs and mathematical algrorithms. It might be worth a try...

Link to comment
Share on other sites

* Removing stray pixel (each area of connected pixel with less than N pixel), color them by their neighbour color

That's what the script I posted above does.

If you want to code your own plugin, here are some tutorials to get you started:

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

Click to play:
j.pngs.pngd.pnga.pngp.png
Download: BoltBait's Plugin Pack | CodeLab | and how about a Computer Dominos Game

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.

 Share

×
×
  • Create New...