TxSprite.fromPngBytes constructor
Create a TxSprite from an indexed PNG Sprites should be PNGs with palettes of up to 2, 4, or 16 colors (1-, 2-, or 4-bit indexed palettes) Alpha channel (4th-RGBA), if present, is dropped before sending to Frame (RGB only, but color 0 is VOID) Scale to 640x400 if larger, preserving aspect ratio
Implementation
TxSprite.fromPngBytes({required super.msgCode, required Uint8List pngBytes}) {
var imgPng = img.PngDecoder().decode(pngBytes);
if (imgPng != null &&
imgPng.hasPalette &&
imgPng.palette!.numColors <= 16) {
// resize the image if it's too big - we really shouldn't have to do this for project sprites, just user-picked images
if (imgPng.width > 640 || imgPng.height > 400) {
// use nearest interpolation, we can't use any interpolation that averages colors
imgPng = img.copyResize(imgPng,
width: 640,
height: 400,
maintainAspect: true,
interpolation: img.Interpolation.nearest);
}
_width = imgPng.width;
_height = imgPng.height;
_numColors = imgPng.palette!.numColors;
_pixelData = imgPng.data!.toUint8List();
// we can process RGB or RGBA format palettes, but any others we just exclude here
if (imgPng.palette!.numChannels == 3 ||
imgPng.palette!.numChannels == 4) {
if (imgPng.palette!.numChannels == 3) {
_paletteData = imgPng.palette!.toUint8List();
}
else if (imgPng.palette!.numChannels == 4) {
// strip out the alpha channel from the palette
_paletteData = _extractRGB(imgPng.palette!.toUint8List());
}
//_log.fine('Sprite: ${imgPng.width} x ${imgPng.height}, ${imgPng.palette!.numColors} cols, ${sprite.pack().length} bytes');
} else {
throw Exception(
'PNG colors must have 3 or 4 channels to be converted to a sprite');
}
} else {
throw Exception(
'PNG must be a valid PNG image with a palette (indexed color) and 16 colors or fewer to be converted to a sprite');
}
}