Saving atlas texture generated by Sprite Packer to a PNG file

When I go to:
Window > 2D > Sprite Packer
I can preview atlas textures generated automatically by Sprite Packer. What I would like to do is to save all of them into PNG files so I can look them up outside Unity editor.

I wrote following script that was supposed to do so:

using UnityEngine;
using UnityEditor;
using UnityEditor.Sprites;
using System.Collections;
using System.IO;

public class AtlasTextureExporter : MonoBehaviour
{

    [MenuItem("Tools/Atlas Exporter/Export atlases as PNG")]
    static void ExportAtlases()
    {
        string[] atlasNames = Packer.atlasNames;

        for (int i = 0; i < atlasNames.Length; i++)
        {
            string atlasName = atlasNames*;*

Texture2D[] textures = Packer.GetTexturesForAtlas(atlasName);

for (int j = 0; j < textures.Length; j++)
{
Texture2D texture = textures[j];
if (!Directory.Exists(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop) + “/Atlases”))
Directory.CreateDirectory(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop) + “/Atlases”);
FileStream fs = new FileStream(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Desktop) + “/Atlases/” + texture.name + “.png”, FileMode.Create);
BinaryWriter bw = new BinaryWriter(fs);
bw.Write(texture.EncodeToPNG());
bw.Close();
fs.Close();
}
}
}
}
But I get following error:
> ArgumentException: Texture
> ‘SpriteAtlasTexture-myScene-2048x2048-fmt12’
> is not readable, the texture memory
> can not be accessed from scripts. You
> can make the texture readable in the
> Texture Import Settings.
> AtlasTextureExporter.ExportAtlases ()
> (at
> Assets/Root/Editor/AtlasTextureExporter.cs:27)
How can I make an atlas texture readable? If I cannot, how can I save an atlas texture into a PNG file?

Same issue here with the new SpriteAtlas system. I had to copy the texture to a new RenderTexture first then save the copy, solution from here.

I couldn’t find a direct way to access the SpriteAtlas texture so I went through the internal method Unity uses to show it in the inspector panel. Obviously not using this for production, but here is how I save a SpriteAtlas to a PNG:

	[MenuItem("Tools/Export atlases as PNG")]
	static void ExportAtlases() {
		string exportPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "/Atlases";
		foreach (UnityEngine.Object obj in Selection.objects) {
			SpriteAtlas atlas = (SpriteAtlas) obj;
			if (atlas == null) continue;
			Debug.Log("Exporting selected atlas: " + atlas);
			
			// use reflection to run this internal editor method
			// UnityEditor.U2D.SpriteAtlasExtensions.GetPreviewTextures
			// internal static extern Texture2D[] GetPreviewTextures(this SpriteAtlas spriteAtlas);
			Type type = typeof(UnityEditor.U2D.SpriteAtlasExtensions);
			MethodInfo methodInfo = type.GetMethod("GetPreviewTextures", BindingFlags.Static | BindingFlags.NonPublic);
			if (methodInfo == null) {
				Debug.LogWarning("Failed to get UnityEditor.U2D.SpriteAtlasExtensions");
				return;
			}
			Texture2D[] textures = (Texture2D[])methodInfo.Invoke(null, new object[] {atlas} );
			if (textures == null) {
				Debug.LogWarning("Failed to get texture results");
				continue;
			}

			foreach (Texture2D texture in textures) {
				// these textures in memory are not saveable so copy them to a RenderTexture first
				Texture2D textureCopy = DuplicateTexture(texture);
				if (!Directory.Exists(exportPath)) Directory.CreateDirectory(exportPath);
				string filename = exportPath + "/" + texture.name + ".png";
				FileStream fs = new FileStream(filename, FileMode.Create);
				BinaryWriter bw = new BinaryWriter(fs);
				bw.Write(textureCopy.EncodeToPNG());
				bw.Close();
				fs.Close();
				Debug.Log("Saved texture to " + filename);
			}
		}
	}
	
	private static Texture2D DuplicateTexture(Texture2D source) {
		RenderTexture renderTex = RenderTexture.GetTemporary(
			source.width,
			source.height,
			0,
			RenderTextureFormat.Default,
			RenderTextureReadWrite.Linear);

		Graphics.Blit(source, renderTex);
		RenderTexture previous = RenderTexture.active;
		RenderTexture.active = renderTex;
		Texture2D readableText = new Texture2D(source.width, source.height);
		readableText.ReadPixels(new Rect(0, 0, renderTex.width, renderTex.height), 0, 0);
		readableText.Apply();
		RenderTexture.active = previous;
		RenderTexture.ReleaseTemporary(renderTex);
		return readableText;
	}

You should be able to make it readable by enabling “Read/Write Enabled” in the atlas’s Import Settings inspector.