Jump to content

Infer transparency plugin


aphillips

Recommended Posts

I have some icons with antialiased/dithered edges that have been rendered on a white background. I don't have the original icons with the alpha channel. I need transparent edges so I can render onto a different background.

Is there a filter around that I can use that will try to work out transparency from the colours? If not I might try to write one.

I guess it would:

1. Work out the pure background areas and convert them to fully transparent. This could be done by the user choosing the background colour (default to colour of top-left pixel?).

2. For pixels next to background areas look at the adjoining (non-background area pixels) and try to work out what colour and alpha value the pixel is likely to have had to generate its actual RGB value.

I have been doing this by hand (with reasonable results). What I have been doing *seems* mechanical enough that it could be automated. I know the results would not be perfect but they would be good enough for my needs.

Link to comment
Share on other sites

Hi barkbark00. Thanks for the pointer to the "Color to Alpha Advanced" plugin. It is quite a bit simpler than the plugin I was thinking of (but it has saved me some time).

First it changes the alpha of almost every pixel of my icons, especially if they have muted colors. I only want to make the background fully transparent and make edges of any shapes detected partially transparent. Using the magic wand to select the area to work on avoids this problem most of the time.

Second it never changes the color (RGB) value only the alpha channel. My plugin will adjust each pixel based on the background color and also the color of adjacent pixels. So if the background is blue and an icon is mainly red then the purple edge pixels get made into a transparent red. In my case the existing backgrounds are white and the new backgrounds are mainly light gray (except where the image is placed on top of another one) so there are only a few small areas that need to be fixed up.

So I can use the "Color to Alpha Advanced" plugin to save me perhaps 90% of my work, but it is not exactly what I wanted.

I think I will still create my plugin. I think it will give much better results by only changing the transparency (and color) of pixels on the borders of shapes. It would need an option to say how far to go into shapes (default probably about 1.4 pixels), plus checkbox for looking for "holes".

Rick, Could you move this back to the plugin development forum? Thanks!

Link to comment
Share on other sites

Here is the start of a CodeLab script:

#region UICode
byte Amount1 = 0; // [1]  Color to delete|White|Black
double Amount2 = 0.5; // [0,1] Tolerance
#endregion

void Render(Surface dst, Surface src, Rectangle rect)
{
   double H=0;
   double S=0;
   double V=0;
   byte R=0;
   byte G=0;
   byte B=0;
   ColorBgra CurrentPixel;
   for (int y = rect.Top; y     {
       for (int x = rect.Left; x         {
           CurrentPixel = src[x,y];
           EvanRGBtoHSV(CurrentPixel.R, CurrentPixel.G, CurrentPixel.B, ref H, ref S, ref V);
           switch (Amount1)
           {
               case 0:    // White
                   if (V >= Amount2)
                   {
                       EvanHSVtoRGB(H, 1.0, V, ref CurrentPixel.R, ref CurrentPixel.G, ref CurrentPixel.;
                       CurrentPixel.A = (byte)(255*S);
                   }
                   break;
               case 1:    // Black
                   if (V                     {
                       EvanHSVtoRGB(H, S, 1.0, ref CurrentPixel.R, ref CurrentPixel.G, ref CurrentPixel.;
                       CurrentPixel.A = (byte)(255*V);
                   }
                   break;
               default:
                   break;
           }
           dst[x,y] = CurrentPixel;
       }
   }
}



public void EvanHSVtoRGB(double H, double S, double V, ref byte bR, ref byte bG, ref byte bB)
{
   const double HSV_UNDEFINED = -999.0;
   // Parameters must satisfy the following ranges:
   // 0.0     // 0.0     // 0.0 
   // Handle special case first
   if (S == 0.0 || H == HSV_UNDEFINED)
   {
       byte x = (byte)(int)(V * 255.0);
       bR = x;
       bG = x;
       bB = x;
       return;
   }

   if (H >= 360.0)
   {
       H = AngleConstrain(H);
   }

   double R = V, G = V, B = V;
   double Hi = Math.Floor(H / 60.0);
   double f = H / 60.0 - Hi;
   double p = V * (1.0 - S);
   double q = V * (1.0 - f * S);
   double t = V * (1.0 - (1.0 - f) * S);
   if (Hi == 0.0)
   {
       R = V;
       G = t;
       B = p;
   }
   else if (Hi == 1.0)
   {
       R = q;
       G = V;
       B = p;
   }
   else if (Hi == 2.0)
   {
       R = p;
       G = V;
       B = t;
   }
   else if (Hi == 3.0)
   {
       R = p;
       G = q;
       B = V;
   }
   else if (Hi == 4.0)
   {
       R = t;
       G = p;
       B = V;
   }
   else if (Hi == 5.0)
   {
       R = V;
       G = p;
       B = q;
   }

   int iR = (int)(R * 255.0);
   int iG = (int)(G * 255.0);
   int iB = (int)(B * 255.0);
   bR = (byte)iR;
   bG = (byte)iG;
   bB = (byte)iB;
}

public void EvanRGBtoHSV(int R, int G, int B, ref double outH, ref double outS, ref double outV)
{
   const double HSV_UNDEFINED = -999.0;
   // R, G, and B must range from 0 to 255
   // Ouput value ranges:
   // outH - 0.0 to 360.0
   // outS - 0.0 to 1.0
   // outV - 0.0 to 1.0

   double dR = (double)R / 255.0;
   double dG = (double)G / 255.0;
   double dB = (double)B / 255.0;
   double dmaxRGB = EvanMax3(dR, dG, dB);
   double dminRGB = EvanMin3(dR, dG, dB);
   double delta = dmaxRGB - dminRGB;

   // Set value
   outV = dmaxRGB;

   // Handle special case
   if (dmaxRGB == 0)
   {
       outH = HSV_UNDEFINED;
       outS = 0.0;
       return;
   }

   outS = delta / dmaxRGB;
   if (dmaxRGB == dminRGB)
   {
       outH = HSV_UNDEFINED;
       return;
   }

   // Finally, compute hue
   if (dR == dmaxRGB)
   {
       outH = (dG - dB) / delta * 60.0;
   }
   else if (dG == dmaxRGB)
   {
       outH = (2.0 + (dB - dR) / delta) * 60.0;
   }
   else //if (dB == dmaxRGB)
   {
       outH = (4.0 + (dR - dG) / delta) * 60.0;
   }

   if (outH     {
       outH += 360.0;
   }
}

public double EvanMax3(double x, double y, double z)
{
   return (x > y) ? ((x > z) ? x : z) : ((y > z) ? y : z);
}

public double EvanMin3(double x, double y, double z)
{
   return (x }

public double AngleConstrain(double MyAngle)
{
   // Makes sure that 0.0     // Wraps around the value if its outside this range
   if (MyAngle >= 360.0)
   {
       MyAngle -= Math.Floor(MyAngle / 360.0) * 360.0;
   }
   if (MyAngle     {
       MyAngle += 360.0;
   }
   return MyAngle;
}

This CodeLab script obviously needs a lot of tweeking and I'll refine it more later when I have more time. Is this getting close to what you want?

Link to comment
Share on other sites

This CodeLab script obviously needs a lot of tweeking and I'll refine it more later when I have more time.

Here's one tweek to save some time. Consider what would happen if the angle were -1000 using the original code:

public void EvanHSVtoRGB(double H, double S, double V, ref byte bR, ref byte bG, ref byte bB)
{
   ...

   //if (H >= 360.0)
   //{
       H = AngleConstrain(H);
   //}

   ...
}

public double AngleConstrain(double MyAngle)
{
   // Makes sure that 0.0 <= MyAngle < 360.0
   // Wraps around the value if its outside this range
   MyAngle %= 360.0;
   if (MyAngle < 0.0)
   {
       MyAngle += 360.0;
   }
   return MyAngle;
}

Link to comment
Share on other sites

I have been using the "Color To Advanced Plugin" for a while and it is not as useful as I first thought. Comparing some images I fixed manually with its results reveals the problem:

Since I have a white background the RGB values are lighter than they should be which when combined with the transparency which makes the edges almost disappear. I usually try to compensate for this by increasing the "Alpha Amount" using the slider (making the pixel less transparent) but there appears to be a bug that causes the alpha value to overflow 8 bits and wrap back to zero. In any case the edges end up too white when overlaid on a dark background.

Another problem is that the plugin keeps crashing.

So I have gone back to my manual method (until I write my plugin). FYI my manual method is fairly simple:

1. Create a layer behind and fill it with the background color (usually white in my case).

2. Find an edge pixel (A) to adjust and an adjacent pixel (B) that probably originally had no transparency

3. Use the color picker to get the RGBA value of (B) above.

4. Reduce the alpha of the color just picked to try to match what was probably the transparency of (A).

5. Use the pencil tool to set pixel (A). As the alpha value is < 255 the background layer should show through a bit.

6. If the pixel color does not change too much then the alpha value OK and I move on to the next pixel.

7. Otherwise I undo the change and go back to step 4.

A plugin to do something similar should be fairly simple. The main problem will be detecting edges I think. My strategy would be that everything of the chosen background would be made fully transparent. Any adjacent pixels that are not exactly the same RGB value are considered an edge.

I am not sure whether to make the "width" of an edge user definable (in pixels) or try to determine the width by looking at how much the RGB values vary from the background. My inclination is the first as the image may be a similar color to the background and it allows the user to control the behavior.

Link to comment
Share on other sites

Hi BoltBait,

I just tried your CodeLab script. It works very nicely adjusting the color (not just the alpha as was my problem with the Color To Alpha plugin). Thanks very much.

I still have to select the area first since it tends to affect a lot of pixels inside shapes which I don't want changed. I usually try the magic wand, but it does not usually give good results (when I increase the tolerance to get enough of the borders to be transparent it tends to "leak" into the shapes first), so I have to manually adjust the selection.

Also your script works brilliantly for a white background (which is what I have most of the time) but how do I change it to work for other colours, eg a gray (192,192,192) background?

Link to comment
Share on other sites

Hi BoltBait,

I just tried your CodeLab script. It works very nicely adjusting the color (not just the alpha as was my problem with the Color To Alpha plugin). Thanks very much.

You're welcome. It was just a quick idea. I'm glad it works for you.

I still have to select the area first since it tends to affect a lot of pixels inside shapes which I don't want changed. I usually try the magic wand, but it does not usually give good results (when I increase the tolerance to get enough of the borders to be transparent it tends to "leak" into the shapes first), so I have to manually adjust the selection.

Yeah, I still need to play with the Tolerance algorithm. I just threw it in there quickly. That's why I said that I still need to tweek it.

Also your script works brilliantly for a white background (which is what I have most of the time) but how do I change it to work for other colours, eg a gray (192,192,192) background?

Sorry, I have not come up with a good algorithm for that scenario. My idea only works for the color white and the color black. I could also do it for red, green, or blue, if you like... but, that's about it right now.

Link to comment
Share on other sites

Wrong forum section. You're asking for a plugin, not for help in the development of your plugin.

Moved to General Discussion

I think it's become that. Should this be moved back?

 

The Doctor: There was a goblin, or a trickster, or a warrior... A nameless, terrible thing, soaked in the blood of a billion galaxies. The most feared being in all the cosmos. And nothing could stop it, or hold it, or reason with it. One day it would just drop out of the sky and tear down your world.
Amy: But how did it end up in there?
The Doctor: You know fairy tales. A good wizard tricked it.
River Song: I hate good wizards in fairy tales; they always turn out to be him.

Link to comment
Share on other sites

Hi Boltbait,

I spoke too soon (as usual). For colored icons (and a white background) your CodeLab script is great but for ones with gray borders it makes the border almost completely transparent. Not what I wanted. (Some icons seem to have the bottom/right side more gray as a shadow, and some icons seems to have a gray line drawn all the way around them.)

I can see why that happens from your code. I am still thinking how to create a plugin to do what I want. (I have written some of this sort of thing before in C++.)

Link to comment
Share on other sites

Wrong forum section. You're asking for a plugin, not for help in the development of your plugin.

Moved to General Discussion

I think it's become that. Should this be moved back?

Yup, I was thinking that too.

Put back

The Paint.NET Blog: https://blog.getpaint.net/

Donations are always appreciated! https://www.getpaint.net/donate.html

forumSig_bmwE60.jpg

Link to comment
Share on other sites

  • 3 weeks later...

> Zip the .dll file up and add it as an attachment in a thread in the plugin section (or plugin developers' central if it's a beta.)

Thanks. I initially did not see the "Upload attachment" pane (off the bottom of the screen), but I saw it and posted it in this forum in a new (Clear Background) thread.

I forgot to zip it first though. I will do that and re-submit. If you are the moderator ignore the 2 earlier posts with the unzipped file. (I assume that posts with attachments have to be approved by the moderator.)

Link to comment
Share on other sites

I forgot to zip it first though. I will do that and re-submit. If you are the moderator ignore the 2 earlier posts with the unzipped file. (I assume that posts with attachments have to be approved by the moderator.)

Attachments don't have to be approved by mods, but the forum rejects any attachments that don't have one of the predefined extensions - I know that ZIP is one.

KaHuc.png
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...