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 );
            // ?
        }
    }
}

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;

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 = Mathf.FloorToInt(sourceRect.x);
            int y = Mathf.FloorToInt(sourceRect.y);
            int width = Mathf.FloorToInt(sourceRect.width);
            int height = Mathf.FloorToInt(sourceRect.height);
            Color[] pix = sourceTex.GetPixels(x, y, width, height);
            
        }
    }
  • Color pix = sourceTex.GetPixels();
    That’s it.

Alternatively:

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

But the result is the same.

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][1]

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*;*

var color = _colors*;*

Debug.Log( $“{spriteRenderer.name}'s colors: {color}” , spriteRenderer.gameObject );
}
}

[ContextMenu(“Update Color Data”)]
void UpdateColorData ()
{
_spriteRenderers = GetComponentsInChildren( 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*;*

// 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++;// 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 += 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 = trio;
}_

#if DEBUG
// print debug info
{
var sb = new System.Text.StringBuilder();
foreach( var color in palette ) sb.AppendLine( " color: {color}" );*_</em></em> <em><em><em><em>Debug.Log( "‘{spriteRenderer.name}’ colors: {_colors.primary}, {_colors.secondary}, {_colors.tertiary}
all colors:
{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*==spriteRenderer )
return _colors;*

}
// else not found:
Debug.LogWarning( "'{spriteRenderer.name}' not found among '{this.name}' SpriteRenderers" , spriteRenderer );*_</em></em></em></em></em></em></em> <em><em><em><em><em><em><em>_*return default(ColorTrio);*_</em></em></em></em></em></em></em> <em><em><em><em><em><em><em>_*}*_</em></em></em></em></em></em></em> <em><em><em><em><em><em><em>_*public ColorTrio GetColorsFor ( GameObject go )*_</em></em></em></em></em></em></em> <em><em><em><em><em><em><em>_*{*_</em></em></em></em></em></em></em> <em><em><em><em><em><em><em><em>*for( int i=0 ; i<_spriteRenderers.Length ; i++ )*</em></em></em></em></em></em></em></em> <em><em><em><em><em><em><em>_*{*_</em></em></em></em></em></em></em> <em><em><em><em><em><em><em><em><em>if( _spriteRenderers*.gameObject==go )*</em></em></em></em></em></em></em></em></em> <em><em><em><em><em><em><em><em><em><em>return _colors*;*</em></em></em></em></em></em></em></em></em></em> <em><em><em><em><em><em><em><em><em>_*}*_</em></em></em></em></em></em></em></em></em> <em><em><em><em><em><em><em><em><em>_*// else not found:*_</em></em></em></em></em></em></em></em></em> <em><em><em><em><em><em><em><em><em>_*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} )”;
}

}
_*[1]: https://i.imgur.com/z5EgSeU.jpg*_