Fun Infused Games  |   Smooth Operator

  Home   |    Archive   |    About
Posts prior to 8/2/2010 may be missing data. If you need one of those posts, please contact kriswd40@yahoo.com and I will try and recover/find it.

Fix White Edges on .png Files with a Custom Content Importer
Date 3/28/2010    Tags XNA    (0)

For those of us who use Adobe Photoshop (and some other graphics applications) along with XNA and like to use .png files, you very well have noticed slight white edges/borders around sprites you've imported into your game when they are drawn at less than full pixel amounts. You can see this effect in the image below.



This effect occurs because of how programs like Photoshop save PNG files. On pixels that are completely transparent, the color of those pixels should be the same as the closest non-transparent pixel. Photoshop though saves fully transparent pixels with the color information set to white. When this occurs, the alpha blending on that sprite causes white borders to appear.

Drawing all your images at full pixel amounts will resolve this issue, though that may not be possible for some games (in the case of Abduction Action!, because of the differing zoom levels it was not) and potentially doing this could be noticeable to gamers playing your game (probably not what you want).

Working off a code snippet written by Jason Doucette of Xona Games in this thread on the XNA forums, I transformed what he wrote into a custom Content Importer that you can apply to all textures in your game. The content importer will go through your images during the building of your project and fix the white transparent textures. This is the ideal way to correct this issue since it will cause no performance hit to your game.

Below is the code for this custom Content Importer. It's pretty easy to wire up, I'm sure a quick Google or Bing search can show you the way.
public override TextureContent Import(string filename, ContentImporterContext context)
{
    Bitmap bitmap = Bitmap.FromFile(filename) as Bitmap;
    PixelBitmapContent<Microsoft.Xna.Framework.Graphics.Color> bitmapContent = new PixelBitmapContent<Microsoft.Xna.Framework.Graphics.Color>(bitmap.Width, bitmap.Height);

    for (int x = 0; x < bitmap.Width; x++)
    {
        for (int y = 0; y < bitmap.Height; y++)
        {
            System.Drawing.Color currentPixel = bitmap.GetPixel(x, y);
            Microsoft.Xna.Framework.Graphics.Color updatedPixel = new Microsoft.Xna.Framework.Graphics.Color(currentPixel.R, currentPixel.G, currentPixel.B, currentPixel.A);

            // If alpha = zero, average the colors with the surroundings.
            if (updatedPixel.A == 0)
            {
                float r = 0;
                float g = 0;
                float b = 0;
                int count = 0;

                // go through all 8 pixels around  
                // don't look at current pixel, but we ignore A=0, anyway, which the current pixel IS,  
                // so we can just loop 3x3 around it, including it  
                for (int yy = y - 1; yy <= y + 1; yy++)
                {
                    for (int xx = x - 1; xx <= x + 1; xx++)
                    {
                        // don't go out of range  
                        if ((xx >= 0) && (yy >= 0) && (xx < bitmap.Width) && (yy < bitmap.Height))
                        {
                            // look at only pixels A != 0  
                            int index2 = yy * bitmap.Width + xx;

                            // Need to test the alpha on the surrounding pixel.
                            System.Drawing.Color adjacentPixel = bitmap.GetPixel(xx, yy);
                            byte alpha = adjacentPixel.A;

                            if (alpha != 0)
                            {
                                r += adjacentPixel.R * alpha;
                                g += adjacentPixel.G * alpha;
                                b += adjacentPixel.B * alpha;
                                count++;
                            }
                        }
                    }
                }

                // did we get any non-alpha=0 info?  
                if (count > 0)
                {
                    // modify the A=0 pixel to be this average color  
                    updatedPixel = new Microsoft.Xna.Framework.Graphics.Color(
                        (byte)(r / count / 255.0f),
                        (byte)(g / count / 255.0f),
                        (byte)(b / count / 255.0f),
                        0);
                }

            }

            bitmapContent.SetPixel(x, y, updatedPixel);
        }
    }

    Texture2DContent texture = new Texture2DContent();
    texture.Faces[0] = new MipmapChain { bitmapContent };

    return texture;
}



This article has been view 2480 times.


Comments

No comments for this article.


Add Comments

Name *
Website
  Name the animal in the picture below:

*
Comment *
Insert Cancel
Things To Click


Tags
Video Games (7)  Trivia or Die (3)  SQL (1)  iOS (3)  Game Dev (11)  Advise (14)  PC (1)  World of Chalk (2)  FIN (20)  Abduction Action! (27)  XBLIG (32)  Abduction Action (1)  Nastier (4)  ASP.net (18)  Absurd (2)  Volchaos (11)  Web (19)  Fin (1)  XNA (40)  Rant (50)  Cool (2)  Visual Studio (1)  Trivia Or Die (1)  Xbox (1)  C# (14)  Sports (11)  Design (2)  Development (13)  Hypership (28)  WP7 (8)  VolChaos (1)  Nasty (34)  Abdction Action! (1)