Sign in to follow this  
Lanceo90

Anyway to Replace One Set of Pixels with Another Set Throughout an Image?

Recommended Posts

Greetings everyone,

That question might not make sense at first glance so here's the more elaborate question:

I have a map file made from a tile set that I want to simplify the tiles down to just a single color.  There's a lot of them, and it's a big image.  I started by just copy pasting but it's going to take way too long.  So I was curious if Paint.net has a built in method to replace sets of pixels with another, or if there is a plugin than can do it.

Here's a visual representation of what I mean using a small piece of the map:
KzR3JFj.png

Share this post


Link to post
Share on other sites

I know of no way to do this, and doubt there currently is one in PDN. I think it would be difficult to write a plugin. It would have to use a 2D equivalent of string matching. Depending on the use, it might have to find near matches, since sampling can modify a pattern when it's resized or translated. I found some reference to 2D pattern matching, such as Fast Two Dimensional Pattern Matching.

Share this post


Link to post
Share on other sites

I'm working on it. I should have a solution for you in a few days or less.

 

Edit: Well, that was faster than expected. I've attached the .dll file. You'll need to drop it in the Effects folder under Paint.net. (An easy way to get there is to right-click paint.net, click "open file location" and do that again on the shortcut. You should see the Effects folder at the top, then.)

 

It was fun :)

PixSetRepl.zip

 

----------------------------

Instructions:

 

Select the tile you want to change. Click the button to store it as the "image to be replaced". Select (or draw) the tile you want to replace it with. Store that as the second image. Go to it again and click "replace". You can also use "reset" to use it on multiple tiles. It might be slow on a large image.

Edited by AnthonyScoffler
  • Upvote 3

Share this post


Link to post
Share on other sites
On 1/4/2017 at 4:07 PM, AnthonyScoffler said:

I'm working on it. I should have a solution for you in a few days or less.

 

Edit: Well, that was faster than expected. I've attached the .dll file. You'll need to drop it in the Effects folder under Paint.net. (An easy way to get there is to right-click paint.net, click "open file location" and do that again on the shortcut. You should see the Effects folder at the top, then.)

 

It was fun :)

PixSetRepl.zip

 

----------------------------

Instructions:

 

Select the tile you want to change. Click the button to store it as the "image to be replaced". Select (or draw) the tile you want to replace it with. Store that as the second image. Go to it again and click "replace". You can also use "reset" to use it on multiple tiles. It might be slow on a large image.

Wow, thanks!  That worked

Share this post


Link to post
Share on other sites

I'm glad it was useful. I took up the work to do that because I had some free time and, after thinking about it, it's sort of a basic utility. I hope the interface isn't too laborious -- I know it's not pretty. :)

Share this post


Link to post
Share on other sites

@MJW Here's the main part of the code.

//Iterates through each pixel.
for (int y = 0; y <= src.Height - token.BmpToReplace.Height; y++)
{
  for (int x = 0; x <= src.Width - token.BmpToReplace.Width; x++)
  {
    //Skips all pixels that have been replaced.
    if (replacedPixels.Count > 0 &&
        replacedPixels[0].X == x &&
        replacedPixels[0].Y == y)
    {
      replacedPixels.RemoveAt(0);
      continue;
    }

    //Checks if the first pixel matches.
    if (ColorBgra.FromColor(token.BmpToReplace.GetPixel(0, 0)).Equals(src[x, y]))
    {
      bool totalMatch = true;

      //Checks if every pixel matches.
      for (int yy = 0; yy < token.BmpToReplace.Height; yy++)
      {
        for (int xx = 0; xx < token.BmpToReplace.Width; xx++)
        {
          if (!ColorBgra.FromColor(token.BmpToReplace.GetPixel(xx, yy)).Equals(src[x + xx, y + yy]))
          {
            totalMatch = false;
            break;
          }
        }
        if (!totalMatch)
        {
          break;
        }
      }

      //Replaces the matching pixels. They will be skipped.
      if (totalMatch)
      {
        for (int yy = 0; yy < token.BmpReplacing.Height; yy++)
        {
          for (int xx = 0; xx < token.BmpReplacing.Width; xx++)
          {
            dst[x + xx, y + yy] = ColorBgra.FromColor(token.BmpReplacing.GetPixel(xx, yy));

            //All pixels except the first should be skipped.
            //The first has been checked already.
            if (xx != 0 && yy != 0)
            {
              replacedPixels.Add(new Point(x + xx, y + yy));
            }
          }
        }
        replacedPixels.OrderBy(p => p.X).ThenBy(p => p.Y);
      }
    }
  }
}
  • Upvote 1

Share this post


Link to post
Share on other sites

Thanks for this tool  @AnthonyScoffler,

 

I thought I would test it by replacing some characters I typed (the characters that followed the word THANKYOU!) with the word :) BRAVO! :)

 

To my surprise the effect found only two instances of the characters I wanted to replace. Upon closer inspection I found that the characters that were not replaced were not exactly identical everywhere.  

 

Could a tolerance option be added to the effect? 

 

pixelreplacer-514f1db.png

Share this post


Link to post
Share on other sites
5 hours ago, Eli said:

Could a tolerance option be added to the effect? 

I've added it in now. I'm still working feverishly on Brush Factory, but eventually I will come back to it later and add things like a preview, which is why I didn't have tolerance the first time around.

Pixel Set Replacer

 

P.S: I was able to replace those letters using a tolerance of 220.

Edited by AnthonyScoffler
Source code included in download
  • Upvote 3

Share this post


Link to post
Share on other sites

I just released my new Tileworld plugin: http://forums.getpaint.net/index.php?/topic/110911-tileworld/

 

With it you can replace tiles as our original poster requested. Demo....

 

Retilingdemo.png

 

It took a little jigging to get the 16x16 tile size matched to the map. After that was accomplished it was simplicity itself to click on each of the tiles to replace it.

 

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.

Sign in to follow this