• Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by useless.unity.user · Apr 12, 2012 at 07:07 AM · transparencypng

PNG transparency has white border/halo

Occasionally I notice a white border along the edge of some (not all) of my transparent PNG images, this happens regardless of whether its PNG or PNG32. I know how to resolve it for PSD or TGA graphics, but is there a solution for PNG?

Thanks!

Comment
Add comment · Show 3
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Lttldude · Apr 12, 2012 at 08:11 AM 0
Share

I'm not sure if you've tried using Unity's AlphaUtility for Photoshop yet. It dialates the image so when you Unity uses the alpha channel there is no white border.

http://unity3d.com/support/documentation/$$anonymous$$anual/HOWTO-alphamaps.html

Hope it helps.

avatar image useless.unity.user · Apr 12, 2012 at 10:22 AM 0
Share

yeah I tried "dilating" it, which is actually the same as using the Solidify filter or painting in a color myself.

That fix seems to only work in regard to PSD and TGA images.

PNG appears to be a whole other "beast" ;-) thanks for your comment.

avatar image Kleptomaniac · Apr 12, 2012 at 12:32 PM 0
Share

Yes, that's always happened for me ... I have always used this thread to generate pretty much perfect borderless textures ... but unfortunately it only ever imports correctly with .psd's ... .png's always end up having the background layer exposed ...

So I don't know if there actually is a way to effectively use the alpha channel to get rid of the white borders in .png's anyway ...

3 Replies

· Add your reply
  • Sort: 
avatar image
0
Best Answer

Answer by useless.unity.user · Apr 13, 2012 at 02:54 AM

thanks for the confirmation!

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image
1

Answer by petrucio · Apr 17, 2015 at 01:18 PM

You can fix your imported png textures by code. In my case, I let the players themselves import png files into the game, so no ammount of Solidify, using TGA, or other proposed fixes are any good.

This is the definitive solution if you are still having this problem and other solutions don't help you.

(I'm adding an answer to this post, since the other related posts are closed. Hopefully it might help people with this problem comming here from google)

 //=========================================================================
 // Copy the values of adjacent pixels to transparent pixels color info, to
 // remove the white border artifact when importing transparent .PNGs.
 public static void FixTransparency(this Texture2D texture)
 {
     Color32[] pixels = texture.GetPixels32();
     int w = texture.width;
     int h = texture.height;
     
     for     (int y = 0; y < h; y++) {
         for (int x = 0; x < w; x++) {
             int idx    = y * w + x;
             Color32 pixel = pixels[idx];
             if (pixel.a == 0) {
                 bool done = false;
                 if (!done && x > 0)   done = TryAdjacent(ref pixel, pixels[idx - 1]);        // Left   pixel
                 if (!done && x < w-1) done = TryAdjacent(ref pixel, pixels[idx + 1]);        // Right  pixel
                 if (!done && y > 0)   done = TryAdjacent(ref pixel, pixels[idx - w]);        // Top    pixel
                 if (!done && y < h-1) done = TryAdjacent(ref pixel, pixels[idx + w]);        // Bottom pixel
                 pixels[idx] = pixel;
             }
         }
     }
     
     texture.SetPixels32(pixels);
     texture.Apply();
 }
 
 //=========================================================================
 private static bool TryAdjacent(ref Color32 pixel, Color32 adjacent)
 {
     if (adjacent.a == 0) return false;
     
     pixel.r = adjacent.r;
     pixel.g = adjacent.g;
     pixel.b = adjacent.b;
     return true;
 }

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image YBDDevelopment · Aug 08, 2015 at 05:00 PM 0
Share

is ther any way to fix this not by code?

avatar image
0

Answer by stomachcontents · Apr 20, 2017 at 10:25 PM

Dunno if this is still relevant in 2017. I certainly couldn't find a tool to do this so I made one. I don't like petrucio's solution because:

1] It has to be run each time you load a texture(?). I don't use Unity but I'm assuming from his code that's what it does. The solution should fix the PNG itself so there is zero overhead when loading the PNG as a texture. People are coming here as a general solution to this fringe artifact problem, so that code won't help them either.

2] It doesn't consider all pixels around the target pixel. There are 8 not 4. I believe there should be some more intelligent averaging algorithm used to determine the correct color. My solution provides that.

3] It removes unneeded headers which can take up a few K some PNGs I've seen. Even smaller PNGs! yay! That may or may not be a problem for you.

You'll need to compile it yourself under Linux. It expects libpng-dev, etc to be installed. Porting to Windows is left up to the reader.

Hope this helps somebody.

Comments, suggestions welcome.

Compile with: gcc fix_png.c -o fix_png -lpng

 /* fix_png.c - A tool to fix transparent pixel color in PNGs so they
                can be scaled/rotated/whatevs without fringe artifacts.
                
                by Christian Ruocco on 19 April 2017.
                Used original PNG loading/saving example code by 
                Guillaume Cottenceau then implemented my own filtering 
                algorithm in that. This code is released under the same 
                licence as his. See original copyright/licence terms 
                below. 
                
                This code is not remotely optimized, but it doesn't
                matter since it writes out a new PNG so it only needs
                to be run once per PNG you want fixed. It also removes
                unneeded headers inserted by art programs which I've 
                seen used a buttload of space on some images so your
                final PNG should a few K smaller. */
                
                
 /*
  * Copyright 2002-2010 Guillaume Cottenceau.
  *
  * This software may be freely redistributed under the terms
  * of the X11 license.
  *
  */
 
 #include <unistd.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdarg.h>
 
 #define PNG_DEBUG 3
 #include <png.h>
 
 void abort_(const char * s, ...)
 {
         va_list args;
         va_start(args, s);
         vfprintf(stderr, s, args);
         fprintf(stderr, "\n");
         va_end(args);
         abort();
 }
 
 int x, y;
 
 int width, height;
 png_byte color_type;
 png_byte bit_depth;
 
 png_structp png_ptr;
 png_infop info_ptr;
 int number_of_passes;
 png_bytep * row_pointers;
 
 void read_png_file(char* file_name)
 {
         char header[8];    // 8 is the maximum size that can be checked
 
         /* open file and test for it being a png */
         FILE *fp = fopen(file_name, "rb");
         if (!fp)
                 abort_("[read_png_file] File %s could not be opened for reading", file_name);
         fread(header, 1, 8, fp);
         if (png_sig_cmp(header, 0, 8))
                 abort_("[read_png_file] File %s is not recognized as a PNG file", file_name);
 
 
         /* initialize stuff */
         png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
 
         if (!png_ptr)
                 abort_("[read_png_file] png_create_read_struct failed");
 
         info_ptr = png_create_info_struct(png_ptr);
         if (!info_ptr)
                 abort_("[read_png_file] png_create_info_struct failed");
 
         if (setjmp(png_jmpbuf(png_ptr)))
                 abort_("[read_png_file] Error during init_io");
 
         png_init_io(png_ptr, fp);
         png_set_sig_bytes(png_ptr, 8);
 
         png_read_info(png_ptr, info_ptr);
 
         width = png_get_image_width(png_ptr, info_ptr);
         height = png_get_image_height(png_ptr, info_ptr);
         color_type = png_get_color_type(png_ptr, info_ptr);
         bit_depth = png_get_bit_depth(png_ptr, info_ptr);
 
         number_of_passes = png_set_interlace_handling(png_ptr);
         png_read_update_info(png_ptr, info_ptr);
 
 
         /* read file */
         if (setjmp(png_jmpbuf(png_ptr)))
                 abort_("[read_png_file] Error during read_image");
 
         row_pointers = (png_bytep*) malloc(sizeof(png_bytep) * height);
         for (y=0; y<height; y++)
                 row_pointers[y] = (png_byte*) malloc(png_get_rowbytes(png_ptr,info_ptr));
 
         png_read_image(png_ptr, row_pointers);
 
         fclose(fp);
 }
 
 
 void write_png_file(char* file_name)
 {
         /* create file */
         FILE *fp = fopen(file_name, "wb");
         if (!fp)
                 abort_("[write_png_file] File %s could not be opened for writing", file_name);
 
 
         /* initialize stuff */
         png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
 
         if (!png_ptr)
                 abort_("[write_png_file] png_create_write_struct failed");
 
         info_ptr = png_create_info_struct(png_ptr);
         if (!info_ptr)
                 abort_("[write_png_file] png_create_info_struct failed");
 
         if (setjmp(png_jmpbuf(png_ptr)))
                 abort_("[write_png_file] Error during init_io");
 
         png_init_io(png_ptr, fp);
 
 
         /* write header */
         if (setjmp(png_jmpbuf(png_ptr)))
                 abort_("[write_png_file] Error during writing header");
 
         png_set_IHDR(png_ptr, info_ptr, width, height,
                      bit_depth, color_type, PNG_INTERLACE_NONE,
                      PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
 
         png_write_info(png_ptr, info_ptr);
 
 
         /* write bytes */
         if (setjmp(png_jmpbuf(png_ptr)))
                 abort_("[write_png_file] Error during writing bytes");
 
         png_write_image(png_ptr, row_pointers);
 
 
         /* end write */
         if (setjmp(png_jmpbuf(png_ptr)))
                 abort_("[write_png_file] Error during end of write");
 
         png_write_end(png_ptr, NULL);
 
         /* cleanup heap allocation */
         for (y=0; y<height; y++)
                 free(row_pointers[y]);
         free(row_pointers);
 
         fclose(fp);
 }
 
 
 unsigned int get_pixel(int x, int y)
 {
         if (y < 0 || y >= height ||
             x < 0 || x >= width)
             return 0;
         
         png_byte *pixel = row_pointers[y] + x * 4;
         
         return (pixel[0] << 0) | (pixel[1] << 8) | (pixel[2] << 16) | (pixel[3]<<24);
 }
 
 void set_pixel(int x, int y, unsigned int color)
 {
         if (y < 0 || y >= height ||
             x < 0 || x >= width)
             return;
         
         png_byte *pixel = row_pointers[y] + x * 4;
         
         pixel[0] = color >> 0;
         pixel[1] = color >> 8;
         pixel[2] = color >> 16;
         pixel[3] = color >> 24;
 }
 
 void process_file(void)
 {
         if (png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_RGB)
                 abort_("[process_file] input file is PNG_COLOR_TYPE_RGB but must be PNG_COLOR_TYPE_RGBA "
                        "(lacks the alpha channel)");
 
         if (png_get_color_type(png_ptr, info_ptr) != PNG_COLOR_TYPE_RGBA)
                 abort_("[process_file] color_type of input file must be PNG_COLOR_TYPE_RGBA (%d) (is %d)",
                        PNG_COLOR_TYPE_RGBA, png_get_color_type(png_ptr, info_ptr));
 
 
         
         for (y=0; y<height; y++) 
         {
                 for (x=0; x<width; x++) 
                 {
                         int red = 0;
                         int green = 0;
                         int blue = 0;
                         int alpha = 0;
                         
                         unsigned color;
                         png_byte *cc = (png_byte*)&color;
                         
                         color = get_pixel(x, y);
                         
                         /* We consider any alpha value <=16 to
                            be zero for "noisy" images. */
                         if (cc[3] > 16)
                                 continue;
                         
                         int i,j;
                         for(i=-1;i<=1;i++)
                         for(j=-1;j<=1;j++)
                         {
                                 if (i==0 && j==0)
                                         continue;
                                         
                                 color = get_pixel(x+i, y+j);
                                 red += cc[0] * cc[3];
                                 green += cc[1] * cc[3];
                                 blue += cc[2] * cc[3];
                                 alpha += cc[3];
                         }
                         
                         if (alpha == 0)
                                 continue;
                                 
                         red /= alpha;
                         green /= alpha;
                         blue /= alpha;
                         
                         
                         color = get_pixel(x, y);
                         
                         cc[0] = red;
                         cc[1] = green;
                         cc[2] = blue;
                                 
                         set_pixel(x, y, color);
                 }
         }
 }
 
 
 int main(int argc, char **argv)
 {
         if (argc != 3)
                 abort_("Usage: program_name <file_in> <file_out>");
 
         read_png_file(argv[1]);
         process_file();
         write_png_file(argv[2]);
 
         return 0;
 }
 
 
Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

10 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

png image problems 2 Answers

UI Image PNG - Transparent Background Black 1 Answer

Alpha Texture overlay 0 Answers

Two png mouse down detect 3 Answers

Saving UI Image to file with transparent background 3 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges