• 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
Question by sam-rae · Jun 18, 2019 at 09:39 PM · spritetexture2dspritesloadimageloadimageintotexture

Texture2D.LoadImage color/colour problems

I'm doing some version of palette swapping for sprites, and I keep $$anonymous$$tting a problem. Unity seems to be altering the colours in PNG files when importing.

As you can see below, when the sprite is saved it has very specific values. when I run the code below to immediately save the png after loading, I get different colours.

If anyone has any idea about what I'm doing wrong here, I'd love to know. To avoid any arguments: I'm not here for a discussion about whether t$$anonymous$$s is the best way to do t$$anonymous$$s, I'm after an answer to a weird problem.

alt text

 byte[] spriteBytes = File.ReadAllBytes(fullPath);

 Texture2D temp = new Texture2D(2, 2, TextureFormat.RGBA32,false);
 //to get the proper size
 if (!temp.LoadImage(spriteBytes)) {
   Debug.LogError("image file:[" + fullPath + "] could not be read.");
   return;
 }
 //import again at the correct size (apparently t$$anonymous$$s is a t$$anonymous$$ng).
 spriteSheetTexture = new Texture2D(temp.width, temp.height, TextureFormat.RGBA32,false);
 
 if (spriteSheetTexture.LoadImage(spriteBytes))  {
   File.WriteAllBytes("a path dont worry about it.png", spriteSheetTexture.EncodeToPNG());
 }

unity version info: 2019.1.7f1personal Visual studio: 2017 15.9.12 community

Comment
animagnoa

People who like this

1 Show 0
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

1 Reply

· Add your reply
  • Sort: 
avatar image
Best Answer

Answer by Bunny83 · Jun 19, 2019 at 01:33 AM

Well, I just did a few tests with LoadImage and EncodePNG. It looks like Unity has issues with loading png files that contain gamma information. When I create a 4k texture with all 16 million colors in Unity and export as png, the resulting file does not contain any of the usual png chunks. It only contains the IHDR as well as several IDAT chunk with the data. If I load t$$anonymous$$s png dynamically through LoadImage, everyt$$anonymous$$ng is right.


However when I open that png in mspaint and re-save it, the new png will have a sRGB, gAMA and pHYs chunk as usual. When we load t$$anonymous$$s at runtime we get errors in the colors that is 0 at black (0) ramps up to "-9" at 128 and ramps back down to 0 as we go further up to 255. So it seems to be a wrong gamma correction that is going on since gamma correction is a power function. That's why the error is largest at 128 ( 0.5 ) and 0 at 0 (0.0) and 255 (1.0).


I would recommend to file a bug report


edit

I just tried using my PNGTools w$$anonymous$$ch I wrote for t$$anonymous$$s question over here and removed the sRGB, gAMA and pHYs chunks before letting Unity load the png and it seems to work with my test image.

Specifically instead of

 byte[] spriteBytes = File.ReadAllBytes(fullPath);

do t$$anonymous$$s:

     byte[] spriteBytes;
     using (var fileStream = System.IO.File.OpenRead("C:\\Data\\ColorTest.png"))
     using (var reader = new System.IO.BinaryReader(fileStream))
     {
         var png = PNGTools.ReadPNGFile(reader);
         for (int i = png.chunks.Count - 1; i >= 0; i--)
         {
             var c = png.chunks[i];
             if (c.type == EPNGChunkType.gAMA ||
                 c.type == EPNGChunkType.pHYs ||
                 c.type == EPNGChunkType.sRBG)
             {
                 png.chunks.RemoveAt(i);
             }
         }
         using (var mem = new MemoryStream())
         {
             PNGTools.WritePNGFile(png, new BinaryWriter(mem));
             spriteBytes = mem.ToArray();
         }
     }

Note that t$$anonymous$$s is not guaranteed to work with every kind of png file.

Comment
sam-rae

People who like this

1 Show 7 · 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 Bunny83 · Jun 19, 2019 at 01:34 AM 1
Share

Note that when importing the png actually as asset through the Unity editor the colors are correct. So it seems to be an issue in the runtime png loader.

avatar image sam-rae · Jun 19, 2019 at 08:43 AM 0
Share

You absolute legend. I love the "I have a problem so I built a tool to fix it" approach.

I ended up "solving" it at 1am by reading the data in via the System.Drawing.Bitmap class and then using

    Texture2D.LoadRawTextureData(byte[] data);
Interesting note: The bitmap class seems to load things upside-down but you can then flip it

avatar image sam-rae · Jun 19, 2019 at 08:45 AM 0
Share

Looks like it's on purpose:

issue

avatar image raarc · Jun 21, 2020 at 03:13 AM 0
Share

@bunny83 You saved me with this code, thank you so much. I had to change some things, I switched EPNGChunkType to EChunkType and the gAMA uint value was different on my files so I changed it to 1766015824. It works perfectly thanks a lot for this tool

avatar image Bunny83 raarc · Jun 21, 2020 at 03:20 AM 0
Share

Uhm the value you just mentioned is not a gAMA chunk. It's an iCCP chunk. The value 1766015824 is 0x69434350 in hex which literally represents the ascii characters "iCCP". All PNG chunk headers are 4 ascii characters. The iCCP chunk is an embedded color profile. So yes, it could also cause some color "errors".

avatar image raarc Bunny83 · Jun 21, 2020 at 09:12 AM 0
Share

hmm then my file did not have a gAMA chunk. Your tool detected 6 chunks and 5 of them were in your enum EChunkType and the one that didnt print was gAMA, your tool told me the id of the one unnacouted for was 1766015824 so i replaced it on gAMA and it fixed the problem. Before I replaced that value the colors were still returning wrong so that chunk was definitely causing the problem.(maybe in conjunction with phys and srgb). Your tool is amazing by the way! Thanks again

avatar image emongev · Aug 22, 2020 at 08:54 AM 0
Share

Thank you so much! you saved me with this, the logic behind was wrong was way over my head, but luckily your fix solved it! :)

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

148 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 avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Image is crushed --- Sprite 2 Answers

2D sprite renders a small part of another one with "Sprite Mode : Multiple" 0 Answers

"Could not create sprite" exception - copying and manipulating texture from SpriteAtlas 1 Answer

iOS Sprites in PVRTC? 1 Answer

Difference between Sprite and Default texture types? 0 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