UGTK / Toolkit / Libraries Extensions / Sprite Base64 Extension Completed
Sprite Base64
Summary
The Sprite Base64 module converts between Unity Sprites and their encoded representations: it
exports the sprite's own area to PNG/JPG bytes or a Base64 string, and rebuilds a Sprite from a
Base64 string or a raw byte array. It is the glue for sending images over HTTP/JSON, storing them in
a save file or a database, and for the UGTK photo/upload systems.
Content
Modules Dependencies
None. One static extension class, no UGTK reference.
Setup
Nothing to set up: no component, no prefab, no scene — this is a static extension class, so there is
nothing to show in a GIF. Add UGTK.LibrariesExtensions.SpriteBase64 to your assembly definition
references and:
using UGTK.LibrariesExtension.SpriteBase64;
Note the namespace:
LibrariesExtension, singular, even though the folder and the assembly areLibrariesExtensions.
One requirement, and it is the one that bites: the source texture must be readable —
Texture Import Settings ▸ Advanced ▸ Read/Write Enabled. Without it GetPixels throws at runtime.
Textures created in code (new Texture2D(...), downloaded images, webcam frames) are readable by
construction.
How To Use
Every method is an extension method, on Sprite, on string and on byte[]:
using UGTK.LibrariesExtension.SpriteBase64;
// Sprite -> Base64 (PNG, lossless)
string data = mySprite.SpriteToBase64();
// Base64 -> Sprite (centered pivot, 100 PPU)
Sprite restored = data.Base64ToSprite();
// Sprite -> raw bytes, PNG or JPG
byte[] png = mySprite.SpriteToBytes(); // PNG
byte[] jpg = mySprite.SpriteToBytes(useJpg: true, jpgQuality: 80);
// raw bytes -> Sprite, choosing the pixels per unit
Sprite fromBytes = png.BytesToSprite(pixelsPerUnit: 200f);
What "the sprite's area" means. Both encoders read sprite.rect from the source texture, so a
sprite taken from an atlas or a sliced sheet exports only its own frame, not the whole sheet.
Good to know:
SpriteToBase64keeps the source texture format, so it fails on compressed textures (DXT/ASTC) becauseSetPixelsneeds an uncompressed one.SpriteToBytesrebuilds inRGBA32instead and is therefore the safer of the two: for a compressed source, useConvert.ToBase64String(sprite.SpriteToBytes()).- PNG or JPG: PNG is lossless and keeps the alpha; JPG is much smaller but drops the alpha —
never use it for UI sprites with transparency.
jpgQualityis clamped to 1–100. - Base64 costs ~33% more bytes than the raw array: send
SpriteToByteswhen the channel accepts binary, and keep Base64 for JSON/text fields. - The decoders allocate a new
Texture2Devery call and Unity does not garbage-collect textures: when you replace a decoded sprite, destroy the old one withObject.Destroy(oldSprite.texture)— otherwise a refresh loop leaks memory steadily. - The rebuilt sprite always has a centered pivot and, for
Base64ToSprite, 100 PPU: if your UI expects a different pivot, useBytesToSpriteand rebuild the sprite yourself. - Errors are exceptions, not silent failures:
ArgumentNullExceptionon a null sprite / empty string / empty array, and a genericExceptionwhenLoadImagecannot decode the data. Wrap the calls when the payload comes from the network.
Testing Scene
Open Debug/SpriteBase64Scene.unity. It holds SpriteBase64Test with
Mn_SpriteBase64Test, and two sprite renderers side by side: Original, showing the sample
image, and Rebuilt, which stays empty until a decode fills it. Every method is on the component's
context menu — right-click the header in the Inspector, no play mode needed.
The sample, Debug/SpriteBase64_Sample.png, is deliberately built for this test: a checkerboard
with hard edges, a gradient, and three saturated bands. It is imported with Read/Write enabled,
which the encoder requires.
What to do, in order:
- Encode — the sample comes out as roughly 6,800 characters, about 6.6 KB of text.
- Decode — the string is rebuilt into a 256×256 sprite and assigned to
Rebuilt, so the two renderers can be compared in the Scene view. - Turn Use Jpg on and Encode again. On this image the JPG payload is five times larger than the PNG one: a flat, hard-edged image is exactly the case PNG wins, and picking JPG by reflex makes the payload worse. Try it on a photo and the result flips.
- Decode Garbage — feeding the decoder a string that is not an image raises
LoadImage failed: invalid data, caught and shown rather than swallowed.
The one hard requirement is the source texture's Read/Write flag. Without it the encoder throws, and it throws at the moment of encoding rather than at import, which is why it is worth seeing here.
Technical Info
| Path | Content |
|---|---|
Scripts/SpriteBase64.cs |
The whole system: the static class SpriteBase64, namespace UGTK.LibrariesExtension.SpriteBase64 |
API: SpriteToBase64(this Sprite), Base64ToSprite(this string),
SpriteToBytes(this Sprite, bool useJpg = false, int jpgQuality = 100),
BytesToSprite(this byte[], float pixelsPerUnit = 100f).
© 2026 Marcello De Bonis. All rights reserved
UGTKengine within an engine

