using System; using System.Collections.Generic; using System.Linq; using SkiaSharp; using StabilityMatrix.Core.Extensions; namespace StabilityMatrix.Avalonia.Helpers; public static class ImageProcessor { /// /// Get the dimensions of a grid that can hold the given amount of images. /// public static (int rows, int columns) GetGridDimensionsFromImageCount(int count) { if (count <= 1) return (1, 1); if (count == 2) return (1, 2); // Prefer one extra row over one extra column, // the row count will be the floor of the square root // and the column count will be floor of count / rows var rows = (int)Math.Floor(Math.Sqrt(count)); var columns = (int)Math.Floor((double)count / rows); return (rows, columns); } public static SKImage CreateImageGrid(IReadOnlyList images, int spacing = 0) { if (images.Count == 0) throw new ArgumentException("Must have at least one image"); var (rows, columns) = GetGridDimensionsFromImageCount(images.Count); var singleWidth = images[0].Width; var singleHeight = images[0].Height; // Make output image using var output = new SKBitmap( singleWidth * columns + spacing * (columns - 1), singleHeight * rows + spacing * (rows - 1) ); // Draw images using var canvas = new SKCanvas(output); foreach ( var (row, column) in Enumerable.Range(0, rows).Product(Enumerable.Range(0, columns)) ) { // Stop if we have drawn all images var index = row * columns + column; if (index >= images.Count) break; // Get image var image = images[index]; // Draw image var destination = new SKRect( singleWidth * column + spacing * column, singleHeight * row + spacing * row, singleWidth * column + spacing * column + image.Width, singleHeight * row + spacing * row + image.Height ); canvas.DrawImage(image, destination); } return SKImage.FromBitmap(output); } }