Encoding & Decoding
TinyCLR includes the standard .NET classes for converting between strings, byte arrays, and other primitive representations: Encoding for text/byte conversion, Convert for Base64, BitConverter for primitive-to-byte conversion, and StringBuilder for efficient string assembly.
Strings and arrays
The System.Text.Encoding class converts between strings and byte arrays. UTF-8 is the most common encoding in embedded use.
using System.Text;
// Byte array → string.
var text = Encoding.UTF8.GetString(new byte[] { 65, 66, 67, 68, 69 }); // "ABCDE"
// String → byte array.
byte[] bytes = Encoding.UTF8.GetBytes("ABCDE"); // { 65, 66, 67, 68, 69 }
Available overloads:
| Method | Use |
|---|---|
GetString(byte[]) | Decode an entire byte array. |
GetString(byte[], index, count) | Decode a slice. |
GetBytes(string) | Encode an entire string. |
GetBytes(string, charIndex, charCount, byte[] bytes, byteIndex) | Encode into an existing buffer. Returns the byte count. |
GetChars(byte[]) | Decode to a char[] instead of string. |
GetChars(byte[], index, count) | Slice variant. |
Base64
Base64 packs binary data into printable ASCII — useful for embedding bytes in JSON, URLs, or email-style transports.
using System;
byte[] data = new byte[] { 0xDE, 0xAD, 0xBE, 0xEF };
// Bytes → Base64 string.
string encoded = Convert.ToBase64String(data); // "3q2+7w=="
// Base64 string → bytes.
byte[] decoded = Convert.FromBase64String(encoded);
To use the RFC 4648 variant (which differs from the legacy default in padding/character set details), set Convert.UseRFC4648Encoding = true;.
BitConverter
BitConverter packs and unpacks primitive numeric types as byte arrays. Use it for binary protocols where you need to write a specific number of bytes in a specific order.
using System;
// Integer → 4 bytes (little-endian on TinyCLR).
byte[] a = BitConverter.GetBytes(23); // { 23, 0, 0, 0 }
byte[] b = BitConverter.GetBytes(65536); // { 0, 0, 1, 0 }
// Bytes → integer.
int value = BitConverter.ToInt32(b, 0); // 65536
// Bytes → hex string (different from text decoding!).
string hex = BitConverter.ToString(new byte[] { 65, 66, 67, 68, 69 });
// hex == "41-42-43-44-45"
BitConverter.ToString(...) produces a hex-pair string with hyphens — useful for logging raw protocol bytes. For text decoding, use Encoding.UTF8.GetString(...) instead.
Supported overloads
GetBytes for: bool, char, short, ushort, int, uint, long, ulong, float, double.
ToX for reading bytes back: ToBoolean, ToChar, ToInt16, ToUInt16, ToInt32, ToUInt32, ToInt64, ToUInt64, ToSingle, ToDouble, ToString. Each takes (byte[] bytes, int startIndex).
DoubleToInt64Bits / Int64BitsToDouble for reinterpreting a double as the underlying long bit pattern (useful when you need exact bit-level access to floats).
SwapEndianness(byte[] data, int groupSize, int index, int size) flips byte order in-place — handy for big-endian network protocols.
ToString formats
TinyCLR supports a subset of the standard numeric format specifiers:
| Specifier | Example | Result |
|---|---|---|
N (number with thousands separator) | 123.ToString("N4") | 123.0000 |
F (fixed-point) | 123.ToString("F4") | 123.0000 |
D (zero-padded decimal) | 123.ToString("D4") | 0123 |
G (general) | 123.ToString("G4") | 123 |
X (uppercase hex) | 123.ToString("X4") | 007B |
Not supported — these throw an exception on TinyCLR:
E(scientific notation)R(round-trip)P(percent)C(currency)
StringBuilder
Strings in .NET are immutable — every concatenation allocates a new string and orphans the old one. In a tight loop, that creates a lot of garbage for the GC to clean up. StringBuilder uses a single growable buffer instead, so building a string character-by-character or in pieces is fast and allocation-light.
using System.Diagnostics;
using System.Text;
// Modify an existing string in place.
var sb = new StringBuilder("PA0 is the pin to use.");
sb[1] = 'B';
Debug.WriteLine(sb.ToString()); // "PB0 is the pin to use."
// Build a string up incrementally.
var digits = new StringBuilder();
for (int i = 48; i < 58; i++)
digits.Append((char)i);
Debug.WriteLine(digits.ToString()); // "0123456789"
Reach for StringBuilder whenever you'd otherwise be concatenating strings in a loop.
Color space conversion
TinyCLR's display stack uses 5:6:5 RGB (16 bits per pixel) internally — two bytes per pixel. The Convert API (in the graphics namespace) converts between this and other common pixel formats for input data coming from image decoders, cameras, or other sources.
Convert(byte[] inArray, byte[] outArray, ColorFormat colorFormat, RgbFormat rgbFormat, byte alpha, byte[] colorTable);
Allocate outArray to the correct size for the target color format:
| Target color space | outArray size |
|---|---|
| 3:5:2 (8 bpp) | inArray.Length × 0.5 |
| 4:4:4 (12 bpp, 2 bytes/pixel) | inArray.Length × 0.75 |
| 5:6:5 (16 bpp) | inArray.Length × 1 |
| 8:8:8 (24 bpp) | inArray.Length × 1.5 |
| 8:8:8:8 (32 bpp w/ alpha) | inArray.Length × 2.0 |
rgbFormat lets you swap channel order (RGB vs BGR), and alpha (0 = transparent, 255 = opaque) is used only by the 8:8:8:8 format.
Converting 5:6:5 → 5:6:5 doesn't change the color depth — but it's still useful for switching rgbFormat (channel swap) or applying colorTable scaling.
The optional colorTable is a 64-entry byte array that maps each 6-bit input channel value (0–63) to an 8-bit output value. Without one, Convert simply shifts 6-bit values up to 8 bits, which gives a slight bias toward dark. A more linear mapping looks like this:
var ColorTable565To888 = new byte[64] {
0, 2, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56,
60, 64, 68, 72, 76, 80, 85, 89, 93, 97,101,105,109,113,117,121,
125,129,133,137,141,145,149,153,157,161,165,170,174,178,182,186,
190,194,198,202,206,210,214,218,222,226,230,234,238,242,246,250,
};
The custom color table is only honored for 5:6:5, 8:8:8, and 8:8:8:8 targets.
1 BPP conversion
ConvertTo1Bpp converts from internal 5:6:5 to a 1-bit-per-pixel monochrome bitmap. Any color becomes 1; only pure black becomes 0.
ConvertTo1Bpp(byte[] inArray, byte[] outArray, uint width);
ConvertTo1Bpp(byte[] inArray, byte[] outArray, uint width, BitFormat bitFormat);
width— the pixel width of the source image.outArraysize —inArray.Length × 0.0625(1 bit per pixel vs 16 bits per pixel input).bitFormat— defaults to vertical grouping (8 pixels stacked per byte), which matches most monochrome OLED panels. Pass an overload value to get horizontal grouping if your panel expects it.