Skip to main content

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:

MethodUse
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:

SpecifierExampleResult
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 spaceoutArray 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.

tip

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,
};
tip

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.
  • outArray sizeinArray.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.