Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • 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
1
Question by deathripper · Sep 28, 2020 at 01:07 PM · spritecolortexture2dspriterenderer

How to get Sprite color palette

Hey there,

I have a psb image which contains of multiple layers, each layer represents a gameObject and I would love to get the color of each of those elements... usually each gameObject contains only 1-3 colors and i would love to know which ones these are.

Is there any other / better approach to get that information ?

My scripts is as follows:

 using UnityEngine;
 using UnityEngine.Rendering;
 
 [System.Serializable]
 public class PageData : MonoBehaviour
 {
     private void Start()
     {
         foreach (Transform child in this.transform)
         {
             Sprite sprite = child.GetComponent<SpriteRenderer>().sprite;
             Color[] pix = sprite.texture.GetPixels();
             Debug.Log( pix );
             // ?
         }
     }
 }
Comment
Add comment · Show 6
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 andrew-lukasik · Sep 28, 2020 at 05:42 PM 0
Share

If you look into Sprite documentation page, you will see that there is a texture property already.

 Sprite sprite = child.GetComponent<SpriteRenderer>().sprite;
 Texture2D sourceTex = sprite.texture;


avatar image deathripper · Sep 29, 2020 at 06:54 AM 0
Share

Good to know, thx.

However even with this simplified script i still get the out of bounds error...

   private void Start()
     {
         foreach (Transform child in this.transform)
         {
 
             Sprite sprite = child.GetComponent<SpriteRenderer>().sprite;
 
             Texture2D sourceTex = sprite.texture;
             
            Rect sourceRect = child.gameObject.GetComponent<RectTransform>().rect;
             int x = $$anonymous$$athf.FloorToInt(sourceRect.x);
             int y = $$anonymous$$athf.FloorToInt(sourceRect.y);
             int width = $$anonymous$$athf.FloorToInt(sourceRect.width);
             int height = $$anonymous$$athf.FloorToInt(sourceRect.height);
             Color[] pix = sourceTex.GetPixels(x, y, width, height);
             
         }
     }
avatar image andrew-lukasik deathripper · Sep 29, 2020 at 07:32 AM 0
Share

You're seeing this error because RectTransform values are not texture coordinates but ui hierarchy coordinates. It's close equivalent to using transform.positionas texture x and y - not an ideal fit.

avatar image andrew-lukasik andrew-lukasik · Sep 29, 2020 at 07:45 AM 0
Share

That being said - you can probably construct a RectTransform hierarchy to mirror texture coordinates OR figure out a way of calculating one from the other

avatar image andrew-lukasik · Sep 29, 2020 at 07:50 AM 0
Share

 Color[] pix = sourceTex.GetPixels();

That's it.


Alternatively:

 Color[] pix = sourceTex.GetPixels( 0 , 0 , sourceTex.width , sourceTex.height );

But the result is the same.

avatar image deathripper andrew-lukasik · Sep 29, 2020 at 08:22 AM 0
Share

ok this seems to work without any errors, thx a lot...

However, it seems that unity is struggling quite a bit now... showing the color arry in the editor shows that each image as 2-10 million pixels and unity is really struggling.

$$anonymous$$aybe my approach is also the wrong one here... What I would love to achieve is the following:

I have a psb image which contains of multiple layers, each layer represents a gameObject and I would love to get the color of each of those elements... usually each gameObject contains only 1-3 colors and i would love to know which ones these are.

Is there any other / better approach to get that information ?

1 Reply

· Add your reply
  • Sort: 
avatar image
0

Answer by andrew-lukasik · Sep 29, 2020 at 10:31 AM

That's right. Going through Color[] to compile color palette data in an inefficient process ideally should be done as pre-processing step (in editor as asset/scene preparation) and saved for easy and fast access while application is running


Click RMB over component in Inspector window and choose "Update Color Data" to update.

inspector view

 using System.Collections.Generic;
 using System.Linq;
 using UnityEngine;
 
 public class PageData : MonoBehaviour
 {
 
     [SerializeField] ColorTrio _sharedColors;
     [SerializeField] SpriteRenderer[] _spriteRenderers;
     [SerializeField] ColorTrio[] _colors;
 
     void Start ()
     {
         for( int i=0 ; i<_spriteRenderers.Length ; i++ )
         {
             var spriteRenderer = _spriteRenderers[i];
             var color = _colors[i];
             
             Debug.Log( $"{spriteRenderer.name}'s colors: {color}" , spriteRenderer.gameObject );
         }
     }
 
     [ContextMenu("Update Color Data")]
     void UpdateColorData ()
     {
         _spriteRenderers = GetComponentsInChildren<SpriteRenderer>( includeInactive:true );
         _colors = new ColorTrio[ _spriteRenderers.Length ];
         Dictionary<Color,int> shared_palette_unsorted = new Dictionary<Color,int>();
         
         for( int i=0 ; i<_spriteRenderers.Length ; i++ )
         {
             var spriteRenderer = _spriteRenderers[i];
 
             // compile sorted array of colors (from most to least common one):
             Color[] palette;
             {
                 Dictionary<Color,int> palette_unsorted = new Dictionary<Color,int>();//to represent Color and number of pixels of that Color
                 Sprite sprite = spriteRenderer.sprite;
                 Rect spriteRect = sprite.rect;
                 Color[] spritePixels = sprite.texture.GetPixels( (int)spriteRect.x , (int)spriteRect.y , (int)spriteRect.width , (int)spriteRect.height );
                 foreach( var color in spritePixels )
                 {
                     if( color.a!=1 ) continue;// lets skip all transparent and semi-transparent pixels
                     
                     if( palette_unsorted.ContainsKey(color) )
                         palette_unsorted[color]++;// another pixel of this color
                     else
                         palette_unsorted.Add( color , 1 );// first
                 }
                 palette = palette_unsorted
                     .OrderByDescending( (kv)=>kv.Value )
                     .Select( (kv)=> kv.Key )
                     .ToArray();
                 
                 foreach( var kv in palette_unsorted )
                 {
                     Color color = kv.Key;
                     int count = kv.Value;
                     if( shared_palette_unsorted.ContainsKey(color) )
                         shared_palette_unsorted[color] += count;
                     else
                         shared_palette_unsorted.Add( color , count );
                 }
             }
             
             // pick colors:
             {
                 ColorTrio trio = new ColorTrio();
                 trio.primary = palette[0];
                 trio.secondary = palette.FirstOrDefault( (col)=> col!=trio.primary );// will result in Color(0,0,0,0) if none found
                 trio.tertiary = palette.FirstOrDefault( (col)=> col!=trio.primary && col!=trio.secondary );// will result in Color(0,0,0,0) if none found
                 _colors[i] = trio;
             }
             
             #if DEBUG
             // print debug info
             {
                 var sb = new System.Text.StringBuilder();
                 foreach( var color in palette ) sb.AppendLine( $"\tcolor: {color}" );
                 Debug.Log( $"'{spriteRenderer.name}' colors: {_colors[i].primary}, {_colors[i].secondary}, {_colors[i].tertiary}\nall colors:\n{sb}" , spriteRenderer.gameObject );
             }
             #endif
         }
 
         // pick shared colors:
         {
             Color[] shared_sorted = shared_palette_unsorted
                 .OrderByDescending( (kv)=>kv.Value )
                 .Select( (kv)=> kv.Key )
                 .ToArray();
             
             ColorTrio trio = new ColorTrio();
             trio.primary = shared_sorted[0];
             trio.secondary = shared_sorted.FirstOrDefault( (col)=> col!=trio.primary );// will result in Color(0,0,0,0) if none found
             trio.tertiary = shared_sorted.FirstOrDefault( (col)=> col!=trio.primary && col!=trio.secondary );// will result in Color(0,0,0,0) if none found
             _sharedColors = trio;
 
             #if DEBUG
             Debug.Log( $"'{this.name}' SHARED COLORS: {_sharedColors.primary}, {_sharedColors.secondary}, {_sharedColors.tertiary}" , gameObject );
             #endif
         }
 
         #if UNITY_EDITOR
         UnityEditor.EditorUtility.SetDirty( this );
         #endif
     }
 
     public ColorTrio GetColorsFor ( SpriteRenderer spriteRenderer )
     {
         for( int i=0 ; i<_spriteRenderers.Length ; i++ )
         {
             if( _spriteRenderers[i]==spriteRenderer )
                 return _colors[i];
         }
         // else not found:
         Debug.LogWarning( $"'{spriteRenderer.name}' not found among '{this.name}' SpriteRenderers" , spriteRenderer );
         return default(ColorTrio);
     }
     public ColorTrio GetColorsFor ( GameObject go )
     {
         for( int i=0 ; i<_spriteRenderers.Length ; i++ )
         {
             if( _spriteRenderers[i].gameObject==go )
                 return _colors[i];
         }
         // else not found:
         Debug.LogWarning( $"'{go.name}' not found among '{this.name}' SpriteRenderers" , go );
         return default(ColorTrio);
     }
 
     [System.Serializable]
     public struct ColorTrio
     {
         public Color primary, secondary, tertiary;
         public override string ToString () => $"( primary:{primary} , secondary:{secondary} , tertiary:{tertiary} )";
     }
     
 }

Comment
Add comment · Show 18 · 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 deathripper · Sep 29, 2020 at 10:53 AM 0
Share

Understood, the issue is that i want to make a color by number game, meaning each picture consits of up to 300 parts (GameObjects) setting the proper colour for each of them is literally a pain in the ***, therefore i made a shader to recolour the gameobjects white upon game start. In order to deter$$anonymous$$e now which colors are being needed (show the buttons etc.) and setting up ids for each gameobject to deter$$anonymous$$e wether the right color got selected upon taping these i would need to know the acctual color of each sprite...

$$anonymous$$aybe there is also a different option like using a polygon collider and getting the centerpoint of that or something?!

avatar image andrew-lukasik deathripper · Sep 29, 2020 at 11:09 AM 0
Share

Consider creating a lookup table of colors for each SpriteRenderer (sample code added above)

avatar image andrew-lukasik deathripper · Sep 29, 2020 at 12:12 PM 0
Share

Sorry for the confusion - I just updated the answer with code that actually works now :)

avatar image andrew-lukasik andrew-lukasik · Sep 29, 2020 at 12:15 PM 0
Share

[Context$$anonymous$$enu("Update Color Data")] adds an Inspector context menu with that name - click over this component with R$$anonymous$$B and this new option should be right there now (it will update both arrays automagically)

Show more comments

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.

Follow this Question

Answers Answers and Comments

136 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

Related Questions

Erase certain color from sprite 0 Answers

Slicing sliced sprite via script 0 Answers

Instantiate a gameObject with a dynamically generated sprite? 0 Answers

How to programmatically change image properties? 1 Answer

Can't create a 2D sprite with Sprite.Create when creating texture in code 1 Answer


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