public static Image <Rgba32> PackSpriteSheet(uint[] palette, int frameCount, GetFrameDelegate <byte> getFrame) { var layout = SpriteSheetUtil.ArrangeSpriteSheet(frameCount, 0, getFrame); Image <Rgba32> image = new Image <Rgba32>(layout.Width, layout.Height); if (!image.TryGetSinglePixelSpan(out var rgbaSpan)) { throw new InvalidOperationException("Could not retrieve single span from Image"); } Span <uint> pixels = MemoryMarshal.Cast <Rgba32, uint>(rgbaSpan); for (var i = 0; i < frameCount; i++) { var frame = getFrame(i); var(toX, toY) = layout.Positions[i]; var target = pixels[(toX + toY * layout.Width)..];
public static SpriteSheetLayout ArrangeSpriteSheet <T>(int frameCount, int margin, GetFrameDelegate <T> getFrame) { long totalPixels = 0; int width = 0; for (int i = 0; i < frameCount; i++) { var frame = getFrame(i); totalPixels += (frame.Width + 2 * margin) * (frame.Height + 2 * margin); if (width < frame.Width) { width = frame.Width; } } int sqrtTotal = (int)Math.Sqrt(totalPixels); if (sqrtTotal > width) { width = sqrtTotal; } width = ApiUtil.NextPowerOfTwo(width); // First arrange to determine required size and positions, then create the image. var positions = new (int, int)[frameCount];