- Home /
Convert Sprite Image to Texture
I am rendering a GUI.Button
which normally takes a Texture
but I'd like to load the image for the button from a sprite sheet instead.
I've been digging in code for a while but I can't find a way to cast/convert a sprite to a texture.
I know you can do it the other way around. That is build a Sprite at runtime from a texture using Sprite.Create(). I don't know how you select a portion of a texture for use in a Button, but you could use GUI.TextureWithTexCoords() and do your own hit test. GUI is not my primary UI, so there may be other ways.
Answer by codeimpossible · Feb 28, 2014 at 06:39 AM
So if anyone is looking for the answer: here it is.
First, you have to open your sprite texture in the inspector and change the type from "Sprite" to "Advanced". Then make sure that Read/Write Enabled
is checked. Click Apply and now you can read the texture and set it into a new texture like so:
// assume "sprite" is your Sprite object
var croppedTexture = new Texture2D( (int)sprite.rect.width, (int)sprite.rect.height );
var pixels = sprite.texture.GetPixels( (int)sprite.textureRect.x,
(int)sprite.textureRect.y,
(int)sprite.textureRect.width,
(int)sprite.textureRect.height );
croppedTexture.SetPixels( pixels );
croppedTexture.Apply();
croppedTexture will now contain the sprite's image as a Texture2D
!
Tried your solution, but when I change type from "Sprite" to "Advanced", and click apply, Unity always instantly revokes the changes and sets it back to Sprite again. Do you know if this is a UnityPro-only feature?
Thanks for posting your own answer, codeimpossible. Seems to work for me. & kid_karma, I'm working with Indie version, so this is not a Pro-only feature. When you import a sprite sheet, set sprite type to multiple, and use the button below that to bring up the Sprite Editor and splice to get your individual sprites. $$anonymous$$aybe you already know that, but I'm still figuring this stuff out since I've mainly been working with 3d.
Nice way to get cropped textures from an atlas. I just want to point that I had to use sprite.rect
ins$$anonymous$$d of sprite.textureRect
on sprite.texture.GetPixels
in order to get actual size of the sprite.
You should not be casting from a float
to an int
in this context. And if you insist on it, then at least use either rect
or textureRect
for height x width calculation, not both. A sprite's rect
and textureRect
won't always be precisely equal (which may or may not be a bug on Unity's end.) $$anonymous$$g. rect
may equal 117.0 and textureRect
may equal 116.9; and an explicit primitive cast will truncate the decimal entirely. $$anonymous$$eaning (int) 116.9 == 116
. The Color[]
array will then be sized to 116*n, but the Texture2D
will be expecting an array that has a size of 117*n, which ultimately will throw an error.
I know this is an old article, however it is something that is relevant for as long as unity has sprites and textures and they are likely not going away. I feel I should mention that above method is very expensive. If you are planning on running this during gameplay be ready to pay the price in stuttering animations etc. This should probably only be done during game initialization or a load screen. Best option though is to prepare these ahead of runtime and have two sets of runtime assets. Unless you are doing some kind of fancy dynamic generation of the sprite and you really really need the texture on the fly.
Answer by trothmaster · Oct 26, 2014 at 08:28 PM
Here is a static helper method that will give you a texture2D from a sprite. It will even determine if the sprite is part of a single texture or if it is just a single sprite automatically. (basically the same as codeimpossibles answer)
public static Texture2D textureFromSprite(Sprite sprite)
{
if(sprite.rect.width != sprite.texture.width){
Texture2D newText = new Texture2D((int)sprite.rect.width,(int)sprite.rect.height);
Color[] newColors = sprite.texture.GetPixels((int)sprite.textureRect.x,
(int)sprite.textureRect.y,
(int)sprite.textureRect.width,
(int)sprite.textureRect.height );
newText.SetPixels(newColors);
newText.Apply();
return newText;
} else
return sprite.texture;
}
You can even make this an extension method by adding the this
keyword before the sprite
parameter:
public static Texture2D textureFromSprite(this Sprite sprite) ...
Answer by LaneFox · Oct 21, 2016 at 06:29 PM
For those looking for an Editor Only solution you can use AssetPreview.GetAssetPreview. If you really wanted to convert a Sprite to a Texture it must be Readable which means you have to set it to Advanced in the import settings and then make it readable. Doing so will make it consume more memory so you'll have to weigh the pros and cons of going through all that mess.
If all you're doing is drawing sprites in the editor, GetAssetPreview isn't bad.
This is exactly the kind of answer I was looking for. I was trying to do what OP suggested for an EditorPreviewWindow and this is perfect, thanks!
THAN$$anonymous$$ YOU. I made a sprite animator asset and have been trying to figure out for hours and hours how to just get the texture of a single sprite from a multiple sprite asset. +1
Answer by jorg3n3gr3iros · Aug 19, 2016 at 11:16 PM
@username trothmaster
Your solution is very good, but the code returns a error of pixel count.
resolved using the System.Math.Ceiling for to round the number for up.
Texture2D ConvertSpriteToTexture(Sprite sprite)
{
try
{
if (sprite.rect.width != sprite.texture.width)
{
Texture2D newText = new Texture2D((int)sprite.rect.width, (int)sprite.rect.height);
Color[] colors = newText.GetPixels();
Color[] newColors = sprite.texture.GetPixels((int)System.Math.Ceiling(sprite.textureRect.x),
(int)System.Math.Ceiling(sprite.textureRect.y),
(int)System.Math.Ceiling(sprite.textureRect.width),
(int)System.Math.Ceiling(sprite.textureRect.height));
Debug.Log(colors.Length+"_"+ newColors.Length);
newText.SetPixels(newColors);
newText.Apply();
return newText;
}
else
return sprite.texture;
}catch
{
return sprite.texture;
}
}
Ins$$anonymous$$d of System.$$anonymous$$ath.Ceiling
, you'd better use Unity's $$anonymous$$athf.CeilToInt
. The former method works with double
rather than float
and will introduce an automatic conversion from float
to double
durring the call. By using Unity's method I hope you would avoid at least that typecast.
Answer by lentinant · Oct 03, 2014 at 08:10 AM
You can simply use Resources.Load. Since asset type is determined not by file, but by Unity itself, you can use your sprite source image as any graphic asset. Using C#
Texture tex = Resources.Load ("textureName");
Your answer
Follow this Question
Related Questions
Addressable texture2d 0 Answers
confusion with sprites. 0 Answers
How to create a Texture2D from a sprite asset 2 Answers
Sprite Based Score Rendering 1 Answer
What is the best way of creating a modular texture? 0 Answers