With pngs imported into my Unity project, the standard ‘Texture’ type has a check box with ‘Alpha Is Transparency’. If I check this, my texture has a nice transparent back ground, as opposed to black. All is lovely.
If I don’t have the png imported though, and instead load it with Texture2D.LoadImage.
I only have the black background option.
Is there a way to make the loaded png behave the same as if it were imported.
Thanks
The images below show the main character with the Texture2D.LoadImage, vs the png imported in Unity with ‘Alpha is Transparency’ set. It’s very minor differences, but i’m keen not to have the slight seam around the top of the leg, as well as the seam where the arm connects to the body, and the small seam at the top of the chin.
Hi. The ‘Alpha Is Transparency’ is applied via editor only code so it is not available to Texture2D.LoadImage.
The code applies an alpha dilation filter, so its something you could do yourself.
Take a look at this and see if it helps first Unity - Manual: Applying Edge Padding to Alpha Textures
Sadly I don’t think Edge Padding is something that will help. Unless i’m mistaken, pngs don’t have an Alpha channel (just alpha transparency), so I can’t dilate the image and then use the alpha channel. To show only the bits of the png I want?
Not sure if it will help but below is how my player is rendered on quads/triangles, along with the sprite sheet used.
Hmm. PNGs can contain RGBA, that’s 4 channels one of which is alpha so it should be fine. Best thing to do is try the photoshop advice, save it as a PNG and see how it looks.
I am fairly certain this will solve your problem
Hi! Bumping this. I have way too many PNG files to do the Photoshop trick manually for each one (> 1000 files), and I’m in the editor, so I have access to any code I want.
Is there a way to apply the alpha dilation filter programmatically @karl_jones ?
Hmm. I don’t think we expose it any other way. You could save the texture as an asset, import it, grab the converted version and then delete the asset. That can all be done through script.
Well, thanks a lot! This worked for me. My usecase was: I wanted user to add a texture (amazon logo ‘a’ for isntance) through selecting the PNG file. The problem was, the logo was getting a cyan tint or sometimes red instead of black color if I set alpha channel traversing through all pixels.
Hi, sorry for bumping this, I’m trying to do something similar, taking a screenshot and saving it, and the screenshot I want to take is for a single character, in other words I need everything else to be transparent, here’s the code:
int width = Screen.width;
int height = Screen.height;
Texture2D screenshotTexture = new Texture2D(width,
height, TextureFormat.RGBA32, false);
Rect rect = new Rect(0, 0, width, height);
screenshotTexture.ReadPixels(rect, 0, 0);
screenshotTexture.Apply();
byte[] byteArray = screenshotTexture.EncodeToPNG();
System.IO.File.WriteAllBytes(_path, byteArray);
It does take screenshot but not with transparency even if the texture format is RGBA32, so I’m guessing it has something to do with Texture2D.alphaIsTransparency, since the result replaces alpha with black color, am I missing something?
I’ve found this to work for a little bit. But then when the texture is set to bilinear filtering mode it breaks!
I spent a while researching this and learned the AlphaIsTransprency basically makes sure that no pixel is without color, even if the alpha is 0.
The problem is bilinear will use pixels around it to make a new pixel. So new Color() always has black. and when you multiply black with a brighter pixel, lets say white, it will become gray. Now you are back to having the same weird fringe outlining around your bright pixels but not your black pixels.
So I came up with an idea to propagate the color of non 0 alphas onto 0 alphas. Note: This probably has issues and need improvement but I guess it works for me.
public static void AlphaIsTransparency(this Texture2D texture)
{
PropagateColors(texture);
texture.Apply();
void PropagateColors(Texture2D texture)
{
int maxTransparentCount = 4;
Color[] pixels = texture.GetPixels();
int width = texture.width;
int height = texture.height;
Color currentColor = Color.clear;
int transparentCount = 0;
int index = 0;
void CheckAndSet()
{
if (pixels[index].a > 0) // If current pixel has alpha > 0
{
currentColor = pixels[index]; // Track current color
currentColor.a = 0; // Set alpha to 0
transparentCount = 0; // Reset the transparent counter
}
else // If current pixel is transparent
{
if (transparentCount < maxTransparentCount)
{
pixels[index] = currentColor; // Apply current color
transparentCount++; // Increment the transparent counter
}
else
{
currentColor = Color.clear; //if it passes max count lets just clear it and reset
transparentCount = 0;
}
}
}
// Top to Bottom
for (int x = 0; x < width; x++)
{
// Counter for consecutive transparent pixels
currentColor = Color.clear;
transparentCount = 0;
for (int y = 0; y < height; y++)
{
index = y * width + x;
CheckAndSet();
}
}
// Bottom to Top
for (int x = 0; x < width; x++)
{
currentColor = Color.clear;
transparentCount = 0;
for (int y = height - 1; y >= 0; y--)
{
index = y * width + x;
CheckAndSet();
}
}
// Left to Right
for (int y = 0; y < height; y++)
{
currentColor = Color.clear;
transparentCount = 0;
for (int x = 0; x < width; x++)
{
index = y * width + x;
CheckAndSet();
}
}
// Right to Left
for (int y = 0; y < height; y++)
{
currentColor = Color.clear;
transparentCount = 0;
for (int x = width - 1; x >= 0; x--)
{
index = y * width + x;
CheckAndSet();
}
}
// Apply modified pixels back to the texture
texture.SetPixels(pixels);
}
}