diff --git a/StableDiffusion.NET/Backends/RocmBackend.cs b/StableDiffusion.NET/Backends/RocmBackend.cs index 61ad0d6..14035e0 100644 --- a/StableDiffusion.NET/Backends/RocmBackend.cs +++ b/StableDiffusion.NET/Backends/RocmBackend.cs @@ -2,7 +2,6 @@ using System.Runtime.InteropServices; using System.Text.RegularExpressions; using JetBrains.Annotations; -using StableDiffusion.NET.Helper; namespace StableDiffusion.NET; diff --git a/StableDiffusion.NET/Extensions/ImageExtension.cs b/StableDiffusion.NET/Extensions/ImageExtension.cs deleted file mode 100644 index 704251b..0000000 --- a/StableDiffusion.NET/Extensions/ImageExtension.cs +++ /dev/null @@ -1,9 +0,0 @@ -using StableDiffusion.NET.Helper.Images; -using StableDiffusion.NET.Helper.Images.Colors; - -namespace StableDiffusion.NET; - -public static class ImageExtension -{ - public static Image ToImage(this StableDiffusionImage image) => new(image.Data.ToArray(), 0, 0, image.Width, image.Height, image.Width); -} \ No newline at end of file diff --git a/StableDiffusion.NET/Helper/ImageHelper.cs b/StableDiffusion.NET/Helper/ImageHelper.cs new file mode 100644 index 0000000..dbccb15 --- /dev/null +++ b/StableDiffusion.NET/Helper/ImageHelper.cs @@ -0,0 +1,36 @@ +using HPPH; +using System; +using System.Runtime.InteropServices; + +namespace StableDiffusion.NET; + +internal static class ImageHelper +{ + public static unsafe Image ToImage(Native.sd_image_t* sdImage) + { + int width = (int)sdImage->width; + int height = (int)sdImage->height; + int bpp = (int)sdImage->channel; + + Image image = Image.Create(new ReadOnlySpan(sdImage->data, width * height * bpp), width, height, width * bpp); + + Dispose(sdImage); + + return image; + } + + public static unsafe void Dispose(Native.sd_image_t* image) + { + Marshal.FreeHGlobal((nint)image->data); + Marshal.FreeHGlobal((nint)image); + } + + public static unsafe Native.sd_image_t ToSdImage(this IImage image, byte* pinnedReference) + => new() + { + width = (uint)image.Width, + height = (uint)image.Height, + channel = (uint)image.ColorFormat.BytesPerPixel, + data = pinnedReference + }; +} \ No newline at end of file diff --git a/StableDiffusion.NET/Helper/Images/Colors/ColorABGR.cs b/StableDiffusion.NET/Helper/Images/Colors/ColorABGR.cs deleted file mode 100644 index 5f1d95c..0000000 --- a/StableDiffusion.NET/Helper/Images/Colors/ColorABGR.cs +++ /dev/null @@ -1,66 +0,0 @@ -// ReSharper disable ConvertToAutoProperty - -using System.Diagnostics; -using System.Runtime.InteropServices; - -namespace StableDiffusion.NET.Helper.Images.Colors; - -/// -/// Represents a color in 32 bit ABGR-format. -/// -[DebuggerDisplay("[A: {A}, R: {R}, G: {G}, B: {B}]")] -[StructLayout(LayoutKind.Sequential)] -public readonly struct ColorABGR : IColor -{ - #region Properties & Fields - - /// - public static ColorFormat ColorFormat => ColorFormat.ABGR; - - private readonly byte _a; - private readonly byte _b; - private readonly byte _g; - private readonly byte _r; - - // ReSharper disable ConvertToAutoPropertyWhenPossible - /// - public byte A => _a; - - /// - public byte B => _b; - - /// - public byte G => _g; - - /// - public byte R => _r; - // ReSharper restore ConvertToAutoPropertyWhenPossible - - #endregion - - #region Constructors - - /// - /// Initializes a new instance of the class. - /// - /// The alpha-component of the color. - /// The blue-component of the color. - /// The green-component of the color. - /// The red-component of the color. - public ColorABGR(byte a, byte b, byte g, byte r) - { - this._a = a; - this._b = b; - this._g = g; - this._r = r; - } - - #endregion - - #region Methods - - /// - public override string ToString() => $"[A: {_a}, R: {_r}, G: {_g}, B: {_b}]"; - - #endregion -} \ No newline at end of file diff --git a/StableDiffusion.NET/Helper/Images/Colors/ColorARGB.cs b/StableDiffusion.NET/Helper/Images/Colors/ColorARGB.cs deleted file mode 100644 index 4bb6f3f..0000000 --- a/StableDiffusion.NET/Helper/Images/Colors/ColorARGB.cs +++ /dev/null @@ -1,66 +0,0 @@ -// ReSharper disable ConvertToAutoProperty - -using System.Diagnostics; -using System.Runtime.InteropServices; - -namespace StableDiffusion.NET.Helper.Images.Colors; - -/// -/// Represents a color in 32 bit ARGB-format. -/// -[DebuggerDisplay("[A: {A}, R: {R}, G: {G}, B: {B}]")] -[StructLayout(LayoutKind.Sequential)] -public readonly struct ColorARGB : IColor -{ - #region Properties & Fields - - /// - public static ColorFormat ColorFormat => ColorFormat.ARGB; - - private readonly byte _a; - private readonly byte _r; - private readonly byte _g; - private readonly byte _b; - - // ReSharper disable ConvertToAutoPropertyWhenPossible - /// - public byte A => _a; - - /// - public byte R => _r; - - /// - public byte G => _g; - - /// - public byte B => _b; - // ReSharper restore ConvertToAutoPropertyWhenPossible - - #endregion - - #region Constructors - - /// - /// Initializes a new instance of the class. - /// - /// The alpha-component of the color. - /// The red-component of the color. - /// The green-component of the color. - /// The blue-component of the color. - public ColorARGB(byte a, byte r, byte g, byte b) - { - this._a = a; - this._r = r; - this._g = g; - this._b = b; - } - - #endregion - - #region Methods - - /// - public override string ToString() => $"[A: {_a}, R: {_r}, G: {_g}, B: {_b}]"; - - #endregion -} \ No newline at end of file diff --git a/StableDiffusion.NET/Helper/Images/Colors/ColorBGR.cs b/StableDiffusion.NET/Helper/Images/Colors/ColorBGR.cs deleted file mode 100644 index 510e738..0000000 --- a/StableDiffusion.NET/Helper/Images/Colors/ColorBGR.cs +++ /dev/null @@ -1,63 +0,0 @@ -// ReSharper disable ConvertToAutoProperty - -using System.Diagnostics; -using System.Runtime.InteropServices; - -namespace StableDiffusion.NET.Helper.Images.Colors; - -/// -/// Represents a color in 24 bit BGR-format. -/// -[DebuggerDisplay("[A: {A}, R: {R}, G: {G}, B: {B}]")] -[StructLayout(LayoutKind.Sequential)] -public readonly struct ColorBGR : IColor -{ - #region Properties & Fields - - /// - public static ColorFormat ColorFormat => ColorFormat.BGR; - - private readonly byte _b; - private readonly byte _g; - private readonly byte _r; - - // ReSharper disable ConvertToAutoPropertyWhenPossible - /// - public byte A => byte.MaxValue; - - /// - public byte B => _b; - - /// - public byte G => _g; - - /// - public byte R => _r; - // ReSharper restore ConvertToAutoPropertyWhenPossible - - #endregion - - #region Constructors - - /// - /// Initializes a new instance of the class. - /// - /// The blue-component of the color. - /// The green-component of the color. - /// The red-component of the color. - public ColorBGR(byte b, byte g, byte r) - { - this._b = b; - this._g = g; - this._r = r; - } - - #endregion - - #region Methods - - /// - public override string ToString() => $"[A: {A}, R: {_r}, G: {_g}, B: {_b}]"; - - #endregion -} \ No newline at end of file diff --git a/StableDiffusion.NET/Helper/Images/Colors/ColorBGRA.cs b/StableDiffusion.NET/Helper/Images/Colors/ColorBGRA.cs deleted file mode 100644 index f1c557e..0000000 --- a/StableDiffusion.NET/Helper/Images/Colors/ColorBGRA.cs +++ /dev/null @@ -1,66 +0,0 @@ -// ReSharper disable ConvertToAutoProperty - -using System.Diagnostics; -using System.Runtime.InteropServices; - -namespace StableDiffusion.NET.Helper.Images.Colors; - -/// -/// Represents a color in 32 bit BGRA-format. -/// -[DebuggerDisplay("[A: {A}, R: {R}, G: {G}, B: {B}]")] -[StructLayout(LayoutKind.Sequential)] -public readonly struct ColorBGRA : IColor -{ - #region Properties & Fields - - /// - public static ColorFormat ColorFormat => ColorFormat.BGRA; - - private readonly byte _b; - private readonly byte _g; - private readonly byte _r; - private readonly byte _a; - - // ReSharper disable ConvertToAutoPropertyWhenPossible - /// - public byte B => _b; - - /// - public byte G => _g; - - /// - public byte R => _r; - - /// - public byte A => _a; - // ReSharper restore ConvertToAutoPropertyWhenPossible - -#endregion - - #region Constructors - - /// - /// Initializes a new instance of the class. - /// - /// The blue-component of the color. - /// The green-component of the color. - /// The red-component of the color. - /// The alpha-component of the color. - public ColorBGRA(byte b, byte g, byte r, byte a) - { - this._b = b; - this._g = g; - this._r = r; - this._a = a; - } - - #endregion - - #region Methods - - /// - public override string ToString() => $"[A: {_a}, R: {_r}, G: {_g}, B: {_b}]"; - - #endregion -} \ No newline at end of file diff --git a/StableDiffusion.NET/Helper/Images/Colors/ColorFormat.cs b/StableDiffusion.NET/Helper/Images/Colors/ColorFormat.cs deleted file mode 100644 index 5ef40af..0000000 --- a/StableDiffusion.NET/Helper/Images/Colors/ColorFormat.cs +++ /dev/null @@ -1,58 +0,0 @@ -namespace StableDiffusion.NET.Helper.Images.Colors; - -/// -/// Represents a color format. -/// -public readonly struct ColorFormat -{ - #region Instances - - public static readonly ColorFormat BGRA = new(1, 4); - public static readonly ColorFormat ABGR = new(2, 4); - public static readonly ColorFormat RGBA = new(3, 4); - public static readonly ColorFormat ARGB = new(4, 4); - public static readonly ColorFormat BGR = new(5, 3); - public static readonly ColorFormat RGB = new(6, 3); - - #endregion - - #region Properties & Fields - - /// - /// Gets the Id of the color-format. - /// - public readonly int Id; - - /// - /// Gets the Bytes per pixel for this color-format. - /// - public readonly int BytesPerPixel; - - #endregion - - #region Constructors - - private ColorFormat(int id, int bytesPerPixel) - { - this.Id = id; - this.BytesPerPixel = bytesPerPixel; - } - - #endregion - - #region Methods - - public bool Equals(ColorFormat other) => Id == other.Id; - public override bool Equals(object? obj) => obj is ColorFormat other && Equals(other); - - public override int GetHashCode() => Id; - - #endregion - - #region Operators - - public static bool operator ==(ColorFormat left, ColorFormat right) => left.Equals(right); - public static bool operator !=(ColorFormat left, ColorFormat right) => !(left == right); - - #endregion -} \ No newline at end of file diff --git a/StableDiffusion.NET/Helper/Images/Colors/ColorRGB.cs b/StableDiffusion.NET/Helper/Images/Colors/ColorRGB.cs deleted file mode 100644 index c3db227..0000000 --- a/StableDiffusion.NET/Helper/Images/Colors/ColorRGB.cs +++ /dev/null @@ -1,63 +0,0 @@ -// ReSharper disable ConvertToAutoProperty - -using System.Diagnostics; -using System.Runtime.InteropServices; - -namespace StableDiffusion.NET.Helper.Images.Colors; - -/// -/// Represents a color in 24 bit RGB-format. -/// -[DebuggerDisplay("[A: {A}, R: {R}, G: {G}, B: {B}]")] -[StructLayout(LayoutKind.Sequential)] -public readonly struct ColorRGB : IColor -{ - #region Properties & Fields - - /// - public static ColorFormat ColorFormat => ColorFormat.RGB; - - private readonly byte _r; - private readonly byte _g; - private readonly byte _b; - - // ReSharper disable ConvertToAutoPropertyWhenPossible - /// - public byte A => byte.MaxValue; - - /// - public byte R => _r; - - /// - public byte G => _g; - - /// - public byte B => _b; - // ReSharper restore ConvertToAutoPropertyWhenPossible - - #endregion - - #region Constructors - - /// - /// Initializes a new instance of the class. - /// - /// The red-component of the color. - /// The green-component of the color. - /// The blue-component of the color. - public ColorRGB(byte r, byte g, byte b) - { - this._r = r; - this._g = g; - this._b = b; - } - - #endregion - - #region Methods - - /// - public override string ToString() => $"[A: {A}, R: {_r}, G: {_g}, B: {_b}]"; - - #endregion -} \ No newline at end of file diff --git a/StableDiffusion.NET/Helper/Images/Colors/ColorRGBA.cs b/StableDiffusion.NET/Helper/Images/Colors/ColorRGBA.cs deleted file mode 100644 index 53ab01d..0000000 --- a/StableDiffusion.NET/Helper/Images/Colors/ColorRGBA.cs +++ /dev/null @@ -1,66 +0,0 @@ -// ReSharper disable ConvertToAutoProperty - -using System.Diagnostics; -using System.Runtime.InteropServices; - -namespace StableDiffusion.NET.Helper.Images.Colors; - -/// -/// Represents a color in 32 bit RGBA-format. -/// -[DebuggerDisplay("[A: {A}, R: {R}, G: {G}, B: {B}]")] -[StructLayout(LayoutKind.Sequential)] -public readonly struct ColorRGBA : IColor -{ - #region Properties & Fields - - /// - public static ColorFormat ColorFormat => ColorFormat.RGBA; - - private readonly byte _r; - private readonly byte _g; - private readonly byte _b; - private readonly byte _a; - - // ReSharper disable ConvertToAutoPropertyWhenPossible - /// - public byte R => _r; - - /// - public byte G => _g; - - /// - public byte B => _b; - - /// - public byte A => _a; - // ReSharper restore ConvertToAutoPropertyWhenPossible - - #endregion - - #region Constructors - - /// - /// Initializes a new instance of the class. - /// - /// The red-component of the color. - /// The green-component of the color. - /// The blue-component of the color. - /// The alpha-component of the color. - public ColorRGBA(byte r, byte g, byte b, byte a) - { - this._r = r; - this._g = g; - this._b = b; - this._a = a; - } - - #endregion - - #region Methods - - /// - public override string ToString() => $"[A: {_a}, R: {_r}, G: {_g}, B: {_b}]"; - - #endregion -} \ No newline at end of file diff --git a/StableDiffusion.NET/Helper/Images/Colors/IColor.cs b/StableDiffusion.NET/Helper/Images/Colors/IColor.cs deleted file mode 100644 index b7c1c6c..0000000 --- a/StableDiffusion.NET/Helper/Images/Colors/IColor.cs +++ /dev/null @@ -1,34 +0,0 @@ -using System; - -namespace StableDiffusion.NET.Helper.Images.Colors; - -/// -/// Represents a generic color made of 4 bytes (alpha, red, green and blue) -/// -public interface IColor -{ - /// - /// Gets the red-component of this color. - /// - byte R { get; } - - /// - /// Gets the green-component of this color. - /// - byte G { get; } - - /// - /// Gets the blue-component of this color. - /// - byte B { get; } - - /// - /// Gets the alpha-component of this color. - /// - byte A { get; } - - /// - /// Gets the color-format of this color. - /// - public static virtual ColorFormat ColorFormat => throw new NotSupportedException(); -} \ No newline at end of file diff --git a/StableDiffusion.NET/Helper/Images/IImage.cs b/StableDiffusion.NET/Helper/Images/IImage.cs deleted file mode 100644 index b06aaaf..0000000 --- a/StableDiffusion.NET/Helper/Images/IImage.cs +++ /dev/null @@ -1,193 +0,0 @@ -using System; -using System.Collections.Generic; -using StableDiffusion.NET.Helper.Images.Colors; - -namespace StableDiffusion.NET.Helper.Images; - -/// -/// Represents a image. -/// -public interface IImage : IEnumerable -{ - /// - /// Gets the color format used in this image. - /// - ColorFormat ColorFormat { get; } - - /// - /// Gets the width of this image. - /// - int Width { get; } - - /// - /// Gets the height of this image. - /// - int Height { get; } - - /// - /// Gets the size in bytes of this image. - /// - int SizeInBytes { get; } - - /// - /// Gets the color at the specified location. - /// - /// The X-location to read. - /// The Y-location to read. - /// The color at the specified location. - IColor this[int x, int y] { get; } - - /// - /// Gets an image representing the specified location. - /// - /// The X-location of the image. - /// The Y-location of the image. - /// The width of the sub-image. - /// - /// - IImage this[int x, int y, int width, int height] { get; } - - /// - /// Gets a list of all rows of this image. - /// - IImageRows Rows { get; } - - /// - /// Gets a list of all columns of this image. - /// - IImageColumns Columns { get; } - - /// - /// Gets an representing this . - /// - /// The color-type of the iamge. - /// The . - RefImage AsRefImage() where TColor : struct, IColor; - - /// - /// Copies the contents of this into a destination instance. - /// - /// The destination instance. - /// - /// Thrown when is shorter than the source instance. - /// - void CopyTo(in Span destination); - - /// - /// Allocates a new array and copies this into it. - /// - /// The new array containing the data of this . - byte[] ToArray(); - - /// - /// Represents a list of rows of an image. - /// - public interface IImageRows : IEnumerable - { - /// - /// Gets the amount of rows in this list. - /// - int Count { get; } - - /// - /// Gets a specific . - /// - /// The ´row to get. - /// The requested . - IImageRow this[int column] { get; } - } - - /// - /// Represents a list of columns of an image. - /// - public interface IImageColumns : IEnumerable - { - /// - /// Gets the amount of columns in this list. - /// - int Count { get; } - - /// - /// Gets a specific . - /// - /// The column to get. - /// The requested . - IImageColumn this[int column] { get; } - } - - /// - /// Represents a single row of an image. - /// - public interface IImageRow : IEnumerable - { - /// - /// Gets the length of the row. - /// - int Length { get; } - - /// - /// Gets the size in bytes of this row. - /// - int SizeInBytes { get; } - - /// - /// Gets the at the specified location. - /// - /// The location to get the color from. - /// The at the specified location. - IColor this[int x] { get; } - - /// - /// Copies the contents of this into a destination instance. - /// - /// The destination instance. - /// - /// Thrown when is shorter than the source instance. - /// - void CopyTo(in Span destination); - - /// - /// Allocates a new array and copies this into it. - /// - /// The new array containing the data of this . - byte[] ToArray(); - } - - /// - /// Represents a single column of an image. - /// - public interface IImageColumn : IEnumerable - { - /// - /// Gets the length of the column. - /// - int Length { get; } - - /// - /// Gets the size in bytes of this column. - /// - int SizeInBytes { get; } - - /// - /// Gets the at the specified location. - /// - /// The location to get the color from. - /// The at the specified location. - IColor this[int y] { get; } - - /// - /// Copies the contents of this into a destination instance. - /// - /// The destination instance. - /// - /// Thrown when is shorter than the source instance. - /// - void CopyTo(in Span destination); - - /// - /// Allocates a new array and copies this into it. - /// - /// The new array containing the data of this . - byte[] ToArray(); - } -} \ No newline at end of file diff --git a/StableDiffusion.NET/Helper/Images/Image.cs b/StableDiffusion.NET/Helper/Images/Image.cs deleted file mode 100644 index 3dbea23..0000000 --- a/StableDiffusion.NET/Helper/Images/Image.cs +++ /dev/null @@ -1,431 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using StableDiffusion.NET.Helper.Images.Colors; - -namespace StableDiffusion.NET.Helper.Images; - -/// -public sealed class Image : IImage - where TColor : struct, IColor -{ - #region Properties & Fields - - private readonly byte[] _buffer; - - private readonly int _x; - private readonly int _y; - private readonly int _stride; - - /// - public ColorFormat ColorFormat - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => TColor.ColorFormat; - } - - /// - public int Width { get; } - - /// - public int Height { get; } - - /// - public int SizeInBytes => Width * Height * ColorFormat.BytesPerPixel; - - #endregion - - #region Indexer - - /// - public IColor this[int x, int y] - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - if ((x < 0) || (y < 0) || (x >= Width) || (y >= Height)) throw new IndexOutOfRangeException(); - - return MemoryMarshal.Cast(_buffer)[((_y + y) * _stride) + (_x + x)]; - } - } - - /// - public IImage this[int x, int y, int width, int height] - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - if ((x < 0) || (y < 0) || (width <= 0) || (height <= 0) || ((x + width) > Width) || ((y + height) > Height)) throw new IndexOutOfRangeException(); - - return new Image(_buffer, _x + x, _y + y, width, height, _stride); - } - } - - /// - public IImage.IImageRows Rows - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => new ImageRows(_buffer, _x, _y, Width, Height, _stride); - } - - /// - public IImage.IImageColumns Columns - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => new ImageColumns(_buffer, _x, _y, Width, Height, _stride); - } - - #endregion - - #region Constructors - - public Image(byte[] buffer, int x, int y, int width, int height, int stride) - { - this._buffer = buffer; - this._x = x; - this._y = y; - this.Width = width; - this.Height = height; - this._stride = stride; - } - - #endregion - - #region Methods - - /// - public void CopyTo(in Span destination) - { - if (destination == null) throw new ArgumentNullException(nameof(destination)); - if (destination.Length < SizeInBytes) throw new ArgumentException("The destination is too small to fit this image.", nameof(destination)); - - int targetStride = Width * ColorFormat.BytesPerPixel; - IImage.IImageRows rows = Rows; - Span target = destination; - foreach (IImage.IImageRow row in rows) - { - row.CopyTo(target); - target = target[targetStride..]; - } - } - - /// - public byte[] ToArray() - { - byte[] array = new byte[SizeInBytes]; - CopyTo(array); - return array; - } - - /// - public RefImage AsRefImage() - where T : struct, IColor - { - if (typeof(T) != typeof(TColor)) throw new ArgumentException("The requested color format does not fit this image.", nameof(T)); - - return new RefImage(MemoryMarshal.Cast(_buffer), _x, _y, Width, Height, _stride); - } - - /// - public IEnumerator GetEnumerator() - { - for (int y = 0; y < Height; y++) - for (int x = 0; x < Width; x++) - yield return this[x, y]; - } - - /// - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - #endregion - - #region Indexer-Classes - - /// - private sealed class ImageRows : IImage.IImageRows - { - #region Properties & Fields - - private readonly byte[] _buffer; - private readonly int _x; - private readonly int _y; - private readonly int _width; - private readonly int _height; - private readonly int _stride; - - /// - public int Count => _height; - - #endregion - - #region Indexer - - /// - public IImage.IImageRow this[int row] - { - get - { - if ((row < 0) || (row >= _height)) throw new IndexOutOfRangeException(); - - return new ImageRow(_buffer, (((row + _y) * _stride) + _x), _width); - } - } - - #endregion - - #region Constructors - - internal ImageRows(byte[] buffer, int x, int y, int width, int height, int stride) - { - this._buffer = buffer; - this._x = x; - this._y = y; - this._width = width; - this._height = height; - this._stride = stride; - } - - #endregion - - #region Methods - - /// - public IEnumerator GetEnumerator() - { - for (int y = 0; y < _height; y++) - yield return this[y]; - } - - /// - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - #endregion - } - - /// - private sealed class ImageRow : IImage.IImageRow - { - #region Properties & Fields - - private readonly byte[] _buffer; - private readonly int _start; - private readonly int _length; - - /// - public int Length => _length; - - /// - public int SizeInBytes => Length * TColor.ColorFormat.BytesPerPixel; - - #endregion - - #region Indexer - - /// - public IColor this[int x] - { - get - { - if ((x < 0) || (x >= _length)) throw new IndexOutOfRangeException(); - - ReadOnlySpan row = MemoryMarshal.Cast(_buffer)[_start..]; - return row[x]; - } - } - - #endregion - - #region Constructors - - internal ImageRow(byte[] buffer, int start, int length) - { - this._buffer = buffer; - this._start = start; - this._length = length; - } - - #endregion - - #region Methods - - /// - public void CopyTo(in Span destination) - { - if (destination == null) throw new ArgumentNullException(nameof(destination)); - if (destination.Length < SizeInBytes) throw new ArgumentException("The destination is too small to fit this image.", nameof(destination)); - - MemoryMarshal.Cast(_buffer).Slice(_start, _length).CopyTo(MemoryMarshal.Cast(destination)); - } - - /// - public byte[] ToArray() - { - byte[] array = new byte[SizeInBytes]; - CopyTo(array); - return array; - } - - /// - public IEnumerator GetEnumerator() - { - for (int x = 0; x < _length; x++) - yield return this[x]; - } - - /// - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - #endregion - } - - /// - private sealed class ImageColumns : IImage.IImageColumns - { - #region Properties & Fields - - private readonly byte[] _buffer; - private readonly int _x; - private readonly int _y; - private readonly int _width; - private readonly int _height; - private readonly int _stride; - - /// - public int Count => _width; - - #endregion - - #region Indexer - - /// - public IImage.IImageColumn this[int column] - { - get - { - if ((column < 0) || (column >= _width)) throw new IndexOutOfRangeException(); - - return new ImageColumn(_buffer, (_y * _stride) + _x + column, _height, _stride); - } - } - - #endregion - - #region Constructors - - internal ImageColumns(byte[] buffer, int x, int y, int width, int height, int stride) - { - this._buffer = buffer; - this._x = x; - this._y = y; - this._width = width; - this._height = height; - this._stride = stride; - } - - #endregion - - #region Methods - - /// - public IEnumerator GetEnumerator() - { - for (int y = 0; y < _height; y++) - yield return this[y]; - } - - /// - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - #endregion - } - - /// - private sealed class ImageColumn : IImage.IImageColumn - { - #region Properties & Fields - - private readonly byte[] _buffer; - private readonly int _start; - private readonly int _length; - private readonly int _step; - - /// - public int Length => _length; - - /// - public int SizeInBytes => Length * TColor.ColorFormat.BytesPerPixel; - - #endregion - - #region Indexer - - /// - public IColor this[int y] - { - get - { - if ((y < 0) || (y >= _length)) throw new IndexOutOfRangeException(); - - ReadOnlySpan data = MemoryMarshal.Cast(_buffer)[_start..]; - return data[y * _step]; - } - } - - #endregion - - #region Constructors - - internal ImageColumn(byte[] buffer, int start, int length, int step) - { - this._buffer = buffer; - this._start = start; - this._length = length; - this._step = step; - } - - #endregion - - #region Methods - - /// - public void CopyTo(in Span destination) - { - if (destination == null) throw new ArgumentNullException(nameof(destination)); - if (destination.Length < SizeInBytes) throw new ArgumentException("The destination is too small to fit this image.", nameof(destination)); - - if (_step == 1) - _buffer.AsSpan(_start, SizeInBytes).CopyTo(destination); - else - { - ReadOnlySpan data = MemoryMarshal.Cast(_buffer)[_start..]; - Span target = MemoryMarshal.Cast(destination); - for (int i = 0; i < Length; i++) - target[i] = data[i * _step]; - } - } - - /// - public byte[] ToArray() - { - byte[] array = new byte[SizeInBytes]; - CopyTo(array); - return array; - } - - /// - public IEnumerator GetEnumerator() - { - for (int y = 0; y < _length; y++) - yield return this[y]; - } - - /// - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - #endregion - } - - #endregion -} \ No newline at end of file diff --git a/StableDiffusion.NET/Helper/Images/ReadOnlyRefEnumerable.cs b/StableDiffusion.NET/Helper/Images/ReadOnlyRefEnumerable.cs deleted file mode 100644 index fa57c76..0000000 --- a/StableDiffusion.NET/Helper/Images/ReadOnlyRefEnumerable.cs +++ /dev/null @@ -1,266 +0,0 @@ -// DarthAffe 05.09.2023: Based on https://github.com/CommunityToolkit/dotnet/blob/b0d6c4f9c0cfb5d860400abb00b0ca1b3e94dfa4/src/CommunityToolkit.HighPerformance/Enumerables/ReadOnlyRefEnumerable%7BT%7D.cs - -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace StableDiffusion.NET.Helper.Images; - -/// -/// A that iterates readonly items from arbitrary memory locations. -/// -/// The type of items to enumerate. -public readonly ref struct ReadOnlyRefEnumerable -{ - #region Properties & Fields - - /// - /// The instance pointing to the first item in the target memory area. - /// - /// The field maps to the total available length. - private readonly ReadOnlySpan _span; - - /// - /// The distance between items in the sequence to enumerate. - /// - /// The distance refers to items, not byte offset. - private readonly int _step; - - /// - /// Gets the total available length for the sequence. - /// - public int Length - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => _span.Length; - } - - /// - /// Gets the element at the specified zero-based index. - /// - /// The zero-based index of the element. - /// A reference to the element at the specified index. - /// - /// Thrown when is invalid. - /// - public ref readonly T this[int index] - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - if ((uint)index >= (uint)Length) throw new IndexOutOfRangeException(); - - ref T r0 = ref MemoryMarshal.GetReference(_span); - nint offset = (nint)(uint)index * (nint)(uint)_step; - ref T ri = ref Unsafe.Add(ref r0, offset); - - return ref ri; - } - } - - /// - /// Gets the element at the specified zero-based index. - /// - /// The zero-based index of the element. - /// A reference to the element at the specified index. - /// - /// Thrown when is invalid. - /// - public ref readonly T this[Index index] - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => ref this[index.GetOffset(Length)]; - } - - #endregion - - #region Constructors - - /// - /// Initializes a new instance of the struct. - /// - /// A reference to the first item of the sequence. - /// The number of items in the sequence. - /// The distance between items in the sequence to enumerate. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal ReadOnlyRefEnumerable(in T reference, int length, int step) - { - this._step = step; - - _span = MemoryMarshal.CreateReadOnlySpan(ref Unsafe.AsRef(in reference), length); - } - - #endregion - - #region Methods - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public Enumerator GetEnumerator() => new(_span, _step); - - public T[] ToArray() - { - int length = _span.Length; - - // Empty array if no data is mapped - if (length == 0) - return Array.Empty(); - - T[] array = new T[length]; - CopyTo(array); - - return array; - } - - /// - /// Copies the contents of this into a destination instance. - /// - /// The destination instance. - /// - /// Thrown when is shorter than the source instance. - /// - public void CopyTo(Span destination) - { - if (_step == 1) - { - _span.CopyTo(destination); - return; - } - - ref T sourceRef = ref MemoryMarshal.GetReference(_span); - int length = _span.Length; - if ((uint)destination.Length < (uint)length) - throw new ArgumentException("The target span is too short to copy all the current items to."); - - ref T destinationRef = ref MemoryMarshal.GetReference(destination); - - CopyTo(ref sourceRef, ref destinationRef, (nint)(uint)length, (nint)(uint)_step); - } - - /// - /// Attempts to copy the current instance to a destination . - /// - /// The target of the copy operation. - /// Whether or not the operation was successful. - public bool TryCopyTo(Span destination) - { - if (destination.Length >= _span.Length) - { - CopyTo(destination); - return true; - } - - return false; - } - - private static void CopyTo(ref T sourceRef, ref T destinationRef, nint length, nint sourceStep) - { - nint sourceOffset = 0; - nint destinationOffset = 0; - - while (length >= 8) - { - Unsafe.Add(ref destinationRef, destinationOffset + 0) = Unsafe.Add(ref sourceRef, sourceOffset); - Unsafe.Add(ref destinationRef, destinationOffset + 1) = Unsafe.Add(ref sourceRef, sourceOffset += sourceStep); - Unsafe.Add(ref destinationRef, destinationOffset + 2) = Unsafe.Add(ref sourceRef, sourceOffset += sourceStep); - Unsafe.Add(ref destinationRef, destinationOffset + 3) = Unsafe.Add(ref sourceRef, sourceOffset += sourceStep); - Unsafe.Add(ref destinationRef, destinationOffset + 4) = Unsafe.Add(ref sourceRef, sourceOffset += sourceStep); - Unsafe.Add(ref destinationRef, destinationOffset + 5) = Unsafe.Add(ref sourceRef, sourceOffset += sourceStep); - Unsafe.Add(ref destinationRef, destinationOffset + 6) = Unsafe.Add(ref sourceRef, sourceOffset += sourceStep); - Unsafe.Add(ref destinationRef, destinationOffset + 7) = Unsafe.Add(ref sourceRef, sourceOffset += sourceStep); - - length -= 8; - sourceOffset += sourceStep; - destinationOffset += 8; - } - - if (length >= 4) - { - Unsafe.Add(ref destinationRef, destinationOffset + 0) = Unsafe.Add(ref sourceRef, sourceOffset); - Unsafe.Add(ref destinationRef, destinationOffset + 1) = Unsafe.Add(ref sourceRef, sourceOffset += sourceStep); - Unsafe.Add(ref destinationRef, destinationOffset + 2) = Unsafe.Add(ref sourceRef, sourceOffset += sourceStep); - Unsafe.Add(ref destinationRef, destinationOffset + 3) = Unsafe.Add(ref sourceRef, sourceOffset += sourceStep); - - length -= 4; - sourceOffset += sourceStep; - destinationOffset += 4; - } - - while (length > 0) - { - Unsafe.Add(ref destinationRef, destinationOffset) = Unsafe.Add(ref sourceRef, sourceOffset); - - length -= 1; - sourceOffset += sourceStep; - destinationOffset += 1; - } - } - - #endregion - - /// - /// A custom enumerator type to traverse items within a instance. - /// - public ref struct Enumerator - { - #region Properties & Fields - - /// - private readonly ReadOnlySpan _span; - - /// - private readonly int _step; - - /// - /// The current position in the sequence. - /// - private int _position; - - /// - public readonly ref readonly T Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - ref T r0 = ref MemoryMarshal.GetReference(_span); - - nint offset = (nint)(uint)_position * (nint)(uint)_step; - ref T ri = ref Unsafe.Add(ref r0, offset); - - return ref ri; - } - } - - #endregion - - #region Constructors - - /// - /// Initializes a new instance of the struct. - /// - /// The instance with the info on the items to traverse. - /// The distance between items in the sequence to enumerate. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal Enumerator(ReadOnlySpan span, int step) - { - this._span = span; - this._step = step; - - _position = -1; - } - - #endregion - - #region Methods - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() => ++_position < _span.Length; - - #endregion - } -} diff --git a/StableDiffusion.NET/Helper/Images/RefImage.cs b/StableDiffusion.NET/Helper/Images/RefImage.cs deleted file mode 100644 index 728e262..0000000 --- a/StableDiffusion.NET/Helper/Images/RefImage.cs +++ /dev/null @@ -1,368 +0,0 @@ -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using StableDiffusion.NET.Helper.Images.Colors; - -namespace StableDiffusion.NET.Helper.Images; - -public readonly ref struct RefImage - where TColor : struct, IColor -{ - #region Properties & Fields - - private readonly ReadOnlySpan _pixels; - - private readonly int _x; - private readonly int _y; - - /// - /// Gets the width of the image. - /// - public int Width { get; } - - /// - /// Gets the height of the image. - /// - public int Height { get; } - - /// - /// Gets the stride (entries per row) of the underlying buffer. - /// Only useful if you want to work with a pinned buffer. - /// - public int RawStride { get; } - - #endregion - - #region Indexer - - public ref readonly TColor this[int x, int y] - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - if ((x < 0) || (y < 0) || (x >= Width) || (y >= Height)) throw new IndexOutOfRangeException(); - - ref TColor r0 = ref MemoryMarshal.GetReference(_pixels); - nint offset = (nint)(uint)((_y + y) * RawStride) + (_x + x); - return ref Unsafe.Add(ref r0, offset); - } - } - - public RefImage this[int x, int y, int width, int height] - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - if ((x < 0) || (y < 0) || (width <= 0) || (height <= 0) || ((x + width) > Width) || ((y + height) > Height)) throw new IndexOutOfRangeException(); - - return new RefImage(_pixels, _x + x, _y + y, width, height, RawStride); - } - } - - public ImageRows Rows - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => new(_pixels, _x, _y, Width, Height, RawStride); - } - public ImageColumns Columns - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => new(_pixels, _x, _y, Width, Height, RawStride); - } - - #endregion - - #region Constructors - - public RefImage(ReadOnlySpan pixels, int x, int y, int width, int height, int stride) - { - this._pixels = pixels; - this._x = x; - this._y = y; - this.Width = width; - this.Height = height; - this.RawStride = stride; - } - - #endregion - - #region Methods - - /// - /// Copies the contents of this into a destination instance. - /// - /// The destination instance. - /// - /// Thrown when is shorter than the source instance. - /// - public void CopyTo(in Span destination) - { - if (destination == null) throw new ArgumentNullException(nameof(destination)); - if (destination.Length < (Width * Height)) throw new ArgumentException("The destination is too small to fit this image.", nameof(destination)); - - ImageRows rows = Rows; - Span target = destination; - foreach (ReadOnlyRefEnumerable row in rows) - { - row.CopyTo(target); - target = target[Width..]; - } - } - - /// - /// Allocates a new array and copies this into it. - /// - /// The new array containing the data of this . - public TColor[] ToArray() - { - TColor[] array = new TColor[Width * Height]; - CopyTo(array); - return array; - } - - /// - /// Returns a reference to the first element of this image inside the full image buffer. - /// - public ref readonly TColor GetPinnableReference() - { - if (_pixels.Length == 0) - return ref Unsafe.NullRef(); - - int offset = (_y * RawStride) + _x; - return ref MemoryMarshal.GetReference(_pixels[offset..]); - } - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ImageEnumerator GetEnumerator() => new(_pixels); - - #endregion - - public ref struct ImageEnumerator - { - #region Properties & Fields - - private readonly ReadOnlySpan _pixels; - private int _position; - - /// - public TColor Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => _pixels[_position]; - } - - #endregion - - #region Constructors - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal ImageEnumerator(ReadOnlySpan pixels) - { - this._pixels = pixels; - - _position = -1; - } - - #endregion - - #region Methods - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() => ++_position < _pixels.Length; - - #endregion - } - - #region Indexer-Structs - - public readonly ref struct ImageRows - { - #region Properties & Fields - - private readonly ReadOnlySpan _pixels; - private readonly int _x; - private readonly int _y; - private readonly int _width; - private readonly int _height; - private readonly int _stride; - - public int Count => _height; - - #endregion - - #region Indexer - - public readonly ReadOnlyRefEnumerable this[int row] - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - if ((row < 0) || (row > _height)) throw new IndexOutOfRangeException(); - - ref TColor r0 = ref MemoryMarshal.GetReference(_pixels); - ref TColor rr = ref Unsafe.Add(ref r0, (nint)(uint)(((row + _y) * _stride) + _x)); - - return new ReadOnlyRefEnumerable(rr, _width, 1); - } - } - - #endregion - - #region Constructors - - public ImageRows(ReadOnlySpan pixels, int x, int y, int width, int height, int stride) - { - this._pixels = pixels; - this._x = x; - this._y = y; - this._width = width; - this._height = height; - this._stride = stride; - } - - #endregion - - #region Methods - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ImageRowsEnumerator GetEnumerator() => new(this); - - #endregion - - public ref struct ImageRowsEnumerator - { - #region Properties & Fields - - private readonly ImageRows _rows; - private int _position; - - /// - public ReadOnlyRefEnumerable Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => _rows[_position]; - } - - #endregion - - #region Constructors - - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal ImageRowsEnumerator(ImageRows rows) - { - this._rows = rows; - - _position = -1; - } - - #endregion - - #region Methods - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() => ++_position < _rows._height; - - #endregion - } - } - - public readonly ref struct ImageColumns - { - #region Properties & Fields - - private readonly ReadOnlySpan _pixels; - private readonly int _x; - private readonly int _y; - private readonly int _width; - private readonly int _height; - private readonly int _stride; - - public int Count => _width; - - #endregion - - #region Indexer - - public ReadOnlyRefEnumerable this[int column] - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get - { - if ((column < 0) || (column > _width)) throw new IndexOutOfRangeException(); - - ref TColor r0 = ref MemoryMarshal.GetReference(_pixels); - ref TColor rc = ref Unsafe.Add(ref r0, (nint)(uint)((_y * _stride) + (column + _x))); - - return new ReadOnlyRefEnumerable(rc, _height, _stride); - } - } - - #endregion - - #region Constructors - - public ImageColumns(ReadOnlySpan pixels, int x, int y, int width, int height, int stride) - { - this._pixels = pixels; - this._x = x; - this._y = y; - this._width = width; - this._height = height; - this._stride = stride; - } - - #endregion - - #region Methods - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public ImageColumnsEnumerator GetEnumerator() => new(this); - - #endregion - - public ref struct ImageColumnsEnumerator - { - #region Properties & Fields - - private readonly ImageColumns _columns; - private int _position; - - /// - public ReadOnlyRefEnumerable Current - { - [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => _columns[_position]; - } - - #endregion - - #region Constructors - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal ImageColumnsEnumerator(ImageColumns columns) - { - this._columns = columns; - this._position = -1; - } - - #endregion - - #region Methods - - /// - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public bool MoveNext() => ++_position < _columns._width; - - #endregion - } - } - - #endregion -} \ No newline at end of file diff --git a/StableDiffusion.NET/Helper/ProcessHelper.cs b/StableDiffusion.NET/Helper/ProcessHelper.cs index 938aa73..516f10b 100644 --- a/StableDiffusion.NET/Helper/ProcessHelper.cs +++ b/StableDiffusion.NET/Helper/ProcessHelper.cs @@ -1,6 +1,6 @@ using System.Diagnostics; -namespace StableDiffusion.NET.Helper; +namespace StableDiffusion.NET; internal static class ProcessHelper { diff --git a/StableDiffusion.NET/StableDiffusion.NET.csproj b/StableDiffusion.NET/StableDiffusion.NET.csproj index 5e15481..74a5d5d 100644 --- a/StableDiffusion.NET/StableDiffusion.NET.csproj +++ b/StableDiffusion.NET/StableDiffusion.NET.csproj @@ -55,6 +55,7 @@ - + + diff --git a/StableDiffusion.NET/StableDiffusion.NET.csproj.DotSettings b/StableDiffusion.NET/StableDiffusion.NET.csproj.DotSettings index d4deeb5..13effd6 100644 --- a/StableDiffusion.NET/StableDiffusion.NET.csproj.DotSettings +++ b/StableDiffusion.NET/StableDiffusion.NET.csproj.DotSettings @@ -4,4 +4,5 @@ True True True + True True \ No newline at end of file diff --git a/StableDiffusion.NET/StableDiffusionImage.cs b/StableDiffusion.NET/StableDiffusionImage.cs deleted file mode 100644 index 8aade19..0000000 --- a/StableDiffusion.NET/StableDiffusionImage.cs +++ /dev/null @@ -1,63 +0,0 @@ -using JetBrains.Annotations; -using System; -using System.Runtime.InteropServices; - -namespace StableDiffusion.NET; - -[PublicAPI] -public sealed unsafe class StableDiffusionImage : IDisposable -{ - #region Properties & Fields - - private bool _disposed; - - internal readonly Native.sd_image_t* Image; - - public int Width { get; } - public int Height { get; } - public int Bpp { get; } - public int Stride { get; } - - public ReadOnlySpan Data - { - get - { - ObjectDisposedException.ThrowIf(_disposed, this); - - return new ReadOnlySpan(Image->data, Width * Height * Bpp); - } - } - - #endregion - - #region Constructors - - internal unsafe StableDiffusionImage(Native.sd_image_t* image) - { - this.Image = image; - - Width = (int)image->width; - Height = (int)image->height; - Bpp = (int)image->channel; - Stride = Width * Bpp; - } - - ~StableDiffusionImage() => Dispose(); - - #endregion - - #region Methods - - public void Dispose() - { - if (_disposed) return; - - Marshal.FreeHGlobal((nint)Image->data); - Marshal.FreeHGlobal((nint)Image); - - GC.SuppressFinalize(this); - _disposed = true; - } - - #endregion -} \ No newline at end of file diff --git a/StableDiffusion.NET/StableDiffusionModel.cs b/StableDiffusion.NET/StableDiffusionModel.cs index 5d2f579..a82c3b7 100644 --- a/StableDiffusion.NET/StableDiffusionModel.cs +++ b/StableDiffusion.NET/StableDiffusionModel.cs @@ -1,5 +1,6 @@ using System; using System.Runtime.InteropServices; +using HPPH; using JetBrains.Annotations; namespace StableDiffusion.NET; @@ -90,7 +91,7 @@ private void Initialize() } } - public StableDiffusionImage TextToImage(string prompt, StableDiffusionParameter parameter) + public IImage TextToImage(string prompt, StableDiffusionParameter parameter) { ObjectDisposedException.ThrowIf(_disposed, this); ArgumentNullException.ThrowIfNull(prompt); @@ -100,16 +101,15 @@ public StableDiffusionImage TextToImage(string prompt, StableDiffusionParameter Native.sd_image_t* result; if (parameter.ControlNet.IsEnabled) { - fixed (byte* imagePtr = parameter.ControlNet.Image) + fixed (byte* imagePtr = parameter.ControlNet.Image!.ToRawArray()) { - if (parameter.ControlNet.CannyPreprocess) { Native.sd_image_t controlNetImage = new() { - width = (uint)parameter.Width, - height = (uint)parameter.Height, - channel = 3, + width = (uint)parameter.ControlNet.Image.Width, + height = (uint)parameter.ControlNet.Image.Height, + channel = (uint)parameter.ControlNet.Image.ColorFormat.BytesPerPixel, data = Native.preprocess_canny(imagePtr, parameter.Width, parameter.Height, @@ -143,9 +143,9 @@ public StableDiffusionImage TextToImage(string prompt, StableDiffusionParameter { Native.sd_image_t controlNetImage = new() { - width = (uint)parameter.Width, - height = (uint)parameter.Height, - channel = 3, + width = (uint)parameter.ControlNet.Image.Width, + height = (uint)parameter.ControlNet.Image.Height, + channel = (uint)parameter.ControlNet.Image.ColorFormat.BytesPerPixel, data = imagePtr }; @@ -188,34 +188,21 @@ public StableDiffusionImage TextToImage(string prompt, StableDiffusionParameter parameter.PhotoMaker.InputIdImageDirectory); } - return new StableDiffusionImage(result); + return ImageHelper.ToImage(result); } - public StableDiffusionImage ImageToImage(string prompt, in ReadOnlySpan image, StableDiffusionParameter parameter) + public IImage ImageToImage(string prompt, IImage image, StableDiffusionParameter parameter) { ObjectDisposedException.ThrowIf(_disposed, this); ArgumentNullException.ThrowIfNull(prompt); parameter.Validate(); - fixed (byte* imagePtr = image) - { - Native.sd_image_t img = new() - { - width = (uint)parameter.Width, - height = (uint)parameter.Height, - channel = 3, - data = imagePtr - }; - - return ImageToImage(prompt, img, parameter); - } + fixed (byte* imagePtr = image.AsRefImage()) + return ImageToImage(prompt, image.ToSdImage(imagePtr), parameter); } - public StableDiffusionImage ImageToImage(string prompt, StableDiffusionImage image, StableDiffusionParameter parameter) - => ImageToImage(prompt, *image.Image, parameter); - - private StableDiffusionImage ImageToImage(string prompt, Native.sd_image_t image, StableDiffusionParameter parameter) + private IImage ImageToImage(string prompt, Native.sd_image_t image, StableDiffusionParameter parameter) { ObjectDisposedException.ThrowIf(_disposed, this); ArgumentNullException.ThrowIfNull(prompt); @@ -225,16 +212,15 @@ private StableDiffusionImage ImageToImage(string prompt, Native.sd_image_t image Native.sd_image_t* result; if (parameter.ControlNet.IsEnabled) { - fixed (byte* imagePtr = parameter.ControlNet.Image) + fixed (byte* imagePtr = parameter.ControlNet.Image!.ToRawArray()) { - if (parameter.ControlNet.CannyPreprocess) { Native.sd_image_t controlNetImage = new() { - width = (uint)parameter.Width, - height = (uint)parameter.Height, - channel = 3, + width = (uint)parameter.ControlNet.Image.Width, + height = (uint)parameter.ControlNet.Image.Height, + channel = (uint)parameter.ControlNet.Image.ColorFormat.BytesPerPixel, data = Native.preprocess_canny(imagePtr, parameter.Width, parameter.Height, @@ -270,9 +256,9 @@ private StableDiffusionImage ImageToImage(string prompt, Native.sd_image_t image { Native.sd_image_t controlNetImage = new() { - width = (uint)parameter.Width, - height = (uint)parameter.Height, - channel = 3, + width = (uint)parameter.ControlNet.Image.Width, + height = (uint)parameter.ControlNet.Image.Height, + channel = (uint)parameter.ControlNet.Image.ColorFormat.BytesPerPixel, data = imagePtr }; @@ -319,46 +305,27 @@ private StableDiffusionImage ImageToImage(string prompt, Native.sd_image_t image parameter.PhotoMaker.InputIdImageDirectory); } - return new StableDiffusionImage(result); + return ImageHelper.ToImage(result); } - public StableDiffusionImage Upscale(StableDiffusionImage image, int upscaleFactor) + public IImage Upscale(IImage image, int upscaleFactor) { ObjectDisposedException.ThrowIf(_disposed, this); ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(upscaleFactor, 0, nameof(upscaleFactor)); if (_upscalerCtx == null) throw new NullReferenceException("The upscaler is not initialized."); - return Upscale(*image.Image, upscaleFactor); - } - - public StableDiffusionImage Upscale(in ReadOnlySpan image, int width, int height, int upscaleFactor) - { - ObjectDisposedException.ThrowIf(_disposed, this); - ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(upscaleFactor, 0, nameof(upscaleFactor)); - ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(width, 0, nameof(upscaleFactor)); - ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(height, 0, nameof(upscaleFactor)); - - if (_upscalerCtx == null) throw new NullReferenceException("The upscaler is not initialized."); - - fixed (byte* imagePtr = image) + fixed (byte* imagePtr = image.ConvertTo().AsRefImage()) { - Native.sd_image_t srcImage = new() - { - width = (uint)width, - height = (uint)height, - channel = 3, - data = imagePtr - }; - - return Upscale(srcImage, upscaleFactor); + Native.sd_image_t result = Native.upscale(_upscalerCtx, image.ToSdImage(imagePtr), upscaleFactor); + return ImageHelper.ToImage(&result); } } - private StableDiffusionImage Upscale(Native.sd_image_t image, int upscaleFactor) + private IImage Upscale(Native.sd_image_t image, int upscaleFactor) { Native.sd_image_t result = Native.upscale(_upscalerCtx, image, upscaleFactor); - return new StableDiffusionImage(&result); + return ImageHelper.ToImage(&result); } public void Dispose() diff --git a/StableDiffusion.NET/StableDiffusionParameter.cs b/StableDiffusion.NET/StableDiffusionParameter.cs index 032b087..4fc8b50 100644 --- a/StableDiffusion.NET/StableDiffusionParameter.cs +++ b/StableDiffusion.NET/StableDiffusionParameter.cs @@ -1,4 +1,5 @@ -using JetBrains.Annotations; +using HPPH; +using JetBrains.Annotations; namespace StableDiffusion.NET; @@ -26,9 +27,9 @@ public sealed class StableDiffusionParameter [PublicAPI] public sealed class StableDiffusionControlNetParameter { - public bool IsEnabled => Image?.Length > 0; + public bool IsEnabled => Image != null; - public byte[]? Image { get; set; } = null; + public IImage? Image { get; set; } = null; public float Strength { get; set; } = 0.9f; public bool CannyPreprocess { get; set; } = false; public float CannyHighThreshold { get; set; } = 0.08f;