CodePaste Logo
New Snippet New Snippet Recent Snippets Recent Snippets My Snippets My Snippets My Favorites Favorites Web Code Search Snippets Search
Sign inor Register
Language: C#

Extension method to use PMA with textures loaded from filesystem

507 Views   
    public static class ExtensionMethods
    {
        public static Texture2D PreMultiplyAlpha(this Texture2D tex)
        {
            Color[] data = new Color[tex.Width * tex.Height];
            tex.GetData<Color>(data);
 
            for (int i = 0; i < data.Length; i++)
            {
                Color c = data[i];
                data[i] = new Color(c.R, c.G, c.B) * (c.A / 255f);
            }
 
            tex.SetData<Color>(data);
            return tex;
        }
    }
 
-----
 
        public Texture2D LoadTexture(GraphicsDevice graphicsDevice, string file)
        {
            return Texture2D.FromStream(graphicsDevice, 
                new FileStream(file, FileMode.Open)).PreMultiplyAlpha();
        }
by Ben Eirich
  May 08, 2010 @ 6:21pm
Description:
If you want to use pre-multiplied alpha in XNA 4.0 but don't want to load your textures from the Content pipeline, this provides an extension method to convert your textures to PMA-format at load-time.

by Bob Burnside    January 06, 2011 @ 2:02pm

Thanks!

This worked great for me. Actually, since I had to generate my own mipmaps from a dynamic content pipeline for PNGs, via a TextureImporter -> TextureContent -> MipmapChainCollection step, I had to pass in the rect, level, and count into PreMultiplyAlpha and call it once per level. This fixed my problem with only the top level mipmap having premultiplier alpha whereas I needed each level to have this step.

Works great though. Cheers!

public static Texture2D PreMultiplyAlpha(this Texture2D tex, int level, Microsoft.Xna.Framework.Rectangle? rect, int count)
{
Microsoft.Xna.Framework.Color[] data = new Microsoft.Xna.Framework.Color[tex.Width * tex.Height];

tex.GetData<Microsoft.Xna.Framework.Color>(level, rect, data, 0, count);

for (int i = 0; i < data.Length; i++)
{
Microsoft.Xna.Framework.Color c = data[i];
data[i] = new Microsoft.Xna.Framework.Color(c.R, c.G, c.B) * (c.A / 255f);
}

tex.SetData<Microsoft.Xna.Framework.Color>(level, rect, data, 0, count);
return tex;
}

Calling function :

public Texture2D LoadAlphaTexture(string path, GraphicsDevice graphicsDevice)
{
TextureContent content = importer.Import(path, null);
content.GenerateMipmaps(true);

MipmapChainCollection chainCol = content.Faces;
MipmapChain chain = chainCol[0];

int level = 0;
Texture2D tex = null;

try
{
foreach (BitmapContent pixels in chain)
{
if (tex == null)
tex = new Texture2D(graphicsDevice, pixels.Width, pixels.Height, true, SurfaceFormat.Color);

//copy mipmapped pixels
Microsoft.Xna.Framework.Rectangle? rect = new Microsoft.Xna.Framework.Rectangle(0, 0, pixels.Width, pixels.Height);

byte[] data = PremultiplyAlpha(pixels.GetPixelData());
int count = pixels.Height * pixels.Width;
tex.SetData<byte>(level, rect, pixels.GetPixelData(), 0, count * 4);
tex.PreMultiplyAlpha(level, rect, count);
level++;
}
}
catch (Exception e)
{
return null;
}

return tex;
}


Works great though. Cheers!

Add a comment


Report Abuse
brought to you by:
West Wind Techologies