using SixLabors.ImageSharp;
using System;
using System.IO;
using System.Threading.Tasks;
namespace OpenMacroBoard.SDK {
///
/// Collection of factory extension methods for s.
///
///
/// You typically don't want to invoke the static methods directly, but instead use them
/// as extension methods by calling .XYZ();
///
public static class KeyBitmapBasicFactoryExtensions {
///
/// Creates a new object.
///
/// The builder that is used to create the
/// width of the bitmap
/// height of the bitmap
/// raw bitmap data (Bgr24)
///
/// Either or are smaller than one.
///
///
/// Provided and doesn't match the
/// expected array length of .
///
public static KeyBitmap FromBgr24Array(
this IKeyBitmapFactory keyFactory,
int width,
int height,
ReadOnlySpan bitmapDataBgr24
) {
if(width < 1) {
throw new ArgumentOutOfRangeException(nameof(width));
}
if(height < 1) {
throw new ArgumentOutOfRangeException(nameof(height));
}
var expectedLength = width * height * 3;
if(bitmapDataBgr24.Length != expectedLength) {
throw new ArgumentException($"{nameof(bitmapDataBgr24)}.Length does not match it's expected size ({nameof(width)} x {nameof(height)} x 3)", nameof(bitmapDataBgr24));
}
var data = new byte[expectedLength];
bitmapDataBgr24.CopyTo(data);
return new KeyBitmap(width, height, data);
}
///
/// Creates a new object.
///
/// The builder that is used to create the
/// width of the bitmap
/// height of the bitmap
/// raw bitmap data (Bgra32). The alpha channel will be ignored.
///
/// Either or are smaller than one.
///
///
/// Provided and doesn't match the
/// expected array length of .
///
public static KeyBitmap FromBgra32Array(
this IKeyBitmapFactory keyFactory,
int width,
int height,
ReadOnlySpan bitmapDataBgra32
) {
if(width < 1) {
throw new ArgumentOutOfRangeException(nameof(width));
}
if(height < 1) {
throw new ArgumentOutOfRangeException(nameof(height));
}
var pixelCount = width * height;
var expectedLength = pixelCount * 4;
if(bitmapDataBgra32.Length != expectedLength) {
throw new ArgumentException($"{nameof(bitmapDataBgra32)}.Length does not match it's expected size ({nameof(width)} x {nameof(height)} x 4)", nameof(bitmapDataBgra32));
}
var data = new byte[expectedLength];
for(int i = 0; i < pixelCount; i++) {
var i3 = i * 3;
var i4 = i * 4;
// Copy BGR and ignore alpha channel
data[i3 + 0] = bitmapDataBgra32[i4 + 0];
data[i3 + 1] = bitmapDataBgra32[i4 + 1];
data[i3 + 2] = bitmapDataBgra32[i4 + 2];
}
return new KeyBitmap(width, height, data);
}
///
/// Creates a new object.
///
/// The builder that is used to create the
/// width of the bitmap
/// height of the bitmap
/// raw bitmap data (Bgra32). The alpha channel will be ignored.
///
/// Either or are smaller than one.
///
///
/// Provided and doesn't match the
/// expected array length of .
///
public static KeyBitmap FromRgba32Array(
this IKeyBitmapFactory keyFactory,
int width,
int height,
ReadOnlySpan bitmapDataRgba32
) {
if(width < 1) {
throw new ArgumentOutOfRangeException(nameof(width));
}
if(height < 1) {
throw new ArgumentOutOfRangeException(nameof(height));
}
var pixelCount = width * height;
var expectedLength = pixelCount * 4;
if(bitmapDataRgba32.Length != expectedLength) {
throw new ArgumentException($"{nameof(bitmapDataRgba32)}.Length does not match it's expected size ({nameof(width)} x {nameof(height)} x 4)", nameof(bitmapDataRgba32));
}
var data = new byte[expectedLength];
for(int i = 0; i < pixelCount; i++) {
var i3 = i * 3;
var i4 = i * 4;
// Copy BGR and ignore alpha channel
data[i3 + 2] = bitmapDataRgba32[i4 + 0];
data[i3 + 1] = bitmapDataRgba32[i4 + 1];
data[i3 + 0] = bitmapDataRgba32[i4 + 2];
}
return new KeyBitmap(width, height, data);
}
///
/// Creates a new object.
///
/// The builder that is used to create the
/// width of the bitmap
/// height of the bitmap
///
/// Either or are smaller than one.
///
public static KeyBitmap Empty(
this IKeyBitmapFactory keyFactory,
int width,
int height
) {
if(width < 1) {
throw new ArgumentOutOfRangeException(nameof(width));
}
if(height < 1) {
throw new ArgumentOutOfRangeException(nameof(height));
}
return new KeyBitmap(width, height, Array.Empty());
}
///
/// Creates a single color (single pixel) with a given color.
///
/// The builder that is used to create the
/// Red channel.
/// Green channel.
/// Blue channel.
public static KeyBitmap FromRgb(this IKeyBitmapFactory keyFactory, byte r, byte g, byte b) {
// If everything is 0 (black) take a shortcut ;-)
if(r == 0 && g == 0 && b == 0) {
return KeyBitmap.Black;
}
var buffer = new byte[3] { b, g, r };
return KeyBitmap.Create.FromBgr24Array(1, 1, buffer);
}
///
/// Creates a single color (single pixel) with a given color.
///
/// The builder that is used to create the
/// The color.
public static KeyBitmap FromColor(this IKeyBitmapFactory keyFactory, OmbColor color) {
return keyFactory.FromRgb(color.R, color.G, color.B);
}
///
/// Create a bitmap from an encoded given image stream.
///
public static KeyBitmap FromStream(this IKeyBitmapFactory builder, Stream bitmapStream) {
return builder.FromImageSharpImage(Image.Load(bitmapStream));
}
///
/// Create a bitmap from an encoded given image stream.
///
public static async Task FromStreamAsync(this IKeyBitmapFactory builder, Stream bitmapStream) {
return builder.FromImageSharpImage(await Image.LoadAsync(bitmapStream));
}
///
/// Create a bitmap from an encoded given image file.
///
public static KeyBitmap FromFile(this IKeyBitmapFactory builder, string bitmapFile) {
return builder.FromImageSharpImage(Image.Load(bitmapFile));
}
///
/// Create a bitmap from an encoded given image file.
///
public static async Task FromFileAsync(this IKeyBitmapFactory builder, string bitmapFile) {
return builder.FromImageSharpImage(await Image.LoadAsync(bitmapFile));
}
///
/// Creates a from a given .
///
/// The provided bitmap is null.
/// The pixel format of the image is not supported.
public static KeyBitmap FromImageSharpImage(this IKeyBitmapFactory keyFactory, Image image) {
if(image is null) {
throw new ArgumentNullException(nameof(image));
}
using var ctx = image.WithBgr24();
var pixelData = ctx.Item.ToBgr24PixelArray();
return KeyBitmap.Create.FromBgr24Array(image.Width, image.Height, pixelData);
}
}
}