mirror of
https://github.com/DarthAffe/StableDiffusion.NET.git
synced 2025-12-12 13:28:35 +00:00
Merge pull request #60 from DarthAffe/APIRework
Reworked everything to fit the new sd.cpp API
This commit is contained in:
commit
a2827a082d
99
.github/workflows/backends.yml
vendored
99
.github/workflows/backends.yml
vendored
@ -111,65 +111,6 @@ jobs:
|
||||
name: windows-cuda12
|
||||
path: .\build\bin\Release\stable-diffusion.dll
|
||||
|
||||
windows-cuda11:
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
id: checkout
|
||||
uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
repository: 'leejet/stable-diffusion.cpp'
|
||||
ref: '${{ github.event.inputs.commit }}'
|
||||
submodules: recursive
|
||||
|
||||
- name: Install Cuda Toolkit 11.8
|
||||
id: cuda-11
|
||||
run: |
|
||||
mkdir -p "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8"
|
||||
choco install unzip -y
|
||||
curl -O "https://developer.download.nvidia.com/compute/cuda/redist/cuda_cudart/windows-x86_64/cuda_cudart-windows-x86_64-11.8.89-archive.zip"
|
||||
curl -O "https://developer.download.nvidia.com/compute/cuda/redist/cuda_nvcc/windows-x86_64/cuda_nvcc-windows-x86_64-11.8.89-archive.zip"
|
||||
curl -O "https://developer.download.nvidia.com/compute/cuda/redist/cuda_nvrtc/windows-x86_64/cuda_nvrtc-windows-x86_64-11.8.89-archive.zip"
|
||||
curl -O "https://developer.download.nvidia.com/compute/cuda/redist/libcublas/windows-x86_64/libcublas-windows-x86_64-11.8.1.74-archive.zip"
|
||||
curl -O "https://developer.download.nvidia.com/compute/cuda/redist/cuda_nvtx/windows-x86_64/cuda_nvtx-windows-x86_64-11.8.86-archive.zip"
|
||||
curl -O "https://developer.download.nvidia.com/compute/cuda/redist/cuda_profiler_api/windows-x86_64/cuda_profiler_api-windows-x86_64-11.8.86-archive.zip"
|
||||
curl -O "https://developer.download.nvidia.com/compute/cuda/redist/visual_studio_integration/windows-x86_64/visual_studio_integration-windows-x86_64-11.8.86-archive.zip"
|
||||
curl -O "https://developer.download.nvidia.com/compute/cuda/redist/cuda_nvprof/windows-x86_64/cuda_nvprof-windows-x86_64-11.8.87-archive.zip"
|
||||
curl -O "https://developer.download.nvidia.com/compute/cuda/redist/cuda_cccl/windows-x86_64/cuda_cccl-windows-x86_64-11.8.89-archive.zip"
|
||||
unzip '*.zip' -d "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8"
|
||||
xcopy "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8\cuda_cudart-windows-x86_64-11.8.89-archive\*" "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8" /E /I /H /Y
|
||||
xcopy "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8\cuda_nvcc-windows-x86_64-11.8.89-archive\*" "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8" /E /I /H /Y
|
||||
xcopy "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8\cuda_nvrtc-windows-x86_64-11.8.89-archive\*" "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8" /E /I /H /Y
|
||||
xcopy "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8\libcublas-windows-x86_64-11.8.1.74-archive\*" "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8" /E /I /H /Y
|
||||
xcopy "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8\cuda_nvtx-windows-x86_64-11.8.86-archive\*" "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8" /E /I /H /Y
|
||||
xcopy "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8\cuda_profiler_api-windows-x86_64-11.8.86-archive\*" "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8" /E /I /H /Y
|
||||
xcopy "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8\visual_studio_integration-windows-x86_64-11.8.86-archive\*" "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8" /E /I /H /Y
|
||||
xcopy "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8\cuda_nvprof-windows-x86_64-11.8.87-archive\*" "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8" /E /I /H /Y
|
||||
xcopy "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8\cuda_cccl-windows-x86_64-11.8.89-archive\*" "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8" /E /I /H /Y
|
||||
xcopy "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8\visual_studio_integration\MSBuildExtensions\*" "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Microsoft\VC\v170\BuildCustomizations" /E /I /H /Y
|
||||
echo "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
||||
echo "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8\libnvvp" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
||||
echo "CUDA_PATH=C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
|
||||
echo "CUDA_PATH_V11_8=C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v11.8" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8
|
||||
|
||||
- name: Build
|
||||
id: cmake_build
|
||||
shell: cmd
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvars64.bat"
|
||||
cmake .. -DSD_CUDA=ON -DCMAKE_CUDA_ARCHITECTURES="61;75;86;89" -DSD_BUILD_SHARED_LIBS=ON -DCMAKE_CUDA_FLAGS="-allow-unsupported-compiler"
|
||||
cmake --build . --config Release
|
||||
|
||||
- name: Upload artifact
|
||||
id: upload_artifact
|
||||
uses: actions/upload-artifact@v4.6.1
|
||||
with:
|
||||
name: windows-cuda11
|
||||
path: .\build\bin\Release\stable-diffusion.dll
|
||||
|
||||
windows-sycl:
|
||||
runs-on: windows-latest
|
||||
|
||||
@ -371,41 +312,6 @@ jobs:
|
||||
name: linux-cuda12
|
||||
path: ./build/bin/libstable-diffusion.so
|
||||
|
||||
linux-cuda11:
|
||||
runs-on: ubuntu-latest
|
||||
container: nvidia/cuda:11.8.0-devel-ubuntu22.04
|
||||
|
||||
steps:
|
||||
- name: Install dependencies
|
||||
env:
|
||||
DEBIAN_FRONTEND: noninteractive
|
||||
run: |
|
||||
apt update
|
||||
apt install -y cmake build-essential ninja-build libgomp1 git
|
||||
|
||||
- name: Checkout
|
||||
id: checkout
|
||||
uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
repository: 'leejet/stable-diffusion.cpp'
|
||||
ref: '${{ github.event.inputs.commit }}'
|
||||
submodules: recursive
|
||||
|
||||
- name: Build
|
||||
id: cmake_build
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DSD_CUDA=ON -DCMAKE_CUDA_ARCHITECTURES="61;75;86;89" -DSD_BUILD_SHARED_LIBS=ON
|
||||
cmake --build . --config Release
|
||||
|
||||
- name: Upload artifact
|
||||
id: upload_artifact
|
||||
uses: actions/upload-artifact@v4.6.1
|
||||
with:
|
||||
name: linux-cuda11
|
||||
path: ./build/bin/libstable-diffusion.so
|
||||
|
||||
linux-sycl:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@ -526,13 +432,11 @@ jobs:
|
||||
needs:
|
||||
- windows-cpu
|
||||
- windows-cuda12
|
||||
# - windows-cuda11
|
||||
# - windows-sycl
|
||||
- windows-hip
|
||||
- windows-vulkan
|
||||
- linux-cpu
|
||||
- linux-cuda12
|
||||
- linux-cuda11
|
||||
- linux-sycl
|
||||
- linux-hip
|
||||
- osx-cpu
|
||||
@ -559,13 +463,10 @@ jobs:
|
||||
id: pack
|
||||
run: |
|
||||
nuget pack ./Backends/StableDiffusion.NET.Backend.Cpu.nuspec -version ${{ github.event.inputs.version }}
|
||||
nuget pack ./Backends/StableDiffusion.NET.Backend.Cuda11.Windows.nuspec -version ${{ github.event.inputs.version }}
|
||||
nuget pack ./Backends/StableDiffusion.NET.Backend.Cuda12.Windows.nuspec -version ${{ github.event.inputs.version }}
|
||||
nuget pack ./Backends/StableDiffusion.NET.Backend.Cuda11.Linux.nuspec -version ${{ github.event.inputs.version }}
|
||||
nuget pack ./Backends/StableDiffusion.NET.Backend.Cuda12.Linux.nuspec -version ${{ github.event.inputs.version }}
|
||||
nuget pack ./Backends/StableDiffusion.NET.Backend.Cuda.nuspec -version ${{ github.event.inputs.version }}
|
||||
nuget pack ./Backends/StableDiffusion.NET.Backend.Rocm.nuspec -version ${{ github.event.inputs.version }}
|
||||
nuget pack ./Backends/StableDiffusion.NET.Backend.Sycl.nuspec -version ${{ github.event.inputs.version }}
|
||||
nuget pack ./Backends/StableDiffusion.NET.Backend.Vulkan.nuspec -version ${{ github.event.inputs.version }}
|
||||
|
||||
- name: Upload artifacts
|
||||
|
||||
@ -9,15 +9,13 @@
|
||||
<license type="expression">MIT</license>
|
||||
<icon>sd_net_cuda.png</icon>
|
||||
<projectUrl>https://github.com/DarthAffe/StableDiffusion.NET</projectUrl>
|
||||
<description>CUDA-Backend (11 and 12) for StableDiffusion.NET.</description>
|
||||
<description>CUDA-Backend (12) for StableDiffusion.NET.</description>
|
||||
<releaseNotes></releaseNotes>
|
||||
<copyright>Copyright © Darth Affe 2024</copyright>
|
||||
<readme>readme.md</readme>
|
||||
|
||||
<dependencies>
|
||||
<dependency id="StableDiffusion.NET.Backend.Cuda11.Windows" version="$version$" />
|
||||
<dependency id="StableDiffusion.NET.Backend.Cuda12.Windows" version="$version$" />
|
||||
<dependency id="StableDiffusion.NET.Backend.Cuda11.Linux" version="$version$" />
|
||||
<dependency id="StableDiffusion.NET.Backend.Cuda12.Linux" version="$version$" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
|
||||
@ -1,28 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<package>
|
||||
<metadata>
|
||||
<id>StableDiffusion.NET.Backend.Cuda11.Linux</id>
|
||||
<version>$version$</version>
|
||||
<title>StableDiffusion.NET.Backend.Cuda11.Linux</title>
|
||||
<authors>Darth Affe & stable-diffusion.cpp Authors</authors>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<license type="expression">MIT</license>
|
||||
<icon>sd_net_cuda.png</icon>
|
||||
<projectUrl>https://github.com/DarthAffe/StableDiffusion.NET</projectUrl>
|
||||
<description>CUDA 11 Linux Backend for StableDiffusion.NET.</description>
|
||||
<releaseNotes></releaseNotes>
|
||||
<copyright>Copyright © Darth Affe 2024</copyright>
|
||||
<readme>readme.md</readme>
|
||||
</metadata>
|
||||
|
||||
<files>
|
||||
<file src="StableDiffusion.NET.Backend.props" target="build/net8.0/StableDiffusion.NET.Backend.Cuda.props" />
|
||||
|
||||
<file src="linux-cuda11/libstable-diffusion.so" target="runtimes\linux-x64\native\cuda11\libstable-diffusion.so" />
|
||||
|
||||
<file src="sd_net_cuda.png" target="sd_net_cuda.png" />
|
||||
<file src="readme.md" target="readme.md" />
|
||||
<file src="ggml.txt" target="ggml.txt" />
|
||||
<file src="stable-diffusion.cpp.txt" target="stable-diffusion.cpp.txt" />
|
||||
</files>
|
||||
</package>
|
||||
@ -1,28 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<package>
|
||||
<metadata>
|
||||
<id>StableDiffusion.NET.Backend.Cuda11.Windows</id>
|
||||
<version>$version$</version>
|
||||
<title>StableDiffusion.NET.Backend.Cuda11.Windows</title>
|
||||
<authors>Darth Affe & stable-diffusion.cpp Authors</authors>
|
||||
<requireLicenseAcceptance>false</requireLicenseAcceptance>
|
||||
<license type="expression">MIT</license>
|
||||
<icon>sd_net_cuda.png</icon>
|
||||
<projectUrl>https://github.com/DarthAffe/StableDiffusion.NET</projectUrl>
|
||||
<description>CUDA 11 Windows Backend for StableDiffusion.NET.</description>
|
||||
<releaseNotes></releaseNotes>
|
||||
<copyright>Copyright © Darth Affe 2024</copyright>
|
||||
<readme>readme.md</readme>
|
||||
</metadata>
|
||||
|
||||
<files>
|
||||
<file src="StableDiffusion.NET.Backend.props" target="build/net8.0/StableDiffusion.NET.Backend.Cuda.props" />
|
||||
|
||||
<file src="windows-cuda11/stable-diffusion.dll" target="runtimes\win-x64\native\cuda11\stable-diffusion.dll" />
|
||||
|
||||
<file src="sd_net_cuda.png" target="sd_net_cuda.png" />
|
||||
<file src="readme.md" target="readme.md" />
|
||||
<file src="ggml.txt" target="ggml.txt" />
|
||||
<file src="stable-diffusion.cpp.txt" target="stable-diffusion.cpp.txt" />
|
||||
</files>
|
||||
</package>
|
||||
@ -1,42 +0,0 @@
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace ImageCreationUI;
|
||||
|
||||
public class ActionCommand(Action command, Func<bool>? canExecute = null) : ICommand
|
||||
{
|
||||
#region Events
|
||||
|
||||
public event EventHandler? CanExecuteChanged;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public bool CanExecute(object? parameter) => canExecute?.Invoke() ?? true;
|
||||
|
||||
public void Execute(object? parameter) => command.Invoke();
|
||||
|
||||
public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public class ActionCommand<T>(Action<T> command, Func<T, bool>? canExecute = null) : ICommand
|
||||
where T : class
|
||||
{
|
||||
#region Events
|
||||
|
||||
public event EventHandler? CanExecuteChanged;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public bool CanExecute(object? parameter) => canExecute?.Invoke((T)parameter!) ?? true;
|
||||
|
||||
public void Execute(object? parameter) => command.Invoke((T)parameter!);
|
||||
|
||||
public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
|
||||
|
||||
#endregion
|
||||
}
|
||||
@ -1,4 +0,0 @@
|
||||
<Application x:Class="ImageCreationUI.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
StartupUri="MainWindow.xaml" />
|
||||
@ -1,5 +0,0 @@
|
||||
using System.Windows;
|
||||
|
||||
namespace ImageCreationUI;
|
||||
|
||||
public partial class App : Application;
|
||||
@ -1,34 +0,0 @@
|
||||
using System.Drawing;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using HPPH;
|
||||
using HPPH.System.Drawing;
|
||||
|
||||
namespace ImageCreationUI.Converter;
|
||||
|
||||
[ValueConversion(typeof(IImage), typeof(ImageSource))]
|
||||
public class ImageToImageSourceConverter : IValueConverter
|
||||
{
|
||||
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
{
|
||||
using Bitmap? bitmap = (value as IImage)?.ToBitmap();
|
||||
if (bitmap == null) return null;
|
||||
|
||||
using MemoryStream ms = new();
|
||||
bitmap.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
|
||||
ms.Position = 0;
|
||||
|
||||
BitmapImage bitmapImage = new();
|
||||
bitmapImage.BeginInit();
|
||||
bitmapImage.StreamSource = ms;
|
||||
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
|
||||
bitmapImage.EndInit();
|
||||
|
||||
return bitmapImage;
|
||||
}
|
||||
|
||||
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) => throw new NotSupportedException();
|
||||
}
|
||||
@ -1,23 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net9.0-windows</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<UseWPF>true</UseWPF>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="HPPH.System.Drawing" Version="1.0.0" />
|
||||
<PackageReference Include="StableDiffusion.NET.Backend.Cpu" Version="3.4.1" />
|
||||
<PackageReference Include="StableDiffusion.NET.Backend.Cuda" Version="3.4.1" />
|
||||
<PackageReference Include="StableDiffusion.NET.Backend.Rocm" Version="3.4.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\StableDiffusion.NET\StableDiffusion.NET.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@ -1,2 +0,0 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=extensions/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||
@ -1,165 +0,0 @@
|
||||
<Window x:Class="ImageCreationUI.MainWindow"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:ImageCreationUI"
|
||||
xmlns:converter="clr-namespace:ImageCreationUI.Converter"
|
||||
xmlns:sys="clr-namespace:System;assembly=System.Runtime"
|
||||
xmlns:sd="clr-namespace:StableDiffusion.NET;assembly=StableDiffusion.NET"
|
||||
mc:Ignorable="d"
|
||||
Title="StableDiffusion.NET" Width="1706" Height="960">
|
||||
<Window.DataContext>
|
||||
<local:MainWindowViewModel />
|
||||
</Window.DataContext>
|
||||
|
||||
<Window.Resources>
|
||||
<converter:ImageToImageSourceConverter x:Key="ImageToImageSourceConverter" />
|
||||
|
||||
<ObjectDataProvider x:Key="ScheduleDataSource"
|
||||
ObjectType="{x:Type sys:Enum}"
|
||||
MethodName="GetValues">
|
||||
<ObjectDataProvider.MethodParameters>
|
||||
<x:Type TypeName="sd:Schedule" />
|
||||
</ObjectDataProvider.MethodParameters>
|
||||
</ObjectDataProvider>
|
||||
|
||||
<ObjectDataProvider x:Key="SamplerDataSource"
|
||||
ObjectType="{x:Type sys:Enum}"
|
||||
MethodName="GetValues">
|
||||
<ObjectDataProvider.MethodParameters>
|
||||
<x:Type TypeName="sd:Sampler" />
|
||||
</ObjectDataProvider.MethodParameters>
|
||||
</ObjectDataProvider>
|
||||
</Window.Resources>
|
||||
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="400" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="400" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
|
||||
<StackPanel Margin="4,0" Orientation="Vertical">
|
||||
<TextBlock Margin="8" Text="This is just an example - inputs are not validated! Make sure everything is correct before pressing 'Create Image'." />
|
||||
|
||||
<Separator />
|
||||
|
||||
<Label Content="Model-Type" />
|
||||
<StackPanel Orientation="Horizontal" Margin="4,0,0,0">
|
||||
<RadioButton Content="Stable Diffusion" IsChecked="{Binding IsStableDiffusionSelected}" GroupName="ModelType" />
|
||||
<RadioButton Margin="16,0,0,0" Content="Flux" IsChecked="{Binding IsFluxSelected}" GroupName="ModelType" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Orientation="Vertical" IsEnabled="{Binding IsStableDiffusionSelected}">
|
||||
<Label Content="Model-Path" />
|
||||
<DockPanel>
|
||||
<Button DockPanel.Dock="Right" Width="24" Margin="2,0,0,0" Content="..." Command="{Binding SelectModelCommand}" IsEnabled="{Binding IsReady}" />
|
||||
<TextBox Text="{Binding ModelPath}" />
|
||||
</DockPanel>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Orientation="Vertical" IsEnabled="{Binding IsFluxSelected}">
|
||||
<Label Content="DiffusionModel-Path" />
|
||||
<DockPanel>
|
||||
<Button DockPanel.Dock="Right" Width="24" Margin="2,0,0,0" Content="..." Command="{Binding SelectDiffusionModelCommand}" IsEnabled="{Binding IsReady}" />
|
||||
<TextBox Text="{Binding DiffusionModelPath}" />
|
||||
</DockPanel>
|
||||
|
||||
<Label Content="ClipL-Path" />
|
||||
<DockPanel>
|
||||
<Button DockPanel.Dock="Right" Width="24" Margin="2,0,0,0" Content="..." Command="{Binding SelectClipLCommand}" IsEnabled="{Binding IsReady}" />
|
||||
<TextBox Text="{Binding ClipLPath}" />
|
||||
</DockPanel>
|
||||
|
||||
<Label Content="T5xxl-Path" />
|
||||
<DockPanel>
|
||||
<Button DockPanel.Dock="Right" Width="24" Margin="2,0,0,0" Content="..." Command="{Binding SelectT5xxlCommand}" IsEnabled="{Binding IsReady}" />
|
||||
<TextBox Text="{Binding T5xxlPath}" />
|
||||
</DockPanel>
|
||||
</StackPanel>
|
||||
|
||||
<Label Content="Vae-Path (Optional)" />
|
||||
<DockPanel>
|
||||
<Button DockPanel.Dock="Right" Width="24" Margin="2,0,0,0" Content="..." Command="{Binding SelectVaeCommand}" IsEnabled="{Binding IsReady}" />
|
||||
<TextBox Text="{Binding VaePath}" />
|
||||
</DockPanel>
|
||||
|
||||
<Label Content="Schedule" />
|
||||
<ComboBox ItemsSource="{Binding Source={StaticResource ScheduleDataSource}}" SelectedItem="{Binding Schedule}" />
|
||||
|
||||
<StackPanel Orientation="Horizontal" Margin="0,4,0,0">
|
||||
<Label Content="Flash Attention" />
|
||||
<CheckBox VerticalAlignment="Center" IsChecked="{Binding FlashAttention}" />
|
||||
</StackPanel>
|
||||
|
||||
<Button Margin="0,8" Content="Load Model" Command="{Binding LoadModelCommand}" IsEnabled="{Binding IsReady}" />
|
||||
|
||||
<Separator />
|
||||
|
||||
<Label Margin="0,8,0,0" Content="Prompt" />
|
||||
<TextBox Height="80" TextWrapping="Wrap" Text="{Binding Prompt}" />
|
||||
|
||||
<Label Content="AntiPrompt" />
|
||||
<TextBox Height="60" TextWrapping="Wrap" Text="{Binding AntiPrompt}" />
|
||||
|
||||
<DockPanel LastChildFill="True">
|
||||
<StackPanel DockPanel.Dock="Left">
|
||||
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="0,8,0,0">
|
||||
<Label Width="50" Content="Width" />
|
||||
<TextBox HorizontalAlignment="Left" Width="60" Text="{Binding Width}" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="0,8,0,0">
|
||||
<Label Width="50" Content="Height" />
|
||||
<TextBox HorizontalAlignment="Left" Width="60" Text="{Binding Height}" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="0,8,0,0">
|
||||
<Label Width="50" Content="Cfg" />
|
||||
<TextBox HorizontalAlignment="Left" Width="60" Text="{Binding Cfg}" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="0,8,0,0">
|
||||
<Label Width="50" Content="Steps" />
|
||||
<TextBox HorizontalAlignment="Left" Width="60" Text="{Binding Steps}" />
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal" Margin="0,8,0,0">
|
||||
<Label Width="50" Content="Seed" />
|
||||
<TextBox HorizontalAlignment="Left" Width="60" Text="{Binding Seed}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<DockPanel Margin="16,0,0,0" LastChildFill="True">
|
||||
<Label DockPanel.Dock="Top" Content="Image2Image Source" />
|
||||
<DockPanel DockPanel.Dock="Top" >
|
||||
<Button DockPanel.Dock="Right" Width="24" Margin="2,0,0,0" Content="..." Command="{Binding SelectImage2ImageSourceCommand}" IsEnabled="{Binding IsReady}" />
|
||||
<TextBox Text="{Binding Image2ImageSourcePath}" />
|
||||
</DockPanel>
|
||||
|
||||
<Image Source="{Binding Image2ImageSource, Converter={StaticResource ImageToImageSourceConverter}}" />
|
||||
</DockPanel>
|
||||
</DockPanel>
|
||||
|
||||
<Label Content="Sample-Method" />
|
||||
<ComboBox ItemsSource="{Binding Source={StaticResource SamplerDataSource}}" SelectedItem="{Binding SampleMethod}" />
|
||||
|
||||
<Button Margin="0,16,0,0" Content="Create Image" Command="{Binding CreateImageCommand}" IsEnabled="{Binding IsReady}" />
|
||||
<Button Margin="0,16,0,0" Content="Save Image" Command="{Binding SaveImageCommand}" IsEnabled="{Binding IsReady}" />
|
||||
</StackPanel>
|
||||
|
||||
</ScrollViewer>
|
||||
|
||||
<GridSplitter Grid.Column="1" Margin="2,0" Width="2" Background="DimGray" VerticalAlignment="Stretch" HorizontalAlignment="Center" />
|
||||
|
||||
<Image Grid.Column="2" Source="{Binding Image, Converter={StaticResource ImageToImageSourceConverter}}" />
|
||||
|
||||
<GridSplitter Grid.Column="3" Margin="2,0" Width="2" Background="DimGray" VerticalAlignment="Stretch" HorizontalAlignment="Center" />
|
||||
|
||||
<TextBox Grid.Column="4" IsReadOnly="True" BorderThickness="0" AcceptsReturn="True" Text="{Binding Log}" TextChanged="TextBoxBase_OnTextChanged" />
|
||||
</Grid>
|
||||
</Window>
|
||||
@ -1,11 +0,0 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace ImageCreationUI;
|
||||
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
public MainWindow() => InitializeComponent();
|
||||
|
||||
private void TextBoxBase_OnTextChanged(object sender, TextChangedEventArgs args) => (sender as TextBox)?.ScrollToEnd();
|
||||
}
|
||||
@ -1,422 +0,0 @@
|
||||
using System.ComponentModel;
|
||||
using System.Drawing.Imaging;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using HPPH;
|
||||
using HPPH.System.Drawing;
|
||||
using Microsoft.Win32;
|
||||
using StableDiffusion.NET;
|
||||
|
||||
namespace ImageCreationUI;
|
||||
|
||||
public class MainWindowViewModel : INotifyPropertyChanged
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
private DiffusionModel? _model;
|
||||
|
||||
private bool _isStableDiffusionSelected = true;
|
||||
public bool IsStableDiffusionSelected
|
||||
{
|
||||
get => _isStableDiffusionSelected;
|
||||
set => SetProperty(ref _isStableDiffusionSelected, value);
|
||||
}
|
||||
|
||||
private bool _isFluxSelected;
|
||||
public bool IsFluxSelected
|
||||
{
|
||||
get => _isFluxSelected;
|
||||
set => SetProperty(ref _isFluxSelected, value);
|
||||
}
|
||||
|
||||
private string _modelPath = string.Empty;
|
||||
public string ModelPath
|
||||
{
|
||||
get => _modelPath;
|
||||
set => SetProperty(ref _modelPath, value);
|
||||
}
|
||||
|
||||
private string _clipLPath;
|
||||
public string ClipLPath
|
||||
{
|
||||
get => _clipLPath;
|
||||
set => SetProperty(ref _clipLPath, value);
|
||||
}
|
||||
|
||||
private string _t5xxlPath;
|
||||
public string T5xxlPath
|
||||
{
|
||||
get => _t5xxlPath;
|
||||
set => SetProperty(ref _t5xxlPath, value);
|
||||
}
|
||||
|
||||
private string _diffusionModelPath;
|
||||
public string DiffusionModelPath
|
||||
{
|
||||
get => _diffusionModelPath;
|
||||
set => SetProperty(ref _diffusionModelPath, value);
|
||||
}
|
||||
|
||||
private string _vaePath = string.Empty;
|
||||
public string VaePath
|
||||
{
|
||||
get => _vaePath;
|
||||
set => SetProperty(ref _vaePath, value);
|
||||
}
|
||||
|
||||
private Schedule _schedule = Schedule.Default;
|
||||
public Schedule Schedule
|
||||
{
|
||||
get => _schedule;
|
||||
set => SetProperty(ref _schedule, value);
|
||||
}
|
||||
|
||||
private bool _flashAttention = true;
|
||||
public bool FlashAttention
|
||||
{
|
||||
get => _flashAttention;
|
||||
set => SetProperty(ref _flashAttention, value);
|
||||
}
|
||||
|
||||
private string _prompt = string.Empty;
|
||||
public string Prompt
|
||||
{
|
||||
get => _prompt;
|
||||
set => SetProperty(ref _prompt, value);
|
||||
}
|
||||
|
||||
private string _antiPrompt = string.Empty;
|
||||
public string AntiPrompt
|
||||
{
|
||||
get => _antiPrompt;
|
||||
set => SetProperty(ref _antiPrompt, value);
|
||||
}
|
||||
|
||||
private int _width = 1024;
|
||||
public int Width
|
||||
{
|
||||
get => _width;
|
||||
set => SetProperty(ref _width, value);
|
||||
}
|
||||
|
||||
private int _height = 1024;
|
||||
public int Height
|
||||
{
|
||||
get => _height;
|
||||
set => SetProperty(ref _height, value);
|
||||
}
|
||||
|
||||
private float _cfg = 5f;
|
||||
public float Cfg
|
||||
{
|
||||
get => _cfg;
|
||||
set => SetProperty(ref _cfg, value);
|
||||
}
|
||||
|
||||
private int _steps = 28;
|
||||
public int Steps
|
||||
{
|
||||
get => _steps;
|
||||
set => SetProperty(ref _steps, value);
|
||||
}
|
||||
|
||||
private long _seed = -1;
|
||||
public long Seed
|
||||
{
|
||||
get => _seed;
|
||||
set => SetProperty(ref _seed, value);
|
||||
}
|
||||
|
||||
private Sampler _sampleMethod = Sampler.Euler_A;
|
||||
public Sampler SampleMethod
|
||||
{
|
||||
get => _sampleMethod;
|
||||
set => SetProperty(ref _sampleMethod, value);
|
||||
}
|
||||
|
||||
private string _image2ImageSourcePath = string.Empty;
|
||||
public string Image2ImageSourcePath
|
||||
{
|
||||
get => _image2ImageSourcePath;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _image2ImageSourcePath, value))
|
||||
{
|
||||
try
|
||||
{
|
||||
Image2ImageSource = ImageHelper.LoadImage(value).ConvertTo<ColorRGB>();
|
||||
}
|
||||
catch
|
||||
{
|
||||
Image2ImageSource = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private IImage<ColorRGB>? _image2ImageSource;
|
||||
public IImage<ColorRGB>? Image2ImageSource
|
||||
{
|
||||
get => _image2ImageSource;
|
||||
set => SetProperty(ref _image2ImageSource, value);
|
||||
}
|
||||
|
||||
private IImage? _image;
|
||||
public IImage? Image
|
||||
{
|
||||
get => _image;
|
||||
set => SetProperty(ref _image, value);
|
||||
}
|
||||
|
||||
private string _log = string.Empty;
|
||||
public string Log
|
||||
{
|
||||
get => _log;
|
||||
set => SetProperty(ref _log, value);
|
||||
}
|
||||
|
||||
private bool _isReady = true;
|
||||
public bool IsReady
|
||||
{
|
||||
get => _isReady;
|
||||
set => SetProperty(ref _isReady, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Commands
|
||||
|
||||
private ActionCommand? _loadModelCommand;
|
||||
public ActionCommand LoadModelCommand => _loadModelCommand ??= new ActionCommand(LoadModel);
|
||||
|
||||
private ActionCommand? _createImageCommand;
|
||||
public ActionCommand CreateImageCommand => _createImageCommand ??= new ActionCommand(CreateImage);
|
||||
|
||||
private ActionCommand? _saveImageCommand;
|
||||
public ActionCommand SaveImageCommand => _saveImageCommand ??= new ActionCommand(SaveImage);
|
||||
|
||||
private ActionCommand? _selectModelCommand;
|
||||
public ActionCommand SelectModelCommand => _selectModelCommand ??= new ActionCommand(SelectModel);
|
||||
|
||||
private ActionCommand? _selectDiffusionModelCommand;
|
||||
public ActionCommand SelectDiffusionModelCommand => _selectDiffusionModelCommand ??= new ActionCommand(SelectDiffusionModel);
|
||||
|
||||
private ActionCommand? _selectClipLCommand;
|
||||
public ActionCommand SelectClipLCommand => _selectClipLCommand ??= new ActionCommand(SelectClipL);
|
||||
|
||||
private ActionCommand? _selectT5xxlCommand;
|
||||
public ActionCommand SelectT5xxlCommand => _selectT5xxlCommand ??= new ActionCommand(SelectT5xxl);
|
||||
|
||||
private ActionCommand? _selectVaeCommand;
|
||||
public ActionCommand SelectVaeCommand => _selectVaeCommand ??= new ActionCommand(SelectVae);
|
||||
|
||||
private ActionCommand? _selectImage2ImageSourceCommand;
|
||||
public ActionCommand SelectImage2ImageSourceCommand => _selectImage2ImageSourceCommand ??= new ActionCommand(SelectImage2ImageSource);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public MainWindowViewModel()
|
||||
{
|
||||
try
|
||||
{
|
||||
StableDiffusionCpp.Log += (_, args) => LogLine($"LOG [{args.Level}]: {args.Text}", false);
|
||||
StableDiffusionCpp.Progress += (_, args) => LogLine($"PROGRESS {args.Step} / {args.Steps} ({(args.Progress * 100):N2} %) {args.IterationsPerSecond:N2} it/s ({args.Time})");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogLine($"Failed to load stable-diffusion.cpp libraries!{Environment.NewLine}{ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
private async void LoadModel()
|
||||
{
|
||||
try
|
||||
{
|
||||
IsReady = false;
|
||||
|
||||
_model?.Dispose();
|
||||
|
||||
bool restoreDefaultParameters = false;
|
||||
|
||||
if (IsStableDiffusionSelected)
|
||||
{
|
||||
restoreDefaultParameters = _model?.ModelParameter.DiffusionModelType != DiffusionModelType.StableDiffusion;
|
||||
|
||||
LogLine($"Loading stable diffusion-model '{ModelPath}'");
|
||||
_model = await Task.Run(() => ModelBuilder.StableDiffusion(ModelPath).WithMultithreading().WithVae(VaePath).WithSchedule(Schedule).WithFlashAttention(FlashAttention).Build());
|
||||
}
|
||||
else if (IsFluxSelected)
|
||||
{
|
||||
restoreDefaultParameters = _model?.ModelParameter.DiffusionModelType != DiffusionModelType.Flux;
|
||||
|
||||
LogLine($"Loading flux-model '{DiffusionModelPath}'");
|
||||
_model = await Task.Run(() => ModelBuilder.Flux(DiffusionModelPath, ClipLPath, T5xxlPath, VaePath).WithMultithreading().WithSchedule(Schedule).WithFlashAttention(FlashAttention).Build());
|
||||
}
|
||||
else
|
||||
{
|
||||
LogLine("No model-type selected :(");
|
||||
}
|
||||
|
||||
if (restoreDefaultParameters && (_model != null))
|
||||
{
|
||||
DiffusionParameter parameter = _model.GetDefaultParameter();
|
||||
AntiPrompt = parameter.NegativePrompt;
|
||||
Width = parameter.Width;
|
||||
Height = parameter.Height;
|
||||
Steps = parameter.SampleSteps;
|
||||
Seed = parameter.Seed;
|
||||
SampleMethod = parameter.SampleMethod;
|
||||
Cfg = _model.ModelParameter.DiffusionModelType == DiffusionModelType.Flux ? parameter.Guidance : parameter.CfgScale;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogLine($"Failed to load model ...{Environment.NewLine}{ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsReady = true;
|
||||
}
|
||||
}
|
||||
|
||||
private async void CreateImage()
|
||||
{
|
||||
if (_model == null) return;
|
||||
|
||||
try
|
||||
{
|
||||
IsReady = false;
|
||||
|
||||
DiffusionParameter parameter = _model.GetDefaultParameter()
|
||||
.WithNegativePrompt(AntiPrompt)
|
||||
.WithSize(Width, Height)
|
||||
.WithSteps(Steps)
|
||||
.WithSeed(Seed)
|
||||
.WithSampler(SampleMethod);
|
||||
if (_model.ModelParameter.DiffusionModelType == DiffusionModelType.StableDiffusion)
|
||||
parameter = parameter.WithCfg(Cfg);
|
||||
else if (_model.ModelParameter.DiffusionModelType == DiffusionModelType.Flux)
|
||||
parameter = parameter.WithGuidance(Cfg);
|
||||
|
||||
if (Image2ImageSource == null)
|
||||
{
|
||||
LogLine("Creating image ...");
|
||||
Image = await Task.Run(() => _model?.TextToImage(Prompt, parameter));
|
||||
}
|
||||
else
|
||||
{
|
||||
LogLine("Manipulating image ...");
|
||||
Image = await Task.Run(() => _model?.ImageToImage(Prompt, Image2ImageSource, parameter));
|
||||
}
|
||||
|
||||
LogLine("done!");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogLine($"Failed to create image ...{Environment.NewLine}{ex.Message}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsReady = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveImage()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Image == null) return;
|
||||
|
||||
SaveFileDialog saveFileDialog = new() { Filter = "PNG File (*.png)|*.png" };
|
||||
if (saveFileDialog.ShowDialog() == true)
|
||||
{
|
||||
File.WriteAllBytes(saveFileDialog.FileName, Image.ToPng());
|
||||
LogLine($"Image saved to '{saveFileDialog.FileName}'!");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogLine($"Failed to save image ...{Environment.NewLine}{ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
private void SelectModel()
|
||||
{
|
||||
OpenFileDialog openFileDialog = new() { Filter = "Stable Diffusion Model|*.*" };
|
||||
if (openFileDialog.ShowDialog() == true)
|
||||
ModelPath = openFileDialog.FileName;
|
||||
}
|
||||
|
||||
private void SelectDiffusionModel()
|
||||
{
|
||||
OpenFileDialog openFileDialog = new() { Filter = "Diffusion Model|*.*" };
|
||||
if (openFileDialog.ShowDialog() == true)
|
||||
DiffusionModelPath = openFileDialog.FileName;
|
||||
}
|
||||
|
||||
private void SelectClipL()
|
||||
{
|
||||
OpenFileDialog openFileDialog = new() { Filter = "ClipL|*.*" };
|
||||
if (openFileDialog.ShowDialog() == true)
|
||||
ClipLPath = openFileDialog.FileName;
|
||||
}
|
||||
|
||||
private void SelectT5xxl()
|
||||
{
|
||||
OpenFileDialog openFileDialog = new() { Filter = "T5xxl|*.*" };
|
||||
if (openFileDialog.ShowDialog() == true)
|
||||
T5xxlPath = openFileDialog.FileName;
|
||||
}
|
||||
|
||||
private void SelectVae()
|
||||
{
|
||||
OpenFileDialog openFileDialog = new() { Filter = "VAE|*.*" };
|
||||
if (openFileDialog.ShowDialog() == true)
|
||||
VaePath = openFileDialog.FileName;
|
||||
}
|
||||
|
||||
private void SelectImage2ImageSource()
|
||||
{
|
||||
IEnumerable<string> codecs = ["All Files (*.*)|*.*", .. ImageCodecInfo.GetImageDecoders().Select(c =>
|
||||
{
|
||||
string codecName = c.CodecName![8..].Replace("Codec", "Files").Trim();
|
||||
return $"{codecName} ({c.FilenameExtension})|{c.FilenameExtension}";
|
||||
})];
|
||||
|
||||
OpenFileDialog openFileDialog = new() { Filter = string.Join('|', codecs) };
|
||||
if (openFileDialog.ShowDialog() == true)
|
||||
Image2ImageSourcePath = openFileDialog.FileName;
|
||||
}
|
||||
|
||||
private void LogLine(string line, bool appendNewLine = true)
|
||||
{
|
||||
if (appendNewLine)
|
||||
Log += line + Environment.NewLine;
|
||||
else
|
||||
Log += line;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region NotifyPropertyChanged
|
||||
|
||||
public event PropertyChangedEventHandler? PropertyChanged;
|
||||
|
||||
private void OnPropertyChanged([CallerMemberName] string? propertyName = null) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
|
||||
private bool SetProperty<T>(ref T field, T value, [CallerMemberName] string? propertyName = null)
|
||||
{
|
||||
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
|
||||
field = value;
|
||||
OnPropertyChanged(propertyName);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
322
Header/stable-diffusion.h
Normal file
322
Header/stable-diffusion.h
Normal file
@ -0,0 +1,322 @@
|
||||
#ifndef __STABLE_DIFFUSION_H__
|
||||
#define __STABLE_DIFFUSION_H__
|
||||
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
#ifndef SD_BUILD_SHARED_LIB
|
||||
#define SD_API
|
||||
#else
|
||||
#ifdef SD_BUILD_DLL
|
||||
#define SD_API __declspec(dllexport)
|
||||
#else
|
||||
#define SD_API __declspec(dllimport)
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
#if __GNUC__ >= 4
|
||||
#define SD_API __attribute__((visibility("default")))
|
||||
#else
|
||||
#define SD_API
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
enum rng_type_t {
|
||||
STD_DEFAULT_RNG,
|
||||
CUDA_RNG,
|
||||
RNG_TYPE_COUNT
|
||||
};
|
||||
|
||||
enum sample_method_t {
|
||||
SAMPLE_METHOD_DEFAULT,
|
||||
EULER,
|
||||
HEUN,
|
||||
DPM2,
|
||||
DPMPP2S_A,
|
||||
DPMPP2M,
|
||||
DPMPP2Mv2,
|
||||
IPNDM,
|
||||
IPNDM_V,
|
||||
LCM,
|
||||
DDIM_TRAILING,
|
||||
TCD,
|
||||
EULER_A,
|
||||
SAMPLE_METHOD_COUNT
|
||||
};
|
||||
|
||||
enum scheduler_t {
|
||||
DEFAULT,
|
||||
DISCRETE,
|
||||
KARRAS,
|
||||
EXPONENTIAL,
|
||||
AYS,
|
||||
GITS,
|
||||
SGM_UNIFORM,
|
||||
SIMPLE,
|
||||
SMOOTHSTEP,
|
||||
SCHEDULE_COUNT
|
||||
};
|
||||
|
||||
enum prediction_t {
|
||||
DEFAULT_PRED,
|
||||
EPS_PRED,
|
||||
V_PRED,
|
||||
EDM_V_PRED,
|
||||
SD3_FLOW_PRED,
|
||||
FLUX_FLOW_PRED,
|
||||
PREDICTION_COUNT
|
||||
};
|
||||
|
||||
// same as enum ggml_type
|
||||
enum sd_type_t {
|
||||
SD_TYPE_F32 = 0,
|
||||
SD_TYPE_F16 = 1,
|
||||
SD_TYPE_Q4_0 = 2,
|
||||
SD_TYPE_Q4_1 = 3,
|
||||
// SD_TYPE_Q4_2 = 4, support has been removed
|
||||
// SD_TYPE_Q4_3 = 5, support has been removed
|
||||
SD_TYPE_Q5_0 = 6,
|
||||
SD_TYPE_Q5_1 = 7,
|
||||
SD_TYPE_Q8_0 = 8,
|
||||
SD_TYPE_Q8_1 = 9,
|
||||
SD_TYPE_Q2_K = 10,
|
||||
SD_TYPE_Q3_K = 11,
|
||||
SD_TYPE_Q4_K = 12,
|
||||
SD_TYPE_Q5_K = 13,
|
||||
SD_TYPE_Q6_K = 14,
|
||||
SD_TYPE_Q8_K = 15,
|
||||
SD_TYPE_IQ2_XXS = 16,
|
||||
SD_TYPE_IQ2_XS = 17,
|
||||
SD_TYPE_IQ3_XXS = 18,
|
||||
SD_TYPE_IQ1_S = 19,
|
||||
SD_TYPE_IQ4_NL = 20,
|
||||
SD_TYPE_IQ3_S = 21,
|
||||
SD_TYPE_IQ2_S = 22,
|
||||
SD_TYPE_IQ4_XS = 23,
|
||||
SD_TYPE_I8 = 24,
|
||||
SD_TYPE_I16 = 25,
|
||||
SD_TYPE_I32 = 26,
|
||||
SD_TYPE_I64 = 27,
|
||||
SD_TYPE_F64 = 28,
|
||||
SD_TYPE_IQ1_M = 29,
|
||||
SD_TYPE_BF16 = 30,
|
||||
// SD_TYPE_Q4_0_4_4 = 31, support has been removed from gguf files
|
||||
// SD_TYPE_Q4_0_4_8 = 32,
|
||||
// SD_TYPE_Q4_0_8_8 = 33,
|
||||
SD_TYPE_TQ1_0 = 34,
|
||||
SD_TYPE_TQ2_0 = 35,
|
||||
// SD_TYPE_IQ4_NL_4_4 = 36,
|
||||
// SD_TYPE_IQ4_NL_4_8 = 37,
|
||||
// SD_TYPE_IQ4_NL_8_8 = 38,
|
||||
SD_TYPE_MXFP4 = 39, // MXFP4 (1 block)
|
||||
SD_TYPE_COUNT = 40,
|
||||
};
|
||||
|
||||
enum sd_log_level_t {
|
||||
SD_LOG_DEBUG,
|
||||
SD_LOG_INFO,
|
||||
SD_LOG_WARN,
|
||||
SD_LOG_ERROR
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
bool enabled;
|
||||
int tile_size_x;
|
||||
int tile_size_y;
|
||||
float target_overlap;
|
||||
float rel_size_x;
|
||||
float rel_size_y;
|
||||
} sd_tiling_params_t;
|
||||
|
||||
typedef struct {
|
||||
const char* model_path;
|
||||
const char* clip_l_path;
|
||||
const char* clip_g_path;
|
||||
const char* clip_vision_path;
|
||||
const char* t5xxl_path;
|
||||
const char* qwen2vl_path;
|
||||
const char* qwen2vl_vision_path;
|
||||
const char* diffusion_model_path;
|
||||
const char* high_noise_diffusion_model_path;
|
||||
const char* vae_path;
|
||||
const char* taesd_path;
|
||||
const char* control_net_path;
|
||||
const char* lora_model_dir;
|
||||
const char* embedding_dir;
|
||||
const char* photo_maker_path;
|
||||
bool vae_decode_only;
|
||||
bool free_params_immediately;
|
||||
int n_threads;
|
||||
enum sd_type_t wtype;
|
||||
enum rng_type_t rng_type;
|
||||
enum prediction_t prediction;
|
||||
bool offload_params_to_cpu;
|
||||
bool keep_clip_on_cpu;
|
||||
bool keep_control_net_on_cpu;
|
||||
bool keep_vae_on_cpu;
|
||||
bool diffusion_flash_attn;
|
||||
bool diffusion_conv_direct;
|
||||
bool vae_conv_direct;
|
||||
bool force_sdxl_vae_conv_scale;
|
||||
bool chroma_use_dit_mask;
|
||||
bool chroma_use_t5_mask;
|
||||
int chroma_t5_mask_pad;
|
||||
float flow_shift;
|
||||
} sd_ctx_params_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t channel;
|
||||
uint8_t* data;
|
||||
} sd_image_t;
|
||||
|
||||
typedef struct {
|
||||
int* layers;
|
||||
size_t layer_count;
|
||||
float layer_start;
|
||||
float layer_end;
|
||||
float scale;
|
||||
} sd_slg_params_t;
|
||||
|
||||
typedef struct {
|
||||
float txt_cfg;
|
||||
float img_cfg;
|
||||
float distilled_guidance;
|
||||
sd_slg_params_t slg;
|
||||
} sd_guidance_params_t;
|
||||
|
||||
typedef struct {
|
||||
sd_guidance_params_t guidance;
|
||||
enum scheduler_t scheduler;
|
||||
enum sample_method_t sample_method;
|
||||
int sample_steps;
|
||||
float eta;
|
||||
int shifted_timestep;
|
||||
} sd_sample_params_t;
|
||||
|
||||
typedef struct {
|
||||
sd_image_t* id_images;
|
||||
int id_images_count;
|
||||
const char* id_embed_path;
|
||||
float style_strength;
|
||||
} sd_pm_params_t; // photo maker
|
||||
|
||||
typedef struct {
|
||||
const char* prompt;
|
||||
const char* negative_prompt;
|
||||
int clip_skip;
|
||||
sd_image_t init_image;
|
||||
sd_image_t* ref_images;
|
||||
int ref_images_count;
|
||||
bool auto_resize_ref_image;
|
||||
bool increase_ref_index;
|
||||
sd_image_t mask_image;
|
||||
int width;
|
||||
int height;
|
||||
sd_sample_params_t sample_params;
|
||||
float strength;
|
||||
int64_t seed;
|
||||
int batch_count;
|
||||
sd_image_t control_image;
|
||||
float control_strength;
|
||||
sd_pm_params_t pm_params;
|
||||
sd_tiling_params_t vae_tiling_params;
|
||||
} sd_img_gen_params_t;
|
||||
|
||||
typedef struct {
|
||||
const char* prompt;
|
||||
const char* negative_prompt;
|
||||
int clip_skip;
|
||||
sd_image_t init_image;
|
||||
sd_image_t end_image;
|
||||
sd_image_t* control_frames;
|
||||
int control_frames_size;
|
||||
int width;
|
||||
int height;
|
||||
sd_sample_params_t sample_params;
|
||||
sd_sample_params_t high_noise_sample_params;
|
||||
float moe_boundary;
|
||||
float strength;
|
||||
int64_t seed;
|
||||
int video_frames;
|
||||
float vace_strength;
|
||||
} sd_vid_gen_params_t;
|
||||
|
||||
typedef struct sd_ctx_t sd_ctx_t;
|
||||
|
||||
typedef void (*sd_log_cb_t)(enum sd_log_level_t level, const char* text, void* data);
|
||||
typedef void (*sd_progress_cb_t)(int step, int steps, float time, void* data);
|
||||
|
||||
SD_API void sd_set_log_callback(sd_log_cb_t sd_log_cb, void* data);
|
||||
SD_API void sd_set_progress_callback(sd_progress_cb_t cb, void* data);
|
||||
SD_API int32_t get_num_physical_cores();
|
||||
SD_API const char* sd_get_system_info();
|
||||
|
||||
SD_API const char* sd_type_name(enum sd_type_t type);
|
||||
SD_API enum sd_type_t str_to_sd_type(const char* str);
|
||||
SD_API const char* sd_rng_type_name(enum rng_type_t rng_type);
|
||||
SD_API enum rng_type_t str_to_rng_type(const char* str);
|
||||
SD_API const char* sd_sample_method_name(enum sample_method_t sample_method);
|
||||
SD_API enum sample_method_t str_to_sample_method(const char* str);
|
||||
SD_API const char* sd_schedule_name(enum scheduler_t scheduler);
|
||||
SD_API enum scheduler_t str_to_schedule(const char* str);
|
||||
SD_API const char* sd_prediction_name(enum prediction_t prediction);
|
||||
SD_API enum prediction_t str_to_prediction(const char* str);
|
||||
|
||||
SD_API void sd_ctx_params_init(sd_ctx_params_t* sd_ctx_params);
|
||||
SD_API char* sd_ctx_params_to_str(const sd_ctx_params_t* sd_ctx_params);
|
||||
|
||||
SD_API sd_ctx_t* new_sd_ctx(const sd_ctx_params_t* sd_ctx_params);
|
||||
SD_API void free_sd_ctx(sd_ctx_t* sd_ctx);
|
||||
SD_API enum sample_method_t sd_get_default_sample_method(const sd_ctx_t* sd_ctx);
|
||||
|
||||
SD_API void sd_sample_params_init(sd_sample_params_t* sample_params);
|
||||
SD_API char* sd_sample_params_to_str(const sd_sample_params_t* sample_params);
|
||||
|
||||
SD_API void sd_img_gen_params_init(sd_img_gen_params_t* sd_img_gen_params);
|
||||
SD_API char* sd_img_gen_params_to_str(const sd_img_gen_params_t* sd_img_gen_params);
|
||||
SD_API sd_image_t* generate_image(sd_ctx_t* sd_ctx, const sd_img_gen_params_t* sd_img_gen_params);
|
||||
|
||||
SD_API void sd_vid_gen_params_init(sd_vid_gen_params_t* sd_vid_gen_params);
|
||||
SD_API sd_image_t* generate_video(sd_ctx_t* sd_ctx, const sd_vid_gen_params_t* sd_vid_gen_params, int* num_frames_out);
|
||||
|
||||
typedef struct upscaler_ctx_t upscaler_ctx_t;
|
||||
|
||||
SD_API upscaler_ctx_t* new_upscaler_ctx(const char* esrgan_path,
|
||||
bool offload_params_to_cpu,
|
||||
bool direct,
|
||||
int n_threads);
|
||||
SD_API void free_upscaler_ctx(upscaler_ctx_t* upscaler_ctx);
|
||||
|
||||
SD_API sd_image_t upscale(upscaler_ctx_t* upscaler_ctx,
|
||||
sd_image_t input_image,
|
||||
uint32_t upscale_factor);
|
||||
|
||||
SD_API int get_upscale_factor(upscaler_ctx_t* upscaler_ctx);
|
||||
|
||||
SD_API bool convert(const char* input_path,
|
||||
const char* vae_path,
|
||||
const char* output_path,
|
||||
enum sd_type_t output_type,
|
||||
const char* tensor_type_rules);
|
||||
|
||||
SD_API bool preprocess_canny(sd_image_t image,
|
||||
float high_threshold,
|
||||
float low_threshold,
|
||||
float weak,
|
||||
float strong,
|
||||
bool inverse);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __STABLE_DIFFUSION_H__
|
||||
68
README.md
68
README.md
@ -9,6 +9,7 @@ Based on https://github.com/leejet/stable-diffusion.cpp
|
||||
## Usage
|
||||
### Setup
|
||||
Install the [StableDiffusion.NET](https://www.nuget.org/packages/StableDiffusion.NET)-Nuget and at least one of the [Backend-Packages](https://www.nuget.org/packages?q=StableDiffusion.NET.Backend).
|
||||
StableDiffusion.NET is using semantic versioning. Backend-packages are compatible as long as the version does only differ in the last digit.
|
||||
If GPU-support is available it will prefer this over CPU.
|
||||
If you want to add your own native-libraries or need more control over which backend to load, check the static `Backends` class.
|
||||
|
||||
@ -17,37 +18,50 @@ If you want to add your own native-libraries or need more control over which bac
|
||||
|
||||
stable diffusion:
|
||||
```csharp
|
||||
using DiffusionModel model = ModelBuilder.StableDiffusion(@"<path to model")
|
||||
.WithVae(@"<optional path to vae>")
|
||||
// Enable the Log- and Progress-events
|
||||
StableDiffusionCpp.InitializeEvents();
|
||||
|
||||
// Register the Log and Progress-events to capture stable-diffusion.cpp output
|
||||
StableDiffusionCpp.Log += (_, args) => Console.WriteLine($"LOG [{args.Level}]: {args.Text}");
|
||||
StableDiffusionCpp.Progress += (_, args) => Console.WriteLine($"PROGRESS {args.Step} / {args.Steps} ({(args.Progress * 100):N2} %) {args.IterationsPerSecond:N2} it/s ({args.Time})");
|
||||
|
||||
Image<ColorRGB>? treeWithTiger;
|
||||
// Load a StableDiffusion model in a using block to unload it again after the two images are created
|
||||
using (DiffusionModel sd = new(DiffusionModelParameter.Create()
|
||||
.WithModelPath(@"<path to model>")
|
||||
// .WithVae(@"<optional path to vae>")
|
||||
.WithMultithreading()
|
||||
.Build();
|
||||
```
|
||||
.WithFlashAttention()))
|
||||
{
|
||||
// Create a image from a prompt
|
||||
Image<ColorRGB>? tree = sd.GenerateImage(ImageGenerationParameter.TextToImage("A beautiful tree standing on a small hill").WithSDXLDefaults());
|
||||
// (optional) Save the image (requires the HPPH System.Dawing or SkiaSharp extension)
|
||||
File.WriteAllBytes("image1.png", tree.ToPng());
|
||||
|
||||
flux:
|
||||
```csharp
|
||||
using DiffusionModel model = ModelBuilder.Flux(@"<path to flux-model.gguf>",
|
||||
@"<path to clip_l.safetensors>",
|
||||
@"<path to t5xxl_fp16.safetensors>",
|
||||
@"<path to ae.safetensors>")
|
||||
// Use the previously created image for an image-to-image creation
|
||||
treeWithTiger = sd.GenerateImage(ImageGenerationParameter.ImageToImage("A cute tiger in front of a tree on a small hill", tree).WithSDXLDefaults());
|
||||
File.WriteAllBytes("image2.png", treeWithTiger.ToPng());
|
||||
}
|
||||
|
||||
// Load the qwen image edit model
|
||||
using DiffusionModel qwenContext = new(DiffusionModelParameter.Create()
|
||||
.WithDiffusionModelPath(@"<Qwen-Image-Edit-2509-path>")
|
||||
.WithQwen2VLPath(@"<Qwen2.5-VL-7B-Instruct-path>")
|
||||
.WithQwen2VLVisionPath(@"<Qwen2.5-VL-7B-Instruct.mmproj-path>")
|
||||
.WithVae(@"<qwen_image_vae-path>")
|
||||
.WithMultithreading()
|
||||
.Build();
|
||||
```
|
||||
.WithFlashAttention()
|
||||
.WithFlowShift(3)
|
||||
.WithOffloadedParamsToCPU()
|
||||
.WithImmediatelyFreedParams());
|
||||
|
||||
#### 2. create image
|
||||
|
||||
with default parameters:
|
||||
```csharp
|
||||
IImage<ColorRGB> image = model.TextToImage("<prompt>");
|
||||
```
|
||||
|
||||
with custom parameters:
|
||||
```csharp
|
||||
IImage<ColorRGB> image = model.TextToImage("<prompt>", model.GetDefaultParameter().WithSeed(1234).WithSize(1344, 768));
|
||||
```
|
||||
|
||||
#### 3. (optional) save the image (requires System.Dawing or SkiaSharp extension)
|
||||
```csharp
|
||||
File.WriteAllBytes("output.png", image.ToPng());
|
||||
// Perform an edit on the previously created image
|
||||
Image<ColorRGB>? tigerOnMoon = qwenContext.GenerateImage(ImageGenerationParameter.TextToImage("Remove the background and place the tree and the tiger on the moon.")
|
||||
.WithSize(1024, 1024)
|
||||
.WithCfg(2.5f)
|
||||
.WithSampler(Sampler.Euler)
|
||||
.WithRefImages(treeWithTiger));
|
||||
File.WriteAllBytes("image3.png", tigerOnMoon.ToPng());
|
||||
```
|
||||
|
||||
To process the resulting image further you can write your own extensions or install one of the [HPPH](https://github.com/DarthAffe/HPPH)-extension sets:
|
||||
|
||||
@ -5,10 +5,7 @@ VisualStudioVersion = 17.8.34322.80
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StableDiffusion.NET", "StableDiffusion.NET\StableDiffusion.NET.csproj", "{ED9336F9-7C5F-47DD-A120-272F4835E95F}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{8961F5D8-3F50-4027-8862-635FCA1E1568}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ImageCreationUI", "Examples\ImageCreationUI\ImageCreationUI.csproj", "{EB73E250-D2F7-469A-80BF-02C5078546A7}"
|
||||
EndProject
|
||||
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -19,17 +16,10 @@ Global
|
||||
{ED9336F9-7C5F-47DD-A120-272F4835E95F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{ED9336F9-7C5F-47DD-A120-272F4835E95F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{ED9336F9-7C5F-47DD-A120-272F4835E95F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EB73E250-D2F7-469A-80BF-02C5078546A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EB73E250-D2F7-469A-80BF-02C5078546A7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EB73E250-D2F7-469A-80BF-02C5078546A7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EB73E250-D2F7-469A-80BF-02C5078546A7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{EB73E250-D2F7-469A-80BF-02C5078546A7} = {8961F5D8-3F50-4027-8862-635FCA1E1568}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {8DD53974-8766-4659-97B6-4AEDF4323F65}
|
||||
EndGlobalSection
|
||||
|
||||
@ -27,7 +27,7 @@ public partial class CudaBackend : IBackend
|
||||
public bool IsAvailable => (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
|
||||
|| RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
&& (RuntimeInformation.OSArchitecture == Architecture.X64)
|
||||
&& CudaVersion is 11 or 12;
|
||||
&& CudaVersion is 12;
|
||||
|
||||
public string PathPart => CudaVersion switch
|
||||
{
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
public enum DiffusionModelType
|
||||
{
|
||||
None = 0,
|
||||
StableDiffusion = 1,
|
||||
Flux = 2
|
||||
}
|
||||
11
StableDiffusion.NET/Enums/Prediction.cs
Normal file
11
StableDiffusion.NET/Enums/Prediction.cs
Normal file
@ -0,0 +1,11 @@
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
public enum Prediction
|
||||
{
|
||||
Default,
|
||||
EPS,
|
||||
V,
|
||||
EDM_V,
|
||||
SD3Flow,
|
||||
FluxFlow
|
||||
}
|
||||
@ -42,6 +42,7 @@ public enum Quantization
|
||||
// SD_TYPE_IQ4_NL_4_4 = 36,
|
||||
// SD_TYPE_IQ4_NL_4_8 = 37,
|
||||
// SD_TYPE_IQ4_NL_8_8 = 38,
|
||||
SD_TYPE_MXFP4 = 39,
|
||||
|
||||
Unspecified = 39
|
||||
Unspecified = 40
|
||||
}
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
public enum Sampler
|
||||
{
|
||||
Euler_A,
|
||||
Default,
|
||||
Euler,
|
||||
Heun,
|
||||
DPM2,
|
||||
@ -13,5 +13,6 @@ public enum Sampler
|
||||
IPNDM_V,
|
||||
LCM,
|
||||
DDIM_Trailing,
|
||||
TCD
|
||||
TCD,
|
||||
Euler_A,
|
||||
}
|
||||
@ -1,11 +1,14 @@
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
public enum Schedule
|
||||
public enum Scheduler
|
||||
{
|
||||
Default,
|
||||
Discrete,
|
||||
Karras,
|
||||
Exponential,
|
||||
AYS,
|
||||
GITS
|
||||
GITS,
|
||||
SGM_Uniform,
|
||||
Simple,
|
||||
Smoothstep
|
||||
}
|
||||
@ -1,92 +1,123 @@
|
||||
#pragma warning disable CA2208
|
||||
|
||||
using JetBrains.Annotations;
|
||||
using System;
|
||||
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
[PublicAPI]
|
||||
public static class ParameterExtension
|
||||
{
|
||||
public static void Validate(this UpscaleModelParameter parameter)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(parameter, nameof(parameter));
|
||||
ArgumentNullException.ThrowIfNull(parameter.ModelPath, nameof(UpscaleModelParameter.ModelPath));
|
||||
|
||||
if (!Enum.IsDefined(parameter.Quantization)) throw new ArgumentOutOfRangeException(nameof(UpscaleModelParameter.Quantization));
|
||||
}
|
||||
|
||||
public static void Validate(this DiffusionModelParameter parameter)
|
||||
{
|
||||
((IQuantizedModelParameter)parameter).Validate();
|
||||
((IDiffusionModelParameter)parameter).Validate();
|
||||
((IPhotomakerModelParameter)parameter).Validate();
|
||||
}
|
||||
|
||||
public static void Validate(this IQuantizedModelParameter parameter)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(parameter, nameof(parameter));
|
||||
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(parameter.ThreadCount, nameof(IQuantizedModelParameter.ThreadCount));
|
||||
|
||||
if (!Enum.IsDefined(parameter.Quantization)) throw new ArgumentOutOfRangeException(nameof(IQuantizedModelParameter.Quantization));
|
||||
}
|
||||
|
||||
public static void Validate(this IPhotomakerModelParameter parameter)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(parameter, nameof(parameter));
|
||||
ArgumentNullException.ThrowIfNull(parameter.StackedIdEmbeddingsDirectory, nameof(IPhotomakerModelParameter.StackedIdEmbeddingsDirectory));
|
||||
}
|
||||
|
||||
public static void Validate(this IDiffusionModelParameter parameter)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(parameter, nameof(parameter));
|
||||
ArgumentNullException.ThrowIfNull(parameter.VaePath, nameof(IDiffusionModelParameter.VaePath));
|
||||
ArgumentNullException.ThrowIfNull(parameter.TaesdPath, nameof(IDiffusionModelParameter.TaesdPath));
|
||||
ArgumentNullException.ThrowIfNull(parameter.LoraModelDirectory, nameof(IDiffusionModelParameter.LoraModelDirectory));
|
||||
ArgumentNullException.ThrowIfNull(parameter.ControlNetPath, nameof(IDiffusionModelParameter.ControlNetPath));
|
||||
ArgumentNullException.ThrowIfNull(parameter.EmbeddingsDirectory, nameof(IDiffusionModelParameter.EmbeddingsDirectory));
|
||||
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(parameter.ThreadCount, nameof(DiffusionModelParameter.ThreadCount));
|
||||
ArgumentNullException.ThrowIfNull(parameter.VaePath, nameof(DiffusionModelParameter.VaePath));
|
||||
ArgumentNullException.ThrowIfNull(parameter.TaesdPath, nameof(DiffusionModelParameter.TaesdPath));
|
||||
ArgumentNullException.ThrowIfNull(parameter.LoraModelDirectory, nameof(DiffusionModelParameter.LoraModelDirectory));
|
||||
ArgumentNullException.ThrowIfNull(parameter.ControlNetPath, nameof(DiffusionModelParameter.ControlNetPath));
|
||||
ArgumentNullException.ThrowIfNull(parameter.EmbeddingsDirectory, nameof(DiffusionModelParameter.EmbeddingsDirectory));
|
||||
ArgumentNullException.ThrowIfNull(parameter.StackedIdEmbeddingsDirectory, nameof(DiffusionModelParameter.StackedIdEmbeddingsDirectory));
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(parameter.VaePath) && !string.IsNullOrWhiteSpace(parameter.TaesdPath)) throw new ArgumentException("VAE and TAESD are mutually exclusive.");
|
||||
|
||||
if (!Enum.IsDefined(parameter.RngType)) throw new ArgumentOutOfRangeException(nameof(IDiffusionModelParameter.RngType));
|
||||
if (!Enum.IsDefined(parameter.Schedule)) throw new ArgumentOutOfRangeException(nameof(IDiffusionModelParameter.Schedule));
|
||||
if (!Enum.IsDefined(parameter.RngType)) throw new ArgumentOutOfRangeException(nameof(DiffusionModelParameter.RngType));
|
||||
}
|
||||
|
||||
public static void Validate(this DiffusionParameter parameter)
|
||||
public static void Validate(this ImageGenerationParameter parameter)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(parameter, nameof(parameter));
|
||||
ArgumentNullException.ThrowIfNull(parameter.ControlNet, nameof(DiffusionParameter.ControlNet));
|
||||
ArgumentNullException.ThrowIfNull(parameter.PhotoMaker, nameof(DiffusionParameter.PhotoMaker));
|
||||
ArgumentNullException.ThrowIfNull(parameter.NegativePrompt, nameof(DiffusionParameter.NegativePrompt));
|
||||
ArgumentNullException.ThrowIfNull(parameter.ControlNet, nameof(ImageGenerationParameter.ControlNet));
|
||||
ArgumentNullException.ThrowIfNull(parameter.PhotoMaker, nameof(ImageGenerationParameter.PhotoMaker));
|
||||
ArgumentNullException.ThrowIfNull(parameter.Prompt, nameof(ImageGenerationParameter.Prompt));
|
||||
ArgumentNullException.ThrowIfNull(parameter.NegativePrompt, nameof(ImageGenerationParameter.NegativePrompt));
|
||||
|
||||
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(parameter.Width, nameof(DiffusionParameter.Width));
|
||||
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(parameter.Height, nameof(DiffusionParameter.Height));
|
||||
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(parameter.SampleSteps, nameof(DiffusionParameter.SampleSteps));
|
||||
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(parameter.CfgScale, nameof(DiffusionParameter.CfgScale));
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(parameter.Guidance, nameof(DiffusionParameter.Guidance));
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(parameter.Strength, nameof(DiffusionParameter.Strength));
|
||||
|
||||
if (!Enum.IsDefined(parameter.SampleMethod)) throw new ArgumentOutOfRangeException(nameof(DiffusionParameter.SampleMethod));
|
||||
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(parameter.Width, nameof(ImageGenerationParameter.Width));
|
||||
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(parameter.Height, nameof(ImageGenerationParameter.Height));
|
||||
|
||||
parameter.SampleParameter.Validate();
|
||||
parameter.ControlNet.Validate();
|
||||
parameter.PhotoMaker.Validate();
|
||||
}
|
||||
|
||||
public static void Validate(this VideoGenerationParameter parameter)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(parameter, nameof(parameter));
|
||||
ArgumentNullException.ThrowIfNull(parameter.Prompt, nameof(VideoGenerationParameter.Prompt));
|
||||
ArgumentNullException.ThrowIfNull(parameter.NegativePrompt, nameof(VideoGenerationParameter.NegativePrompt));
|
||||
|
||||
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(parameter.Width, nameof(VideoGenerationParameter.Width));
|
||||
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(parameter.Height, nameof(VideoGenerationParameter.Height));
|
||||
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(parameter.FrameCount, nameof(VideoGenerationParameter.FrameCount));
|
||||
|
||||
parameter.SampleParameter.Validate();
|
||||
parameter.HighNoiseSampleParameter.Validate();
|
||||
}
|
||||
|
||||
public static void Validate(this ControlNetParameter parameter)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(parameter, nameof(DiffusionParameter.ControlNet));
|
||||
ArgumentNullException.ThrowIfNull(parameter, nameof(ImageGenerationParameter.ControlNet));
|
||||
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(parameter.Strength, nameof(ControlNetParameter.Strength));
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(parameter.CannyHighThreshold, nameof(ControlNetParameter.CannyHighThreshold));
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(parameter.CannyLowThreshold, nameof(ControlNetParameter.CannyLowThreshold));
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(parameter.CannyWeak, nameof(ControlNetParameter.CannyWeak));
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(parameter.CannyStrong, nameof(ControlNetParameter.CannyStrong));
|
||||
}
|
||||
|
||||
public static void Validate(this PhotoMakerParameter parameter)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(parameter, nameof(DiffusionParameter.PhotoMaker));
|
||||
ArgumentNullException.ThrowIfNull(parameter.InputIdImageDirectory, nameof(PhotoMakerParameter.InputIdImageDirectory));
|
||||
ArgumentNullException.ThrowIfNull(parameter, nameof(ImageGenerationParameter.PhotoMaker));
|
||||
ArgumentNullException.ThrowIfNull(parameter.IdEmbedPath, nameof(PhotoMakerParameter.IdEmbedPath));
|
||||
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(parameter.StyleRatio, nameof(PhotoMakerParameter.StyleRatio));
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(parameter.StyleStrength, nameof(PhotoMakerParameter.StyleStrength));
|
||||
}
|
||||
|
||||
public static void Validate(this SampleParameter parameter)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(parameter, nameof(parameter));
|
||||
|
||||
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(parameter.SampleSteps, nameof(ImageGenerationParameter.SampleParameter.SampleSteps));
|
||||
|
||||
if (!Enum.IsDefined(parameter.Scheduler)) throw new ArgumentOutOfRangeException(nameof(ImageGenerationParameter.SampleParameter.Scheduler));
|
||||
if (!Enum.IsDefined(parameter.SampleMethod)) throw new ArgumentOutOfRangeException(nameof(ImageGenerationParameter.SampleParameter.SampleMethod));
|
||||
|
||||
parameter.Guidance.Validate();
|
||||
}
|
||||
|
||||
public static void Validate(this GuidanceParameter parameter)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(parameter, nameof(parameter));
|
||||
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(parameter.ImgCfg);
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(parameter.DistilledGuidance);
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(parameter.MinCfg);
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(parameter.TxtCfg);
|
||||
|
||||
parameter.Slg.Validate();
|
||||
}
|
||||
|
||||
public static void Validate(this SlgParameter parameter)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(parameter, nameof(parameter));
|
||||
ArgumentNullException.ThrowIfNull(parameter.Layers);
|
||||
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(parameter.Scale);
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(parameter.SkipLayerStart);
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(parameter.SkipLayerEnd);
|
||||
}
|
||||
|
||||
public static void Validate(this CannyParameter parameter)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(parameter, nameof(parameter));
|
||||
|
||||
ArgumentNullException.ThrowIfNull(parameter.Image);
|
||||
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(parameter.HighThreshold, nameof(CannyParameter.HighThreshold));
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(parameter.LowThreshold, nameof(CannyParameter.LowThreshold));
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(parameter.Weak, nameof(CannyParameter.Weak));
|
||||
ArgumentOutOfRangeException.ThrowIfNegative(parameter.Strong, nameof(CannyParameter.Strong));
|
||||
}
|
||||
}
|
||||
@ -6,68 +6,134 @@ namespace StableDiffusion.NET;
|
||||
|
||||
internal static class ImageHelper
|
||||
{
|
||||
public static unsafe Image<ColorRGB> ToImage(Native.sd_image_t* sdImage)
|
||||
{
|
||||
Image<ColorRGB> image = ToImage(*sdImage);
|
||||
|
||||
Marshal.FreeHGlobal((nint)sdImage);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
public static unsafe Image<ColorRGB> ToImage(Native.sd_image_t sdImage)
|
||||
public static unsafe Image<ColorRGB> ToImage(this Native.Types.sd_image_t sdImage)
|
||||
{
|
||||
int width = (int)sdImage.width;
|
||||
int height = (int)sdImage.height;
|
||||
int bpp = (int)sdImage.channel;
|
||||
|
||||
Image<ColorRGB> image = Image<ColorRGB>.Create(new ReadOnlySpan<byte>(sdImage.data, width * height * bpp), width, height, width * bpp);
|
||||
switch (bpp)
|
||||
{
|
||||
case 3:
|
||||
return Image<ColorRGB>.Create(new ReadOnlySpan<byte>(sdImage.data, width * height * bpp), width, height, width * bpp);
|
||||
|
||||
Dispose(sdImage);
|
||||
case 1:
|
||||
{
|
||||
ColorRGB[] pixels = new ColorRGB[width * height];
|
||||
Span<byte> sdData = new(sdImage.data, pixels.Length);
|
||||
|
||||
for (int i = 0; i < pixels.Length; i++)
|
||||
{
|
||||
byte c = sdData[i];
|
||||
pixels[i] = new ColorRGB(c, c, c);
|
||||
}
|
||||
|
||||
Image<ColorRGB> image = Image<ColorRGB>.Create(pixels, width, height);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
public static unsafe void Dispose(Native.sd_image_t image) => Marshal.FreeHGlobal((nint)image.data);
|
||||
|
||||
public static unsafe Native.sd_image_t ToSdImage(this IImage image, out nint dataPtr)
|
||||
{
|
||||
int sizeInBytes = image.SizeInBytes;
|
||||
|
||||
dataPtr = Marshal.AllocHGlobal(sizeInBytes);
|
||||
image.CopyTo(new Span<byte>((void*)dataPtr, sizeInBytes));
|
||||
|
||||
return image.ToSdImage((byte*)dataPtr);
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException($"Image-BPP of {bpp} is not supported");
|
||||
}
|
||||
}
|
||||
|
||||
public static unsafe Native.sd_image_t ToSdImage(this IImage image, byte* pinnedReference)
|
||||
=> new()
|
||||
public static unsafe Native.Types.sd_image_t ToSdImage(this IImage image, bool monochrome = false)
|
||||
{
|
||||
if (monochrome)
|
||||
{
|
||||
int sizeInBytes = image.Width * image.Height;
|
||||
|
||||
byte* dataPtr = (byte*)NativeMemory.Alloc((nuint)sizeInBytes);
|
||||
Span<byte> data = new(dataPtr, sizeInBytes);
|
||||
|
||||
// DarthAffe 16.08.2025: HPPH does currently not support monochrome images, that's why we need to convert it here. We're going for the simple conversion as the source image is supposed to be monochrome anyway.
|
||||
for (int y = 0; y < image.Height; y++)
|
||||
for (int x = 0; x < image.Width; x++)
|
||||
{
|
||||
IColor color = image[x, y];
|
||||
data[(image.Width * y) + x] = (byte)Math.Round((color.R + color.G + color.B) / 3.0);
|
||||
}
|
||||
|
||||
return new Native.Types.sd_image_t
|
||||
{
|
||||
width = (uint)image.Width,
|
||||
height = (uint)image.Height,
|
||||
channel = (uint)image.ColorFormat.BytesPerPixel,
|
||||
data = pinnedReference
|
||||
channel = 1,
|
||||
data = dataPtr
|
||||
};
|
||||
|
||||
public static unsafe Native.sd_image_t* ToSdImagePtr(this IImage image, out nint dataPtr)
|
||||
}
|
||||
else
|
||||
{
|
||||
int sizeInBytes = image.SizeInBytes;
|
||||
IImage<ColorRGB> img = image as IImage<ColorRGB> ?? image.ConvertTo<ColorRGB>();
|
||||
|
||||
dataPtr = Marshal.AllocHGlobal(sizeInBytes);
|
||||
image.CopyTo(new Span<byte>((void*)dataPtr, sizeInBytes));
|
||||
int sizeInBytes = img.SizeInBytes;
|
||||
|
||||
return image.ToSdImagePtr((byte*)dataPtr);
|
||||
}
|
||||
byte* dataPtr = (byte*)NativeMemory.Alloc((nuint)sizeInBytes);
|
||||
img.CopyTo(new Span<byte>(dataPtr, sizeInBytes));
|
||||
|
||||
public static unsafe Native.sd_image_t* ToSdImagePtr(this IImage image, byte* pinnedReference)
|
||||
return new Native.Types.sd_image_t
|
||||
{
|
||||
Native.sd_image_t* nativeImage = (Native.sd_image_t*)Marshal.AllocHGlobal(sizeof(Native.sd_image_t));
|
||||
|
||||
nativeImage->width = (uint)image.Width;
|
||||
nativeImage->height = (uint)image.Height;
|
||||
nativeImage->channel = (uint)image.ColorFormat.BytesPerPixel;
|
||||
nativeImage->data = pinnedReference;
|
||||
|
||||
return nativeImage;
|
||||
width = (uint)img.Width,
|
||||
height = (uint)img.Height,
|
||||
channel = (uint)img.ColorFormat.BytesPerPixel,
|
||||
data = dataPtr
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public static unsafe void Free(this Native.Types.sd_image_t sdImage)
|
||||
{
|
||||
if (sdImage.data == null) return;
|
||||
|
||||
NativeMemory.Free(sdImage.data);
|
||||
}
|
||||
|
||||
public static unsafe Image<ColorRGB>[] ToImageArray(Native.Types.sd_image_t* sdImage, int count)
|
||||
{
|
||||
if (sdImage == null) return [];
|
||||
|
||||
Image<ColorRGB>[] images = new Image<ColorRGB>[count];
|
||||
|
||||
for (int i = 0; i < images.Length; i++)
|
||||
images[i] = GetImage(sdImage, i);
|
||||
|
||||
return images;
|
||||
}
|
||||
|
||||
internal static unsafe IImage[] ToImageArrayIFace(Native.Types.sd_image_t* sdImage, int count)
|
||||
{
|
||||
if (sdImage == null) return [];
|
||||
|
||||
IImage[] images = new IImage[count];
|
||||
|
||||
for (int i = 0; i < images.Length; i++)
|
||||
images[i] = GetImage(sdImage, i);
|
||||
|
||||
return images;
|
||||
}
|
||||
|
||||
public static unsafe Image<ColorRGB> GetImage(Native.Types.sd_image_t* sdImage, int index) => sdImage[index].ToImage();
|
||||
|
||||
public static unsafe Native.Types.sd_image_t* ToSdImage(this IImage[] images, bool monochrome = false)
|
||||
{
|
||||
int count = images.Length;
|
||||
|
||||
Native.Types.sd_image_t* imagePtr = (Native.Types.sd_image_t*)NativeMemory.Alloc((nuint)count, (nuint)Marshal.SizeOf<Native.Types.sd_image_t>());
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
imagePtr[i] = images[i].ToSdImage(monochrome);
|
||||
|
||||
return imagePtr;
|
||||
}
|
||||
|
||||
public static unsafe void Free(Native.Types.sd_image_t* sdImage, int count)
|
||||
{
|
||||
if (sdImage == null) return;
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
Free(sdImage[i]);
|
||||
|
||||
NativeMemory.Free(sdImage);
|
||||
}
|
||||
}
|
||||
@ -1,29 +0,0 @@
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
[PublicAPI]
|
||||
public sealed class ESRGANModelBuilder : IQuantizedModelBuilder
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public UpscaleModelParameter Parameter { get; }
|
||||
IQuantizedModelParameter IQuantizedModelBuilder.Parameter => Parameter;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public ESRGANModelBuilder(string modelPath)
|
||||
{
|
||||
Parameter = new UpscaleModelParameter { ModelPath = modelPath };
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public UpscaleModel Build() => new(Parameter);
|
||||
|
||||
#endregion
|
||||
}
|
||||
@ -1,130 +0,0 @@
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
[PublicAPI]
|
||||
public static class DiffusionModelBuilderExtension
|
||||
{
|
||||
public static T WithVae<T>(this T builder, string vaePath)
|
||||
where T : IDiffusionModelBuilder
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(vaePath);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(builder.Parameter.TaesdPath)) throw new ArgumentException("TAESD is already enabled. VAE and TAESD are mutually exclusive.", nameof(vaePath));
|
||||
|
||||
builder.Parameter.VaePath = vaePath;
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static T WithTaesd<T>(this T builder, string taesdPath)
|
||||
where T : IDiffusionModelBuilder
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(taesdPath);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(builder.Parameter.VaePath)) throw new ArgumentException("VAE is already enabled. TAESD and VAE are mutually exclusive.", nameof(taesdPath));
|
||||
|
||||
builder.Parameter.TaesdPath = taesdPath;
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static T WithLoraSupport<T>(this T builder, string loraModelDirectory)
|
||||
where T : IDiffusionModelBuilder
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(loraModelDirectory);
|
||||
|
||||
builder.Parameter.LoraModelDirectory = loraModelDirectory;
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static T WithEmbeddingSupport<T>(this T builder, string embeddingsDirectory)
|
||||
where T : IDiffusionModelBuilder
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(embeddingsDirectory);
|
||||
|
||||
builder.Parameter.EmbeddingsDirectory = embeddingsDirectory;
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static T WithControlNet<T>(this T builder, string controlNetPath)
|
||||
where T : IDiffusionModelBuilder
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(controlNetPath);
|
||||
|
||||
builder.Parameter.ControlNetPath = controlNetPath;
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static T WithVaeDecodeOnly<T>(this T builder, bool vaeDecodeOnly = true)
|
||||
where T : IDiffusionModelBuilder
|
||||
{
|
||||
builder.Parameter.VaeDecodeOnly = vaeDecodeOnly;
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static T WithVaeTiling<T>(this T builder, bool vaeTiling = true)
|
||||
where T : IDiffusionModelBuilder
|
||||
{
|
||||
builder.Parameter.VaeTiling = vaeTiling;
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static T KeepVaeOnCpu<T>(this T builder, bool keepVaeOnCpu = true)
|
||||
where T : IDiffusionModelBuilder
|
||||
{
|
||||
builder.Parameter.KeepVaeOnCPU = keepVaeOnCpu;
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static T KeepClipNetOnCpu<T>(this T builder, bool keepClipNetOnCpu = true)
|
||||
where T : IDiffusionModelBuilder
|
||||
{
|
||||
builder.Parameter.KeepClipOnCPU = keepClipNetOnCpu;
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static T KeepControlNetOnCpu<T>(this T builder, bool keepControlNetOnCpu = true)
|
||||
where T : IDiffusionModelBuilder
|
||||
{
|
||||
builder.Parameter.KeepControlNetOnCPU = keepControlNetOnCpu;
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static T WithRngType<T>(this T builder, RngType rngType)
|
||||
where T : IDiffusionModelBuilder
|
||||
{
|
||||
if (!Enum.IsDefined(rngType)) throw new ArgumentOutOfRangeException(nameof(rngType));
|
||||
|
||||
builder.Parameter.RngType = rngType;
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static T WithSchedule<T>(this T builder, Schedule schedule)
|
||||
where T : IDiffusionModelBuilder
|
||||
{
|
||||
if (!Enum.IsDefined(schedule)) throw new ArgumentOutOfRangeException(nameof(schedule));
|
||||
|
||||
builder.Parameter.Schedule = schedule;
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static T WithFlashAttention<T>(this T builder, bool flashAttention = true)
|
||||
where T : IDiffusionModelBuilder
|
||||
{
|
||||
builder.Parameter.FlashAttention = flashAttention;
|
||||
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
@ -1,18 +0,0 @@
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
[PublicAPI]
|
||||
public static class PhotomakerModelBuilderExtension
|
||||
{
|
||||
public static T WithPhotomaker<T>(this T builder, string stackedIdEmbeddingsDirectory)
|
||||
where T : IPhotomakerModelBuilder
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(stackedIdEmbeddingsDirectory, nameof(stackedIdEmbeddingsDirectory));
|
||||
|
||||
builder.Parameter.StackedIdEmbeddingsDirectory = stackedIdEmbeddingsDirectory;
|
||||
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
@ -1,36 +0,0 @@
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
[PublicAPI]
|
||||
public static class QuantizedModelBuilderExtension
|
||||
{
|
||||
public static T WithoutMultithreading<T>(this T builder)
|
||||
where T : IQuantizedModelBuilder
|
||||
{
|
||||
builder.Parameter.ThreadCount = 1;
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static T WithMultithreading<T>(this T builder, int threadCount = 0)
|
||||
where T : IQuantizedModelBuilder
|
||||
{
|
||||
ArgumentOutOfRangeException.ThrowIfLessThan(threadCount, 0, nameof(threadCount));
|
||||
|
||||
if (threadCount == 0) threadCount = Environment.ProcessorCount;
|
||||
|
||||
builder.Parameter.ThreadCount = threadCount;
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
public static T WithQuantization<T>(this T builder, Quantization quantization)
|
||||
where T : IQuantizedModelBuilder
|
||||
{
|
||||
builder.Parameter.Quantization = quantization;
|
||||
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
@ -1,30 +0,0 @@
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
[PublicAPI]
|
||||
public sealed class FluxModelBuilder : IDiffusionModelBuilder, IQuantizedModelBuilder
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public DiffusionModelParameter Parameter { get; }
|
||||
IDiffusionModelParameter IDiffusionModelBuilder.Parameter => Parameter;
|
||||
IQuantizedModelParameter IQuantizedModelBuilder.Parameter => Parameter;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public FluxModelBuilder(string diffusionModelPath, string clipLPath, string t5xxlPath, string vaePath)
|
||||
{
|
||||
Parameter = new DiffusionModelParameter { DiffusionModelType = DiffusionModelType.Flux, DiffusionModelPath = diffusionModelPath, ClipLPath = clipLPath, T5xxlPath = t5xxlPath, VaePath = vaePath };
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public DiffusionModel Build() => new(Parameter);
|
||||
|
||||
#endregion
|
||||
}
|
||||
@ -1,6 +0,0 @@
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
public interface IDiffusionModelBuilder
|
||||
{
|
||||
IDiffusionModelParameter Parameter { get; }
|
||||
}
|
||||
@ -1,6 +0,0 @@
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
public interface IPhotomakerModelBuilder
|
||||
{
|
||||
IPhotomakerModelParameter Parameter { get; }
|
||||
}
|
||||
@ -1,6 +0,0 @@
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
public interface IQuantizedModelBuilder
|
||||
{
|
||||
IQuantizedModelParameter Parameter { get; }
|
||||
}
|
||||
@ -1,12 +0,0 @@
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
[PublicAPI]
|
||||
public static class ModelBuilder
|
||||
{
|
||||
public static StableDiffusionModelBuilder StableDiffusion(string modelPath) => new(modelPath);
|
||||
public static StableDiffusion3_5ModelBuilder StableDiffusion3_5(string modelPath, string clipLPath, string clipGPath, string t5xxlPath) => new(modelPath, clipLPath, clipGPath, t5xxlPath);
|
||||
public static FluxModelBuilder Flux(string diffusionModelPath, string clipLPath, string t5xxlPath, string vaePath) => new(diffusionModelPath, clipLPath, t5xxlPath, vaePath);
|
||||
public static ESRGANModelBuilder ESRGAN(string modelPath) => new(modelPath);
|
||||
}
|
||||
@ -1,37 +0,0 @@
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
[PublicAPI]
|
||||
public sealed class StableDiffusion3_5ModelBuilder : IDiffusionModelBuilder, IQuantizedModelBuilder
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public DiffusionModelParameter Parameter { get; }
|
||||
IDiffusionModelParameter IDiffusionModelBuilder.Parameter => Parameter;
|
||||
IQuantizedModelParameter IQuantizedModelBuilder.Parameter => Parameter;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public StableDiffusion3_5ModelBuilder(string modelPath, string clipLPath, string clipGPath, string t5xxlPath)
|
||||
{
|
||||
Parameter = new DiffusionModelParameter
|
||||
{
|
||||
DiffusionModelType = DiffusionModelType.StableDiffusion,
|
||||
ModelPath = modelPath,
|
||||
ClipLPath = clipLPath,
|
||||
ClipGPath = clipGPath,
|
||||
T5xxlPath = t5xxlPath,
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public DiffusionModel Build() => new(Parameter);
|
||||
|
||||
#endregion
|
||||
}
|
||||
@ -1,31 +0,0 @@
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
[PublicAPI]
|
||||
public sealed class StableDiffusionModelBuilder : IDiffusionModelBuilder, IQuantizedModelBuilder, IPhotomakerModelBuilder
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public DiffusionModelParameter Parameter { get; }
|
||||
IDiffusionModelParameter IDiffusionModelBuilder.Parameter => Parameter;
|
||||
IQuantizedModelParameter IQuantizedModelBuilder.Parameter => Parameter;
|
||||
IPhotomakerModelParameter IPhotomakerModelBuilder.Parameter => Parameter;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
public StableDiffusionModelBuilder(string modelPath)
|
||||
{
|
||||
Parameter = new DiffusionModelParameter { DiffusionModelType = DiffusionModelType.StableDiffusion, ModelPath = modelPath };
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public DiffusionModel Build() => new(Parameter);
|
||||
|
||||
#endregion
|
||||
}
|
||||
@ -1,8 +1,6 @@
|
||||
using HPPH;
|
||||
using JetBrains.Annotations;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
@ -15,7 +13,7 @@ public sealed unsafe class DiffusionModel : IDisposable
|
||||
|
||||
public DiffusionModelParameter ModelParameter { get; }
|
||||
|
||||
private Native.sd_ctx_t* _ctx;
|
||||
private Native.Types.sd_ctx_t* _ctx;
|
||||
|
||||
#endregion
|
||||
|
||||
@ -25,8 +23,6 @@ public sealed unsafe class DiffusionModel : IDisposable
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(modelParameter, nameof(modelParameter));
|
||||
|
||||
modelParameter.Validate();
|
||||
|
||||
this.ModelParameter = modelParameter;
|
||||
|
||||
Initialize();
|
||||
@ -40,336 +36,53 @@ public sealed unsafe class DiffusionModel : IDisposable
|
||||
|
||||
private void Initialize()
|
||||
{
|
||||
_ctx = Native.new_sd_ctx(ModelParameter.ModelPath,
|
||||
ModelParameter.ClipLPath,
|
||||
ModelParameter.ClipGPath,
|
||||
ModelParameter.T5xxlPath,
|
||||
ModelParameter.DiffusionModelPath,
|
||||
ModelParameter.VaePath,
|
||||
ModelParameter.TaesdPath,
|
||||
ModelParameter.ControlNetPath,
|
||||
ModelParameter.LoraModelDirectory,
|
||||
ModelParameter.EmbeddingsDirectory,
|
||||
ModelParameter.StackedIdEmbeddingsDirectory,
|
||||
ModelParameter.VaeDecodeOnly,
|
||||
ModelParameter.VaeTiling,
|
||||
false,
|
||||
ModelParameter.ThreadCount,
|
||||
ModelParameter.Quantization,
|
||||
ModelParameter.RngType,
|
||||
ModelParameter.Schedule,
|
||||
ModelParameter.KeepClipOnCPU,
|
||||
ModelParameter.KeepControlNetOnCPU,
|
||||
ModelParameter.KeepVaeOnCPU,
|
||||
ModelParameter.FlashAttention,
|
||||
ModelParameter.ChromaUseDitMap,
|
||||
ModelParameter.ChromaEnableT5Map,
|
||||
ModelParameter.ChromaT5MaskPad);
|
||||
ModelParameter.Validate();
|
||||
|
||||
_ctx = Native.new_sd_ctx(ModelParameter);
|
||||
|
||||
if (_ctx == null) throw new NullReferenceException("Failed to initialize diffusion-model.");
|
||||
}
|
||||
|
||||
public DiffusionParameter GetDefaultParameter() => ModelParameter.DiffusionModelType switch
|
||||
public Image<ColorRGB>? GenerateImage(ImageGenerationParameter parameter)
|
||||
{
|
||||
DiffusionModelType.None => new DiffusionParameter(),
|
||||
DiffusionModelType.StableDiffusion => DiffusionParameter.SDXLDefault,
|
||||
DiffusionModelType.Flux => DiffusionParameter.FluxDefault,
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
|
||||
public IImage<ColorRGB> TextToImage(string prompt, DiffusionParameter? parameter = null)
|
||||
{
|
||||
parameter ??= GetDefaultParameter();
|
||||
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
ArgumentNullException.ThrowIfNull(prompt);
|
||||
|
||||
if (_ctx == null) throw new NullReferenceException("The model is not initialized.");
|
||||
|
||||
parameter.Validate();
|
||||
|
||||
List<nint> ptrsToFree = [];
|
||||
Native.Types.sd_image_t* result = Native.generate_image(_ctx, parameter);
|
||||
if (result == null) return null;
|
||||
|
||||
try
|
||||
{
|
||||
NativeParameters nativeParameters = PrefillParameters(prompt, parameter);
|
||||
SetControlNetParameters(ref nativeParameters, parameter, ptrsToFree);
|
||||
|
||||
Native.sd_image_t* result = Txt2Img(nativeParameters);
|
||||
|
||||
return ImageHelper.ToImage(result);
|
||||
return ImageHelper.GetImage(result, 0);
|
||||
}
|
||||
finally
|
||||
{
|
||||
foreach (nint ptr in ptrsToFree)
|
||||
Marshal.FreeHGlobal(ptr);
|
||||
ImageHelper.Free(result, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public IImage<ColorRGB> ImageToImage(string prompt, IImage image, DiffusionParameter? parameter = null)
|
||||
public Image<ColorRGB>[] GenerateVideo(VideoGenerationParameter parameter)
|
||||
{
|
||||
parameter ??= GetDefaultParameter();
|
||||
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
ArgumentNullException.ThrowIfNull(prompt);
|
||||
ArgumentNullException.ThrowIfNull(image);
|
||||
|
||||
parameter.Validate();
|
||||
|
||||
// DarthAffe 10.08.2024: Mask needs to be a 1 channel all max value image when it's not used - I really don't like this concept as it adds unnecessary allocations, but that's how it is :(
|
||||
Span<byte> maskBuffer = new byte[image.Width * image.Height];
|
||||
maskBuffer.Fill(byte.MaxValue);
|
||||
|
||||
return InternalImageToImage(prompt, image, maskBuffer, parameter);
|
||||
}
|
||||
|
||||
public IImage<ColorRGB> Inpaint(string prompt, IImage image, IImage mask, DiffusionParameter? parameter = null)
|
||||
{
|
||||
parameter ??= GetDefaultParameter();
|
||||
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
ArgumentNullException.ThrowIfNull(prompt);
|
||||
ArgumentNullException.ThrowIfNull(image);
|
||||
ArgumentNullException.ThrowIfNull(mask);
|
||||
|
||||
parameter.Validate();
|
||||
|
||||
if (image.Width != mask.Width) throw new ArgumentException("The mask needs to have the same with as the image.", nameof(mask));
|
||||
if (image.Height != mask.Height) throw new ArgumentException("The mask needs to have the same height as the image.", nameof(mask));
|
||||
|
||||
// DarthAffe 10.08.2024: HPPH does currently not support monochrome images, that's why we need to convert it here. We're going for the simple conversion as the source image is supposed to be monochrome anyway.
|
||||
Span<byte> maskBuffer = new byte[image.Width * image.Height];
|
||||
for (int y = 0; y < image.Height; y++)
|
||||
for (int x = 0; x < image.Width; x++)
|
||||
{
|
||||
IColor color = mask[x, y];
|
||||
maskBuffer[(image.Width * y) + x] = (byte)Math.Round((color.R + color.G + color.B) / 3.0);
|
||||
}
|
||||
|
||||
return InternalImageToImage(prompt, image, maskBuffer, parameter);
|
||||
}
|
||||
|
||||
public IImage<ColorRGB> Edit(string prompt, IImage[] refImages, DiffusionParameter? parameter = null)
|
||||
{
|
||||
parameter ??= GetDefaultParameter();
|
||||
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
ArgumentNullException.ThrowIfNull(prompt);
|
||||
ArgumentNullException.ThrowIfNull(refImages);
|
||||
|
||||
parameter.Validate();
|
||||
|
||||
List<nint> ptrsToFree = [];
|
||||
Native.Types.sd_image_t* result = Native.generate_video(_ctx, parameter, out int frameCount);
|
||||
if (result == null) return [];
|
||||
|
||||
try
|
||||
{
|
||||
NativeParameters nativeParameters = PrefillParameters(prompt, parameter);
|
||||
SetControlNetParameters(ref nativeParameters, parameter, ptrsToFree);
|
||||
|
||||
Native.sd_image_t[] nativeRefImages = new Native.sd_image_t[refImages.Length];
|
||||
|
||||
for (int i = 0; i < refImages.Length; i++)
|
||||
{
|
||||
IImage image = refImages[i];
|
||||
if (image is not IImage<ColorRGB> refImage)
|
||||
refImage = image.ConvertTo<ColorRGB>();
|
||||
|
||||
nativeRefImages[i] = refImage.ToSdImage(out nint dataPtr);
|
||||
ptrsToFree.Add(dataPtr);
|
||||
}
|
||||
|
||||
fixed (Native.sd_image_t* nativeRefImagesPtr = nativeRefImages)
|
||||
{
|
||||
nativeParameters.ref_images = nativeRefImagesPtr;
|
||||
nativeParameters.ref_images_count = nativeRefImages.Length;
|
||||
|
||||
Native.sd_image_t* result = Edit(nativeParameters);
|
||||
|
||||
return ImageHelper.ToImage(result);
|
||||
}
|
||||
return ImageHelper.ToImageArray(result, frameCount);
|
||||
}
|
||||
finally
|
||||
{
|
||||
foreach (nint ptr in ptrsToFree)
|
||||
Marshal.FreeHGlobal(ptr);
|
||||
ImageHelper.Free(result, frameCount);
|
||||
}
|
||||
}
|
||||
|
||||
private Image<ColorRGB> InternalImageToImage(string prompt, IImage image, Span<byte> mask, DiffusionParameter parameter)
|
||||
{
|
||||
List<nint> ptrsToFree = [];
|
||||
|
||||
try
|
||||
{
|
||||
NativeParameters nativeParameters = PrefillParameters(prompt, parameter);
|
||||
SetControlNetParameters(ref nativeParameters, parameter, ptrsToFree);
|
||||
|
||||
if (image is not IImage<ColorRGB> refImage)
|
||||
refImage = image.ConvertTo<ColorRGB>();
|
||||
|
||||
nativeParameters.init_image = refImage.ToSdImage(out nint imagePtr);
|
||||
ptrsToFree.Add(imagePtr);
|
||||
|
||||
fixed (byte* maskPtr = mask)
|
||||
{
|
||||
Native.sd_image_t maskImage = new()
|
||||
{
|
||||
width = (uint)refImage.Width,
|
||||
height = (uint)refImage.Height,
|
||||
channel = 1,
|
||||
data = maskPtr
|
||||
};
|
||||
nativeParameters.mask_image = maskImage;
|
||||
|
||||
Native.sd_image_t* result = Img2Img(nativeParameters);
|
||||
|
||||
return ImageHelper.ToImage(result);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
foreach (nint ptr in ptrsToFree)
|
||||
Marshal.FreeHGlobal(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
private static NativeParameters PrefillParameters(string prompt, DiffusionParameter parameter)
|
||||
=> new()
|
||||
{
|
||||
prompt = prompt,
|
||||
negative_prompt = parameter.NegativePrompt,
|
||||
clip_skip = parameter.ClipSkip,
|
||||
cfg_scale = parameter.CfgScale,
|
||||
guidance = parameter.Guidance,
|
||||
eta = parameter.Eta,
|
||||
width = parameter.Width,
|
||||
height = parameter.Height,
|
||||
sample_method = parameter.SampleMethod,
|
||||
sample_steps = parameter.SampleSteps,
|
||||
seed = parameter.Seed,
|
||||
batch_count = 1,
|
||||
control_cond = null,
|
||||
control_strength = 0,
|
||||
style_strength = parameter.PhotoMaker.StyleRatio,
|
||||
normalize_input = parameter.PhotoMaker.NormalizeInput,
|
||||
input_id_images_path = parameter.PhotoMaker.InputIdImageDirectory,
|
||||
skip_layers = parameter.SkipLayers,
|
||||
skip_layers_count = parameter.SkipLayers.Length,
|
||||
slg_scale = parameter.SlgScale,
|
||||
skip_layer_start = parameter.SkipLayerStart,
|
||||
skip_layer_end = parameter.SkipLayerEnd,
|
||||
strength = parameter.Strength,
|
||||
};
|
||||
|
||||
private static void SetControlNetParameters(ref NativeParameters nativeParameters, DiffusionParameter parameter, List<nint> ptrsToFree)
|
||||
{
|
||||
if (!parameter.ControlNet.IsEnabled) return;
|
||||
if (parameter.ControlNet.Image == null) return;
|
||||
|
||||
if (parameter.ControlNet.Image is not IImage<ColorRGB> controlNetImage)
|
||||
controlNetImage = parameter.ControlNet.Image!.ConvertTo<ColorRGB>();
|
||||
|
||||
Native.sd_image_t* nativeControlNetImage = controlNetImage.ToSdImagePtr(out nint controlNetImagePtr);
|
||||
ptrsToFree.Add(controlNetImagePtr);
|
||||
ptrsToFree.Add((nint)nativeControlNetImage);
|
||||
|
||||
nativeParameters.control_cond = nativeControlNetImage;
|
||||
nativeParameters.control_strength = parameter.ControlNet.Strength;
|
||||
|
||||
if (parameter.ControlNet.CannyPreprocess)
|
||||
{
|
||||
nativeParameters.control_cond->data = Native.preprocess_canny(nativeParameters.control_cond->data,
|
||||
parameter.Width,
|
||||
parameter.Height,
|
||||
parameter.ControlNet.CannyHighThreshold,
|
||||
parameter.ControlNet.CannyLowThreshold,
|
||||
parameter.ControlNet.CannyWeak,
|
||||
parameter.ControlNet.CannyStrong,
|
||||
parameter.ControlNet.CannyInverse);
|
||||
ptrsToFree.Add((nint)nativeParameters.control_cond->data);
|
||||
}
|
||||
}
|
||||
|
||||
private Native.sd_image_t* Txt2Img(NativeParameters parameter)
|
||||
=> Native.txt2img(_ctx,
|
||||
parameter.prompt,
|
||||
parameter.negative_prompt,
|
||||
parameter.clip_skip,
|
||||
parameter.cfg_scale,
|
||||
parameter.guidance,
|
||||
parameter.eta,
|
||||
parameter.width,
|
||||
parameter.height,
|
||||
parameter.sample_method,
|
||||
parameter.sample_steps,
|
||||
parameter.seed,
|
||||
parameter.batch_count,
|
||||
parameter.control_cond,
|
||||
parameter.control_strength,
|
||||
parameter.style_strength,
|
||||
parameter.normalize_input,
|
||||
parameter.input_id_images_path,
|
||||
parameter.skip_layers,
|
||||
parameter.skip_layers_count,
|
||||
parameter.slg_scale,
|
||||
parameter.skip_layer_start,
|
||||
parameter.skip_layer_end
|
||||
);
|
||||
|
||||
private Native.sd_image_t* Img2Img(NativeParameters parameter)
|
||||
=> Native.img2img(_ctx,
|
||||
parameter.init_image,
|
||||
parameter.mask_image,
|
||||
parameter.prompt,
|
||||
parameter.negative_prompt,
|
||||
parameter.clip_skip,
|
||||
parameter.cfg_scale,
|
||||
parameter.guidance,
|
||||
parameter.width,
|
||||
parameter.height,
|
||||
parameter.sample_method,
|
||||
parameter.sample_steps,
|
||||
parameter.strength,
|
||||
parameter.seed,
|
||||
parameter.batch_count,
|
||||
parameter.control_cond,
|
||||
parameter.control_strength,
|
||||
parameter.style_strength,
|
||||
parameter.normalize_input,
|
||||
parameter.input_id_images_path,
|
||||
parameter.skip_layers,
|
||||
parameter.skip_layers_count,
|
||||
parameter.slg_scale,
|
||||
parameter.skip_layer_start,
|
||||
parameter.skip_layer_end
|
||||
);
|
||||
|
||||
private Native.sd_image_t* Edit(NativeParameters parameter)
|
||||
=> Native.edit(_ctx,
|
||||
parameter.ref_images,
|
||||
parameter.ref_images_count,
|
||||
parameter.prompt,
|
||||
parameter.negative_prompt,
|
||||
parameter.clip_skip,
|
||||
parameter.cfg_scale,
|
||||
parameter.guidance,
|
||||
parameter.eta,
|
||||
parameter.width,
|
||||
parameter.height,
|
||||
parameter.sample_method,
|
||||
parameter.sample_steps,
|
||||
parameter.strength,
|
||||
parameter.seed,
|
||||
parameter.batch_count,
|
||||
parameter.control_cond,
|
||||
parameter.control_strength,
|
||||
parameter.style_strength,
|
||||
parameter.normalize_input,
|
||||
parameter.skip_layers,
|
||||
parameter.skip_layers_count,
|
||||
parameter.slg_scale,
|
||||
parameter.skip_layer_start,
|
||||
parameter.skip_layer_end
|
||||
);
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed) return;
|
||||
@ -382,37 +95,4 @@ public sealed unsafe class DiffusionModel : IDisposable
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private ref struct NativeParameters
|
||||
{
|
||||
internal string prompt;
|
||||
internal string negative_prompt;
|
||||
internal int clip_skip;
|
||||
internal float cfg_scale;
|
||||
internal float guidance;
|
||||
internal float eta;
|
||||
internal int width;
|
||||
internal int height;
|
||||
internal Sampler sample_method;
|
||||
internal int sample_steps;
|
||||
internal long seed;
|
||||
internal int batch_count;
|
||||
internal Native.sd_image_t* control_cond;
|
||||
internal float control_strength;
|
||||
internal float style_strength;
|
||||
internal bool normalize_input;
|
||||
internal string input_id_images_path;
|
||||
internal int[] skip_layers;
|
||||
internal int skip_layers_count;
|
||||
internal float slg_scale;
|
||||
internal float skip_layer_start;
|
||||
internal float skip_layer_end;
|
||||
|
||||
internal Native.sd_image_t init_image;
|
||||
internal Native.sd_image_t mask_image;
|
||||
|
||||
internal Native.sd_image_t* ref_images;
|
||||
internal int ref_images_count;
|
||||
internal float strength;
|
||||
}
|
||||
}
|
||||
40
StableDiffusion.NET/Models/Parameter/CannyParameter.cs
Normal file
40
StableDiffusion.NET/Models/Parameter/CannyParameter.cs
Normal file
@ -0,0 +1,40 @@
|
||||
using HPPH;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
[PublicAPI]
|
||||
public sealed class CannyParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// the image to process
|
||||
/// </summary>
|
||||
public IImage? Image { get; set; } = null;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public float HighThreshold { get; set; } = 0.08f;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public float LowThreshold { get; set; } = 0.08f;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public float Weak { get; set; } = 0.8f;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public float Strong { get; set; } = 1.0f;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool Inverse { get; set; } = false;
|
||||
|
||||
public static CannyParameter Create() => new();
|
||||
}
|
||||
@ -1,13 +1,9 @@
|
||||
using HPPH;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
[PublicAPI]
|
||||
public sealed class ControlNetParameter
|
||||
{
|
||||
public bool IsEnabled => Image != null;
|
||||
|
||||
/// <summary>
|
||||
/// image condition, control net
|
||||
/// </summary>
|
||||
@ -19,33 +15,5 @@ public sealed class ControlNetParameter
|
||||
/// </summary>
|
||||
public float Strength { get; set; } = 0.9f;
|
||||
|
||||
/// <summary>
|
||||
/// apply canny preprocessor (edge detection)
|
||||
/// </summary>
|
||||
public bool CannyPreprocess { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public float CannyHighThreshold { get; set; } = 0.08f;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public float CannyLowThreshold { get; set; } = 0.08f;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public float CannyWeak { get; set; } = 0.8f;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public float CannyStrong { get; set; } = 1.0f;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public bool CannyInverse { get; set; } = false;
|
||||
internal ControlNetParameter() { }
|
||||
}
|
||||
@ -1,9 +1,10 @@
|
||||
namespace StableDiffusion.NET;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
public sealed class DiffusionModelParameter : IDiffusionModelParameter, IQuantizedModelParameter, IPhotomakerModelParameter
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
[PublicAPI]
|
||||
public sealed class DiffusionModelParameter
|
||||
{
|
||||
public DiffusionModelType DiffusionModelType { get; set; } = DiffusionModelType.None;
|
||||
|
||||
/// <summary>
|
||||
/// path to vae
|
||||
/// </summary>
|
||||
@ -40,21 +41,25 @@ public sealed class DiffusionModelParameter : IDiffusionModelParameter, IQuantiz
|
||||
/// </summary>
|
||||
public bool VaeDecodeOnly { get; set; } = false;
|
||||
|
||||
public bool FreeParamsImmediately { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// process vae in tiles to reduce memory usage
|
||||
/// </summary>
|
||||
public bool VaeTiling { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// keep controlnet in cpu
|
||||
/// </summary>
|
||||
public bool KeepControlNetOnCPU { get; set; } = false;
|
||||
public bool OffloadParamsToCPU { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// keep clip in cpu (for low vram)
|
||||
/// </summary>
|
||||
public bool KeepClipOnCPU { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// keep controlnet in cpu
|
||||
/// </summary>
|
||||
public bool KeepControlNetOnCPU { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// keep vae in cpu (for low vram)
|
||||
/// </summary>
|
||||
@ -67,33 +72,45 @@ public sealed class DiffusionModelParameter : IDiffusionModelParameter, IQuantiz
|
||||
/// </summary>
|
||||
public bool FlashAttention { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// use Conv2d direct in the diffusion model
|
||||
/// This might crash if it is not supported by the backend.
|
||||
/// </summary>
|
||||
public bool DiffusionConvDirect { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// use Conv2d direct in the vae model (should improve the performance)
|
||||
/// This might crash if it is not supported by the backend.
|
||||
/// </summary>
|
||||
public bool VaeConvDirect { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// RNG (default: Standard)
|
||||
/// </summary>
|
||||
public RngType RngType { get; set; } = RngType.Standard;
|
||||
|
||||
/// <summary>
|
||||
/// Denoiser sigma schedule (default: Default)
|
||||
/// </summary>
|
||||
public Schedule Schedule { get; set; } = Schedule.Default;
|
||||
public Prediction Prediction { get; set; } = Prediction.Default;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// quantizes on load
|
||||
/// not really useful in most cases
|
||||
/// </summary>
|
||||
public Quantization Quantization { get; set; } = Quantization.Unspecified;
|
||||
|
||||
// SD <= 3 only
|
||||
/// <summary>
|
||||
/// path to full model
|
||||
/// </summary>
|
||||
public string ModelPath { get; set; } = string.Empty;
|
||||
public float FlowShift { get; set; } = 0;
|
||||
|
||||
public bool ForceSdxlVaeConvScale { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// path to PHOTOMAKER stacked id embeddings
|
||||
/// </summary>
|
||||
public string StackedIdEmbeddingsDirectory { get; set; } = string.Empty;
|
||||
|
||||
// Flux & SD3.5 only
|
||||
/// <summary>
|
||||
/// path to full model
|
||||
/// </summary>
|
||||
public string ModelPath { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// path to the standalone diffusion model
|
||||
/// </summary>
|
||||
@ -104,19 +121,26 @@ public sealed class DiffusionModelParameter : IDiffusionModelParameter, IQuantiz
|
||||
/// </summary>
|
||||
public string ClipLPath { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// path to the clip-g text encoder
|
||||
/// </summary>
|
||||
public string ClipGPath { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// path to the the t5xxl text encoder
|
||||
/// </summary>
|
||||
public string T5xxlPath { get; set; } = string.Empty;
|
||||
|
||||
// Flux Chroma specific
|
||||
public string Qwen2VLPath { get; set; } = string.Empty;
|
||||
|
||||
public string Qwen2VLVisionPath { get; set; } = string.Empty;
|
||||
|
||||
public string ClipVisionPath { get; set; } = string.Empty;
|
||||
public string HighNoiseDiffusionModelPath { get; set; } = string.Empty;
|
||||
|
||||
public bool ChromaUseDitMap { get; set; } = true;
|
||||
public bool ChromaEnableT5Map { get; set; } = false;
|
||||
public int ChromaT5MaskPad { get; set; } = 1;
|
||||
|
||||
// SD3.5 only
|
||||
/// <summary>
|
||||
/// path to the clip-g text encoder
|
||||
/// </summary>
|
||||
public string ClipGPath { get; set; } = string.Empty;
|
||||
public static DiffusionModelParameter Create() => new();
|
||||
}
|
||||
@ -1,99 +0,0 @@
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
[PublicAPI]
|
||||
public sealed class DiffusionParameter
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public static DiffusionParameter SD1Default => new() { Width = 512, Height = 512, CfgScale = 7.5f, Guidance = 1f, SampleSteps = 25, SampleMethod = Sampler.Euler_A };
|
||||
public static DiffusionParameter SDXLDefault => new() { Width = 1024, Height = 1024, CfgScale = 7f, Guidance = 1f, SampleSteps = 30, SampleMethod = Sampler.Euler_A };
|
||||
public static DiffusionParameter SD3_5Default => new() { Width = 1024, Height = 1024, CfgScale = 4.5f, Guidance = 1f, SampleSteps = 20, SampleMethod = Sampler.Euler };
|
||||
public static DiffusionParameter FluxDefault => new() { Width = 1024, Height = 1024, CfgScale = 1, Guidance = 3.5f, SampleSteps = 20, SampleMethod = Sampler.Euler };
|
||||
|
||||
/// <summary>
|
||||
/// the negative prompt (default: "");
|
||||
/// </summary>
|
||||
public string NegativePrompt { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// image width, in pixel space (default: 512)
|
||||
/// </summary>
|
||||
public int Width { get; set; } = 512;
|
||||
|
||||
/// <summary>
|
||||
/// image height, in pixel space (default: 512)
|
||||
/// </summary>
|
||||
public int Height { get; set; } = 512;
|
||||
|
||||
/// <summary>
|
||||
/// sampling method (default: Euler_A)
|
||||
/// </summary>
|
||||
public Sampler SampleMethod { get; set; } = Sampler.Euler_A;
|
||||
|
||||
/// <summary>
|
||||
/// number of sample steps (default: 25)
|
||||
/// </summary>
|
||||
public int SampleSteps { get; set; } = 25;
|
||||
|
||||
/// <summary>
|
||||
/// RNG seed. use -1 for a random seed (default: -1)
|
||||
/// </summary>
|
||||
public long Seed { get; set; } = -1;
|
||||
|
||||
/// <summary>
|
||||
/// strength for noising/unnoising (default: 0.7)
|
||||
/// </summary>
|
||||
public float Strength { get; set; } = 0.7f;
|
||||
|
||||
/// <summary>
|
||||
/// ignore last layers of CLIP network; 1 ignores none, 2 ignores one layer (default: -1)
|
||||
/// -1 represents unspecified, will be 1 for SD1.x, 2 for SD2.x
|
||||
/// </summary>
|
||||
public int ClipSkip { get; set; } = -1;
|
||||
|
||||
/// <summary>
|
||||
/// skip layer guidance (SLG) scale, only for DiT models: (default: 0)
|
||||
/// 0 means disabled, a value of 2.5 is nice for sd3.5 medium
|
||||
/// </summary>
|
||||
public float SlgScale { get; set; } = 0f;
|
||||
|
||||
/// <summary>
|
||||
/// Layers to skip for SLG steps: (default: [7,8,9])
|
||||
/// </summary>
|
||||
public int[] SkipLayers { get; set; } = [7, 8, 9];
|
||||
|
||||
/// <summary>
|
||||
/// SLG enabling point: (default: 0.01)
|
||||
/// </summary>
|
||||
public float SkipLayerStart { get; set; } = 0.01f;
|
||||
|
||||
/// <summary>
|
||||
/// SLG disabling point: (default: 0.2)
|
||||
/// </summary>
|
||||
public float SkipLayerEnd { get; set; } = 0.2f;
|
||||
|
||||
public ControlNetParameter ControlNet { get; } = new();
|
||||
|
||||
// Stable Diffusion only
|
||||
/// <summary>
|
||||
/// unconditional guidance scale: (default: 7.5)
|
||||
/// </summary>
|
||||
public float CfgScale { get; set; } = 7.5f;
|
||||
|
||||
public PhotoMakerParameter PhotoMaker { get; } = new();
|
||||
|
||||
// Flux only
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public float Guidance { get; set; } = 3.5f;
|
||||
|
||||
/// <summary>
|
||||
/// eta in DDIM, only for DDIM and TCD (default: 0)
|
||||
/// </summary>
|
||||
public float Eta { get; set; } = 0f;
|
||||
|
||||
#endregion
|
||||
}
|
||||
@ -0,0 +1,287 @@
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
[PublicAPI]
|
||||
public static class DiffusionModelBuilderExtension
|
||||
{
|
||||
public static DiffusionModelParameter WithVae(this DiffusionModelParameter parameter, string vaePath)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(vaePath);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(parameter.TaesdPath)) throw new ArgumentException("TAESD is already enabled. VAE and TAESD are mutually exclusive.", nameof(vaePath));
|
||||
|
||||
parameter.VaePath = vaePath;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionModelParameter WithTaesd(this DiffusionModelParameter parameter, string taesdPath)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(taesdPath);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(parameter.VaePath)) throw new ArgumentException("VAE is already enabled. TAESD and VAE are mutually exclusive.", nameof(taesdPath));
|
||||
|
||||
parameter.TaesdPath = taesdPath;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionModelParameter WithLoraSupport(this DiffusionModelParameter parameter, string loraModelDirectory)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(loraModelDirectory);
|
||||
|
||||
parameter.LoraModelDirectory = loraModelDirectory;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionModelParameter WithEmbeddingSupport(this DiffusionModelParameter parameter, string embeddingsDirectory)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(embeddingsDirectory);
|
||||
|
||||
parameter.EmbeddingsDirectory = embeddingsDirectory;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionModelParameter WithControlNet(this DiffusionModelParameter parameter, string controlNetPath)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(controlNetPath);
|
||||
|
||||
parameter.ControlNetPath = controlNetPath;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionModelParameter WithoutMultithreading(this DiffusionModelParameter parameter)
|
||||
{
|
||||
parameter.ThreadCount = 1;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionModelParameter WithMultithreading(this DiffusionModelParameter parameter, int threadCount = 0)
|
||||
{
|
||||
ArgumentOutOfRangeException.ThrowIfLessThan(threadCount, 0, nameof(threadCount));
|
||||
|
||||
if (threadCount == 0) threadCount = Environment.ProcessorCount;
|
||||
|
||||
parameter.ThreadCount = threadCount;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionModelParameter WithVaeDecodeOnly(this DiffusionModelParameter parameter, bool vaeDecodeOnly = true)
|
||||
{
|
||||
parameter.VaeDecodeOnly = vaeDecodeOnly;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionModelParameter WithImmediatelyFreedParams(this DiffusionModelParameter parameter, bool immediatelyFreedParams = true)
|
||||
{
|
||||
parameter.FreeParamsImmediately = immediatelyFreedParams;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionModelParameter WithVaeTiling(this DiffusionModelParameter parameter, bool vaeTiling = true)
|
||||
{
|
||||
parameter.VaeTiling = vaeTiling;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionModelParameter WithOffloadedParamsToCPU(this DiffusionModelParameter parameter, bool offloadParamsToCPU = true)
|
||||
{
|
||||
parameter.OffloadParamsToCPU = offloadParamsToCPU;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionModelParameter WithClipNetOnCpu(this DiffusionModelParameter parameter, bool keepClipNetOnCpu = true)
|
||||
{
|
||||
parameter.KeepClipOnCPU = keepClipNetOnCpu;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionModelParameter WithControlNetOnCpu(this DiffusionModelParameter parameter, bool keepControlNetOnCpu = true)
|
||||
{
|
||||
parameter.KeepControlNetOnCPU = keepControlNetOnCpu;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionModelParameter WithVaeOnCpu(this DiffusionModelParameter parameter, bool keepVaeOnCpu = true)
|
||||
{
|
||||
parameter.KeepVaeOnCPU = keepVaeOnCpu;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionModelParameter WithFlashAttention(this DiffusionModelParameter parameter, bool flashAttention = true)
|
||||
{
|
||||
parameter.FlashAttention = flashAttention;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionModelParameter WithDiffusionConvDirect(this DiffusionModelParameter parameter, bool diffusionConvDirect = true)
|
||||
{
|
||||
parameter.DiffusionConvDirect = diffusionConvDirect;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionModelParameter WithVaeConvDirect(this DiffusionModelParameter parameter, bool vaeConvDirect = true)
|
||||
{
|
||||
parameter.VaeConvDirect = vaeConvDirect;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionModelParameter WithRngType(this DiffusionModelParameter parameter, RngType rngType)
|
||||
{
|
||||
if (!Enum.IsDefined(rngType)) throw new ArgumentOutOfRangeException(nameof(rngType));
|
||||
|
||||
parameter.RngType = rngType;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionModelParameter WithPrediction(this DiffusionModelParameter parameter, Prediction prediction)
|
||||
{
|
||||
parameter.Prediction = prediction;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionModelParameter WithQuantization(this DiffusionModelParameter parameter, Quantization quantization)
|
||||
{
|
||||
if (!Enum.IsDefined(quantization)) throw new ArgumentOutOfRangeException(nameof(quantization));
|
||||
|
||||
parameter.Quantization = quantization;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionModelParameter WithFlowShift(this DiffusionModelParameter parameter, float flowShift)
|
||||
{
|
||||
parameter.FlowShift = flowShift;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionModelParameter WithForcedSdxlVaeConvScale(this DiffusionModelParameter parameter, bool forcedScale = true)
|
||||
{
|
||||
parameter.ForceSdxlVaeConvScale = forcedScale;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionModelParameter WithPhotomaker(this DiffusionModelParameter parameter, string stackedIdEmbeddingsDirectory)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(stackedIdEmbeddingsDirectory, nameof(stackedIdEmbeddingsDirectory));
|
||||
|
||||
parameter.StackedIdEmbeddingsDirectory = stackedIdEmbeddingsDirectory;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionModelParameter WithModelPath(this DiffusionModelParameter parameter, string modelPath)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(modelPath);
|
||||
|
||||
parameter.ModelPath = modelPath;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionModelParameter WithDiffusionModelPath(this DiffusionModelParameter parameter, string diffusionModelPath)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(diffusionModelPath);
|
||||
|
||||
parameter.DiffusionModelPath = diffusionModelPath;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionModelParameter WithClipLPath(this DiffusionModelParameter parameter, string clipLPath)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(clipLPath);
|
||||
|
||||
parameter.ClipLPath = clipLPath;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionModelParameter WithClipGPath(this DiffusionModelParameter parameter, string clipGPath)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(clipGPath);
|
||||
|
||||
parameter.ClipGPath = clipGPath;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionModelParameter WithT5xxlPath(this DiffusionModelParameter parameter, string t5xxlPath)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(t5xxlPath);
|
||||
|
||||
parameter.T5xxlPath = t5xxlPath;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionModelParameter WithQwen2VLPath(this DiffusionModelParameter parameter, string qwen2VLPath)
|
||||
{
|
||||
parameter.Qwen2VLPath = qwen2VLPath;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionModelParameter WithQwen2VLVisionPath(this DiffusionModelParameter parameter, string qwen2VLVisionPath)
|
||||
{
|
||||
parameter.Qwen2VLVisionPath = qwen2VLVisionPath;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionModelParameter WithClipVisionPath(this DiffusionModelParameter parameter, string clipVisionPath)
|
||||
{
|
||||
parameter.ClipVisionPath = clipVisionPath;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionModelParameter WithHighNoiseDiffusionModelPath(this DiffusionModelParameter parameter, string highNoiseDiffusionModelPath)
|
||||
{
|
||||
parameter.HighNoiseDiffusionModelPath = highNoiseDiffusionModelPath;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionModelParameter UseChromaDitMap(this DiffusionModelParameter parameter, bool useChromaDitMap = true)
|
||||
{
|
||||
parameter.ChromaUseDitMap = useChromaDitMap;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionModelParameter EnableChromaT5Map(this DiffusionModelParameter parameter, bool enableChromaT5Map = true)
|
||||
{
|
||||
parameter.ChromaEnableT5Map = enableChromaT5Map;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionModelParameter WithChromaT5MaskPad(this DiffusionModelParameter parameter, int chromaT5MaskPad)
|
||||
{
|
||||
parameter.ChromaT5MaskPad = chromaT5MaskPad;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
}
|
||||
@ -1,149 +0,0 @@
|
||||
using HPPH;
|
||||
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
public static class DiffusionParameterExtension
|
||||
{
|
||||
public static DiffusionParameter WithSize(this DiffusionParameter parameter, int? width = null, int? height = null)
|
||||
{
|
||||
if (width != null)
|
||||
parameter.Width = width.Value;
|
||||
|
||||
if (height != null)
|
||||
parameter.Height = height.Value;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionParameter WithSampler(this DiffusionParameter parameter, Sampler sampler)
|
||||
{
|
||||
parameter.SampleMethod = sampler;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionParameter WithSteps(this DiffusionParameter parameter, int steps)
|
||||
{
|
||||
parameter.SampleSteps = steps;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionParameter WithSeed(this DiffusionParameter parameter, long seed)
|
||||
{
|
||||
parameter.Seed = seed;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionParameter WithClipSkip(this DiffusionParameter parameter, int clipSkip)
|
||||
{
|
||||
parameter.ClipSkip = clipSkip;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionParameter WithCfg(this DiffusionParameter parameter, float cfg)
|
||||
{
|
||||
parameter.CfgScale = cfg;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionParameter WithGuidance(this DiffusionParameter parameter, float guidance)
|
||||
{
|
||||
parameter.Guidance = guidance;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionParameter WithNegativePrompt(this DiffusionParameter parameter, string negativePrompt)
|
||||
{
|
||||
parameter.NegativePrompt = negativePrompt;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionParameter WithStrength(this DiffusionParameter parameter, float strength)
|
||||
{
|
||||
parameter.Strength = strength;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionParameter WithSlgScale(this DiffusionParameter parameter, float slgScale)
|
||||
{
|
||||
parameter.SlgScale = slgScale;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionParameter WithSkipLayers(this DiffusionParameter parameter, int[] layers)
|
||||
{
|
||||
parameter.SkipLayers = layers;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionParameter WithSkipLayerStart(this DiffusionParameter parameter, float skipLayerStart)
|
||||
{
|
||||
parameter.SkipLayerStart = skipLayerStart;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionParameter WithSkipLayerEnd(this DiffusionParameter parameter, float skipLayerEnd)
|
||||
{
|
||||
parameter.SkipLayerEnd = skipLayerEnd;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionParameter WithControlNet(this DiffusionParameter parameter, IImage image, float? strength = null)
|
||||
{
|
||||
parameter.ControlNet.Image = image;
|
||||
|
||||
if (strength != null)
|
||||
parameter.ControlNet.Strength = strength.Value;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionParameter WithCannyPreprocessing(this DiffusionParameter parameter,
|
||||
float? cannyHighThreshold = null, float? cannyLowThreshold = null,
|
||||
float? cannyWeak = null, float? cannyStrong = null,
|
||||
bool? cannyInverse = null)
|
||||
{
|
||||
parameter.ControlNet.CannyPreprocess = true;
|
||||
|
||||
if (cannyHighThreshold != null)
|
||||
parameter.ControlNet.CannyHighThreshold = cannyHighThreshold.Value;
|
||||
|
||||
if (cannyLowThreshold != null)
|
||||
parameter.ControlNet.CannyLowThreshold = cannyLowThreshold.Value;
|
||||
|
||||
if (cannyWeak != null)
|
||||
parameter.ControlNet.CannyWeak = cannyWeak.Value;
|
||||
|
||||
if (cannyStrong != null)
|
||||
parameter.ControlNet.CannyStrong = cannyStrong.Value;
|
||||
|
||||
if (cannyInverse != null)
|
||||
parameter.ControlNet.CannyInverse = cannyInverse.Value;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static DiffusionParameter WithPhotomaker(this DiffusionParameter parameter, string inputIdImageDirectory, float? styleRatio = null, bool? normalizeInput = null)
|
||||
{
|
||||
parameter.PhotoMaker.InputIdImageDirectory = inputIdImageDirectory;
|
||||
|
||||
if (styleRatio != null)
|
||||
parameter.PhotoMaker.StyleRatio = styleRatio.Value;
|
||||
|
||||
if (normalizeInput != null)
|
||||
parameter.PhotoMaker.NormalizeInput = normalizeInput.Value;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,302 @@
|
||||
using HPPH;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
[PublicAPI]
|
||||
public static class ImageGenerationParameterExtension
|
||||
{
|
||||
public static ImageGenerationParameter WithPrompt(this ImageGenerationParameter parameter, string prompt)
|
||||
{
|
||||
parameter.Prompt = prompt;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static ImageGenerationParameter WithNegativePrompt(this ImageGenerationParameter parameter, string negativePrompt)
|
||||
{
|
||||
parameter.NegativePrompt = negativePrompt;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static ImageGenerationParameter WithClipSkip(this ImageGenerationParameter parameter, int clipSkip)
|
||||
{
|
||||
parameter.ClipSkip = clipSkip;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static ImageGenerationParameter WithInitImage(this ImageGenerationParameter parameter, IImage image)
|
||||
{
|
||||
parameter.InitImage = image;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static ImageGenerationParameter WithRefImages(this ImageGenerationParameter parameter, params IImage[] images)
|
||||
{
|
||||
parameter.RefImages = images;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static ImageGenerationParameter WithMaskImage(this ImageGenerationParameter parameter, IImage image)
|
||||
{
|
||||
parameter.MaskImage = image;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static ImageGenerationParameter WithRefIndexIncrease(this ImageGenerationParameter parameter, bool refIndexIncrease = true)
|
||||
{
|
||||
parameter.IncreaseRefIndex = refIndexIncrease;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static ImageGenerationParameter WithRefImageAutoResize(this ImageGenerationParameter parameter, bool refImageAutoResize = true)
|
||||
{
|
||||
parameter.AutoResizeRefImage = refImageAutoResize;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static ImageGenerationParameter WithSize(this ImageGenerationParameter parameter, int? width = null, int? height = null)
|
||||
{
|
||||
if (width != null)
|
||||
parameter.Width = width.Value;
|
||||
|
||||
if (height != null)
|
||||
parameter.Height = height.Value;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
#region SampleParameter
|
||||
|
||||
#region Guidance
|
||||
|
||||
public static ImageGenerationParameter WithCfg(this ImageGenerationParameter parameter, float cfg)
|
||||
{
|
||||
parameter.WithTxtCfg(cfg);
|
||||
parameter.WithImgCfg(cfg);
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static ImageGenerationParameter WithTxtCfg(this ImageGenerationParameter parameter, float txtCfg)
|
||||
{
|
||||
parameter.SampleParameter.Guidance.TxtCfg = txtCfg;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static ImageGenerationParameter WithImgCfg(this ImageGenerationParameter parameter, float imgCfg)
|
||||
{
|
||||
parameter.SampleParameter.Guidance.ImgCfg = imgCfg;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static ImageGenerationParameter WithMinCfg(this ImageGenerationParameter parameter, float minCfg)
|
||||
{
|
||||
parameter.SampleParameter.Guidance.MinCfg = minCfg;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static ImageGenerationParameter WithGuidance(this ImageGenerationParameter parameter, float guidance)
|
||||
{
|
||||
parameter.SampleParameter.Guidance.DistilledGuidance = guidance;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
#region Slg
|
||||
|
||||
public static ImageGenerationParameter WithSkipLayers(this ImageGenerationParameter parameter, int[] layers)
|
||||
{
|
||||
parameter.SampleParameter.Guidance.Slg.Layers = layers;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static ImageGenerationParameter WithSkipLayerStart(this ImageGenerationParameter parameter, float skipLayerStart)
|
||||
{
|
||||
parameter.SampleParameter.Guidance.Slg.SkipLayerStart = skipLayerStart;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static ImageGenerationParameter WithSkipLayerEnd(this ImageGenerationParameter parameter, float skipLayerEnd)
|
||||
{
|
||||
parameter.SampleParameter.Guidance.Slg.SkipLayerEnd = skipLayerEnd;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static ImageGenerationParameter WithSlgScale(this ImageGenerationParameter parameter, float slgScale)
|
||||
{
|
||||
parameter.SampleParameter.Guidance.Slg.Scale = slgScale;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
public static ImageGenerationParameter WithScheduler(this ImageGenerationParameter parameter, Scheduler scheduler)
|
||||
{
|
||||
parameter.SampleParameter.Scheduler = scheduler;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static ImageGenerationParameter WithSampler(this ImageGenerationParameter parameter, Sampler sampler)
|
||||
{
|
||||
parameter.SampleParameter.SampleMethod = sampler;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static ImageGenerationParameter WithSteps(this ImageGenerationParameter parameter, int steps)
|
||||
{
|
||||
parameter.SampleParameter.SampleSteps = steps;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static ImageGenerationParameter WithEta(this ImageGenerationParameter parameter, float eta)
|
||||
{
|
||||
parameter.SampleParameter.Eta = eta;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static ImageGenerationParameter WithShiftedTimestep(this ImageGenerationParameter parameter, int shiftedTimestep)
|
||||
{
|
||||
parameter.SampleParameter.ShiftedTimestep = shiftedTimestep;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public static ImageGenerationParameter WithStrength(this ImageGenerationParameter parameter, float strength)
|
||||
{
|
||||
parameter.Strength = strength;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static ImageGenerationParameter WithSeed(this ImageGenerationParameter parameter, long seed)
|
||||
{
|
||||
parameter.Seed = seed;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static ImageGenerationParameter WithControlNet(this ImageGenerationParameter parameter, IImage image, float? strength = null)
|
||||
{
|
||||
parameter.ControlNet.Image = image;
|
||||
|
||||
if (strength != null)
|
||||
parameter.ControlNet.Strength = strength.Value;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static ImageGenerationParameter WithPhotomaker(this ImageGenerationParameter parameter, string inputIdImageDirectory, float? styleStrength = null, bool? normalizeInput = null)
|
||||
{
|
||||
//todo
|
||||
//parameter.PhotoMaker.InputIdImageDirectory = inputIdImageDirectory;
|
||||
|
||||
//if (styleStrength != null)
|
||||
// parameter.PhotoMaker.StyleStrength = styleStrength.Value;
|
||||
|
||||
//if (normalizeInput != null)
|
||||
// parameter.PhotoMaker.NormalizeInput = normalizeInput.Value;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
#region VaeTiling
|
||||
|
||||
public static ImageGenerationParameter WithVaeTiling(this ImageGenerationParameter parameter, bool tiling = true)
|
||||
{
|
||||
parameter.VaeTiling.IsEnabled = tiling;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static ImageGenerationParameter WithVaeTileSizeX(this ImageGenerationParameter parameter, int tileSizeX)
|
||||
{
|
||||
parameter.VaeTiling.TileSizeX = tileSizeX;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static ImageGenerationParameter WithVaeTileSizeY(this ImageGenerationParameter parameter, int tileSizeY)
|
||||
{
|
||||
parameter.VaeTiling.TileSizeY = tileSizeY;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static ImageGenerationParameter WithVaeTargetOverlap(this ImageGenerationParameter parameter, float targetOverlap)
|
||||
{
|
||||
parameter.VaeTiling.TargetOverlap = targetOverlap;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static ImageGenerationParameter WithVaeRelSizeX(this ImageGenerationParameter parameter, float relSizeX)
|
||||
{
|
||||
parameter.VaeTiling.RelSizeX = relSizeX;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static ImageGenerationParameter WithVaeRelSizeY(this ImageGenerationParameter parameter, float relSizeY)
|
||||
{
|
||||
parameter.VaeTiling.RelSizeY = relSizeY;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Defaults
|
||||
|
||||
public static ImageGenerationParameter WithSd1Defaults(this ImageGenerationParameter parameter)
|
||||
=> parameter.WithSize(512, 512)
|
||||
.WithCfg(7.5f)
|
||||
.WithGuidance(1f)
|
||||
.WithSteps(25)
|
||||
.WithSampler(Sampler.Euler_A);
|
||||
|
||||
public static ImageGenerationParameter WithSDXLDefaults(this ImageGenerationParameter parameter)
|
||||
=> parameter.WithSize(1024, 1024)
|
||||
.WithCfg(7f)
|
||||
.WithGuidance(1f)
|
||||
.WithSteps(30)
|
||||
.WithSampler(Sampler.Euler_A);
|
||||
|
||||
public static ImageGenerationParameter WithSD3_5Defaults(this ImageGenerationParameter parameter)
|
||||
=> parameter.WithSize(1024, 1024)
|
||||
.WithCfg(4.5f)
|
||||
.WithGuidance(1f)
|
||||
.WithSteps(20)
|
||||
.WithSampler(Sampler.Euler);
|
||||
|
||||
public static ImageGenerationParameter WithFluxDefaults(this ImageGenerationParameter parameter)
|
||||
=> parameter.WithSize(1024, 1024)
|
||||
.WithCfg(1f)
|
||||
.WithGuidance(3.5f)
|
||||
.WithSteps(20)
|
||||
.WithSampler(Sampler.Euler);
|
||||
|
||||
#endregion
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
[PublicAPI]
|
||||
public static class UpscaleModelBuilderExtension
|
||||
{
|
||||
public static UpscaleModelParameter WithModelPath(this UpscaleModelParameter parameter, string modelPath)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(modelPath);
|
||||
|
||||
parameter.ModelPath = modelPath;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static UpscaleModelParameter WithOffloadedParamsToCPU(this UpscaleModelParameter parameter, bool offloadParamsToCPU = true)
|
||||
{
|
||||
parameter.OffloadParamsToCPU = offloadParamsToCPU;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static UpscaleModelParameter WithoutMultithreading(this UpscaleModelParameter parameter)
|
||||
{
|
||||
parameter.ThreadCount = 1;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static UpscaleModelParameter WithMultithreading(this UpscaleModelParameter parameter, int threadCount = 0)
|
||||
{
|
||||
ArgumentOutOfRangeException.ThrowIfLessThan(threadCount, 0, nameof(threadCount));
|
||||
|
||||
if (threadCount == 0) threadCount = Environment.ProcessorCount;
|
||||
|
||||
parameter.ThreadCount = threadCount;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static UpscaleModelParameter WithConvDirect(this UpscaleModelParameter parameter, bool convDirect = true)
|
||||
{
|
||||
parameter.ConvDirect = convDirect;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,318 @@
|
||||
using HPPH;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
[PublicAPI]
|
||||
public static class VideoGenerationParameterExtension
|
||||
{
|
||||
public static VideoGenerationParameter WithPrompt(this VideoGenerationParameter parameter, string prompt)
|
||||
{
|
||||
parameter.Prompt = prompt;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static VideoGenerationParameter WithNegativePrompt(this VideoGenerationParameter parameter, string negativePrompt)
|
||||
{
|
||||
parameter.NegativePrompt = negativePrompt;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static VideoGenerationParameter WithClipSkip(this VideoGenerationParameter parameter, int clipSkip)
|
||||
{
|
||||
parameter.ClipSkip = clipSkip;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static VideoGenerationParameter WithSize(this VideoGenerationParameter parameter, int? width = null, int? height = null)
|
||||
{
|
||||
if (width != null)
|
||||
parameter.Width = width.Value;
|
||||
|
||||
if (height != null)
|
||||
parameter.Height = height.Value;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static VideoGenerationParameter WithInitImage(this VideoGenerationParameter parameter, IImage image)
|
||||
{
|
||||
parameter.InitImage = image;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static VideoGenerationParameter WithEndImage(this VideoGenerationParameter parameter, IImage image)
|
||||
{
|
||||
parameter.EndImage = image;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static VideoGenerationParameter WithControlFrames(this VideoGenerationParameter parameter, params IImage[] images)
|
||||
{
|
||||
parameter.ControlFrames = images;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
#region SampleParameter
|
||||
|
||||
#region Guidance
|
||||
|
||||
public static VideoGenerationParameter WithCfg(this VideoGenerationParameter parameter, float cfg)
|
||||
{
|
||||
parameter.WithTxtCfg(cfg);
|
||||
parameter.WithImgCfg(cfg);
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static VideoGenerationParameter WithTxtCfg(this VideoGenerationParameter parameter, float txtCfg)
|
||||
{
|
||||
parameter.SampleParameter.Guidance.TxtCfg = txtCfg;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static VideoGenerationParameter WithImgCfg(this VideoGenerationParameter parameter, float imgCfg)
|
||||
{
|
||||
parameter.SampleParameter.Guidance.ImgCfg = imgCfg;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static VideoGenerationParameter WithMinCfg(this VideoGenerationParameter parameter, float minCfg)
|
||||
{
|
||||
parameter.SampleParameter.Guidance.MinCfg = minCfg;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static VideoGenerationParameter WithGuidance(this VideoGenerationParameter parameter, float guidance)
|
||||
{
|
||||
parameter.SampleParameter.Guidance.DistilledGuidance = guidance;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
#region Slg
|
||||
|
||||
public static VideoGenerationParameter WithSkipLayers(this VideoGenerationParameter parameter, int[] layers)
|
||||
{
|
||||
parameter.SampleParameter.Guidance.Slg.Layers = layers;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static VideoGenerationParameter WithSkipLayerStart(this VideoGenerationParameter parameter, float skipLayerStart)
|
||||
{
|
||||
parameter.SampleParameter.Guidance.Slg.SkipLayerStart = skipLayerStart;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static VideoGenerationParameter WithSkipLayerEnd(this VideoGenerationParameter parameter, float skipLayerEnd)
|
||||
{
|
||||
parameter.SampleParameter.Guidance.Slg.SkipLayerEnd = skipLayerEnd;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static VideoGenerationParameter WithSlgScale(this VideoGenerationParameter parameter, float slgScale)
|
||||
{
|
||||
parameter.SampleParameter.Guidance.Slg.Scale = slgScale;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
public static VideoGenerationParameter WithScheduler(this VideoGenerationParameter parameter, Scheduler scheduler)
|
||||
{
|
||||
parameter.SampleParameter.Scheduler = scheduler;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static VideoGenerationParameter WithSampler(this VideoGenerationParameter parameter, Sampler sampler)
|
||||
{
|
||||
parameter.SampleParameter.SampleMethod = sampler;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static VideoGenerationParameter WithSteps(this VideoGenerationParameter parameter, int steps)
|
||||
{
|
||||
parameter.SampleParameter.SampleSteps = steps;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static VideoGenerationParameter WithEta(this VideoGenerationParameter parameter, float eta)
|
||||
{
|
||||
parameter.SampleParameter.Eta = eta;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static VideoGenerationParameter WithShiftedTimestep(this VideoGenerationParameter parameter, int shiftedTimestep)
|
||||
{
|
||||
parameter.SampleParameter.ShiftedTimestep = shiftedTimestep;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region HighNoiseSampleParameter
|
||||
|
||||
#region Guidance
|
||||
|
||||
public static VideoGenerationParameter WithHighNoiseCfg(this VideoGenerationParameter parameter, float cfg)
|
||||
{
|
||||
parameter.WithTxtCfg(cfg);
|
||||
parameter.WithImgCfg(cfg);
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static VideoGenerationParameter WithHighNoiseTxtCfg(this VideoGenerationParameter parameter, float txtCfg)
|
||||
{
|
||||
parameter.HighNoiseSampleParameter.Guidance.TxtCfg = txtCfg;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static VideoGenerationParameter WithHighNoiseImgCfg(this VideoGenerationParameter parameter, float imgCfg)
|
||||
{
|
||||
parameter.HighNoiseSampleParameter.Guidance.ImgCfg = imgCfg;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static VideoGenerationParameter WithHighNoiseMinCfg(this VideoGenerationParameter parameter, float minCfg)
|
||||
{
|
||||
parameter.HighNoiseSampleParameter.Guidance.MinCfg = minCfg;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static VideoGenerationParameter WithHighNoiseGuidance(this VideoGenerationParameter parameter, float guidance)
|
||||
{
|
||||
parameter.HighNoiseSampleParameter.Guidance.DistilledGuidance = guidance;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
#region Slg
|
||||
|
||||
public static VideoGenerationParameter WithHighNoiseSkipLayers(this VideoGenerationParameter parameter, int[] layers)
|
||||
{
|
||||
parameter.HighNoiseSampleParameter.Guidance.Slg.Layers = layers;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static VideoGenerationParameter WithHighNoiseSkipLayerStart(this VideoGenerationParameter parameter, float skipLayerStart)
|
||||
{
|
||||
parameter.HighNoiseSampleParameter.Guidance.Slg.SkipLayerStart = skipLayerStart;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static VideoGenerationParameter WithHighNoiseSkipLayerEnd(this VideoGenerationParameter parameter, float skipLayerEnd)
|
||||
{
|
||||
parameter.HighNoiseSampleParameter.Guidance.Slg.SkipLayerEnd = skipLayerEnd;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static VideoGenerationParameter WithHighNoiseSlgScale(this VideoGenerationParameter parameter, float slgScale)
|
||||
{
|
||||
parameter.HighNoiseSampleParameter.Guidance.Slg.Scale = slgScale;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
public static VideoGenerationParameter WithHighNoiseScheduler(this VideoGenerationParameter parameter, Scheduler scheduler)
|
||||
{
|
||||
parameter.HighNoiseSampleParameter.Scheduler = scheduler;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static VideoGenerationParameter WithHighNoiseSampler(this VideoGenerationParameter parameter, Sampler sampler)
|
||||
{
|
||||
parameter.HighNoiseSampleParameter.SampleMethod = sampler;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static VideoGenerationParameter WithHighNoiseSteps(this VideoGenerationParameter parameter, int steps)
|
||||
{
|
||||
parameter.HighNoiseSampleParameter.SampleSteps = steps;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static VideoGenerationParameter WithHighNoiseEta(this VideoGenerationParameter parameter, float eta)
|
||||
{
|
||||
parameter.HighNoiseSampleParameter.Eta = eta;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static VideoGenerationParameter WithHighNoiseShiftedTimestep(this VideoGenerationParameter parameter, int shiftedTimestep)
|
||||
{
|
||||
parameter.HighNoiseSampleParameter.ShiftedTimestep = shiftedTimestep;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public static VideoGenerationParameter WithMoeBoundry(this VideoGenerationParameter parameter, float moeBoundry)
|
||||
{
|
||||
parameter.MoeBoundry = moeBoundry;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static VideoGenerationParameter WithStrength(this VideoGenerationParameter parameter, float strength)
|
||||
{
|
||||
parameter.Strength = strength;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static VideoGenerationParameter WithSeed(this VideoGenerationParameter parameter, long seed)
|
||||
{
|
||||
parameter.Seed = seed;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static VideoGenerationParameter WithFrameCount(this VideoGenerationParameter parameter, int frameCount)
|
||||
{
|
||||
parameter.FrameCount = frameCount;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static VideoGenerationParameter WithVaceStrength(this VideoGenerationParameter parameter, float vaceStrength)
|
||||
{
|
||||
parameter.VaceStrength = vaceStrength;
|
||||
|
||||
return parameter;
|
||||
}
|
||||
}
|
||||
13
StableDiffusion.NET/Models/Parameter/GuidanceParameter.cs
Normal file
13
StableDiffusion.NET/Models/Parameter/GuidanceParameter.cs
Normal file
@ -0,0 +1,13 @@
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
public sealed class GuidanceParameter
|
||||
{
|
||||
public float TxtCfg { get; set; } = 7.0f;
|
||||
public float ImgCfg { get; set; } = 7.0f;
|
||||
public float MinCfg { get; set; } = 1.0f;
|
||||
public float DistilledGuidance { get; set; } = 3.5f;
|
||||
|
||||
public SlgParameter Slg { get; } = new();
|
||||
|
||||
internal GuidanceParameter() { }
|
||||
}
|
||||
@ -0,0 +1,68 @@
|
||||
using HPPH;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
[PublicAPI]
|
||||
public sealed class ImageGenerationParameter
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public string Prompt { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// the negative prompt (default: "");
|
||||
/// </summary>
|
||||
public string NegativePrompt { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// ignore last layers of CLIP network; 1 ignores none, 2 ignores one layer (default: -1)
|
||||
/// -1 represents unspecified, will be 1 for SD1.x, 2 for SD2.x
|
||||
/// </summary>
|
||||
public int ClipSkip { get; set; } = -1;
|
||||
|
||||
public IImage? InitImage { get; set; }
|
||||
|
||||
public IImage[]? RefImages { get; set; }
|
||||
|
||||
public bool IncreaseRefIndex { get; set; } = false;
|
||||
|
||||
public bool AutoResizeRefImage { get; set; } = false;
|
||||
|
||||
public IImage? MaskImage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// image width, in pixel space (default: 512)
|
||||
/// </summary>
|
||||
public int Width { get; set; } = 512;
|
||||
|
||||
/// <summary>
|
||||
/// image height, in pixel space (default: 512)
|
||||
/// </summary>
|
||||
public int Height { get; set; } = 512;
|
||||
|
||||
public SampleParameter SampleParameter { get; internal init; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// strength for noising/unnoising (default: 0.7)
|
||||
/// </summary>
|
||||
public float Strength { get; set; } = 0.7f;
|
||||
|
||||
/// <summary>
|
||||
/// RNG seed. use -1 for a random seed (default: -1)
|
||||
/// </summary>
|
||||
public long Seed { get; set; } = -1;
|
||||
|
||||
public ControlNetParameter ControlNet { get; } = new();
|
||||
|
||||
public PhotoMakerParameter PhotoMaker { get; } = new();
|
||||
|
||||
public TilingParameter VaeTiling { get; } = new();
|
||||
|
||||
#endregion
|
||||
|
||||
public static ImageGenerationParameter Create() => new();
|
||||
|
||||
public static ImageGenerationParameter TextToImage(string prompt) => Create().WithPrompt(prompt);
|
||||
public static ImageGenerationParameter ImageToImage(string prompt, IImage image) => Create().WithPrompt(prompt).WithInitImage(image);
|
||||
}
|
||||
@ -1,23 +0,0 @@
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
public interface IDiffusionModelParameter
|
||||
{
|
||||
DiffusionModelType DiffusionModelType { get; set; }
|
||||
|
||||
string VaePath { get; set; }
|
||||
string TaesdPath { get; set; }
|
||||
|
||||
string LoraModelDirectory { get; set; }
|
||||
string EmbeddingsDirectory { get; set; }
|
||||
string ControlNetPath { get; set; }
|
||||
|
||||
bool VaeDecodeOnly { get; set; }
|
||||
bool VaeTiling { get; set; }
|
||||
bool KeepControlNetOnCPU { get; set; }
|
||||
bool KeepClipOnCPU { get; set; }
|
||||
bool KeepVaeOnCPU { get; set; }
|
||||
bool FlashAttention { get; set; }
|
||||
|
||||
RngType RngType { get; set; }
|
||||
Schedule Schedule { get; set; }
|
||||
}
|
||||
@ -1,6 +0,0 @@
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
public interface IPhotomakerModelParameter
|
||||
{
|
||||
string StackedIdEmbeddingsDirectory { get; set; }
|
||||
}
|
||||
@ -1,8 +0,0 @@
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
public interface IQuantizedModelParameter
|
||||
{
|
||||
int ThreadCount { get; set; }
|
||||
|
||||
Quantization Quantization { get; set; }
|
||||
}
|
||||
@ -1,22 +1,17 @@
|
||||
using JetBrains.Annotations;
|
||||
using HPPH;
|
||||
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
[PublicAPI]
|
||||
public sealed class PhotoMakerParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// path to PHOTOMAKER input id images dir
|
||||
/// </summary>
|
||||
public string InputIdImageDirectory { get; set; } = string.Empty;
|
||||
public IImage[]? IdImages { get; set; }
|
||||
|
||||
public string IdEmbedPath { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// strength for keeping input identity (default: 20)
|
||||
/// </summary>
|
||||
public float StyleRatio { get; set; } = 20f;
|
||||
public float StyleStrength { get; set; } = 20f;
|
||||
|
||||
/// <summary>
|
||||
/// normalize PHOTOMAKER input id images
|
||||
/// </summary>
|
||||
public bool NormalizeInput { get; set; } = false;
|
||||
internal PhotoMakerParameter() { }
|
||||
}
|
||||
30
StableDiffusion.NET/Models/Parameter/SampleParameter.cs
Normal file
30
StableDiffusion.NET/Models/Parameter/SampleParameter.cs
Normal file
@ -0,0 +1,30 @@
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
public sealed class SampleParameter
|
||||
{
|
||||
public GuidanceParameter Guidance { get; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Denoiser sigma schedule (default: Default)
|
||||
/// </summary>
|
||||
public Scheduler Scheduler { get; set; } = Scheduler.Default;
|
||||
|
||||
/// <summary>
|
||||
/// sampling method (default: Euler_A)
|
||||
/// </summary>
|
||||
public Sampler SampleMethod { get; set; } = Sampler.Euler_A;
|
||||
|
||||
/// <summary>
|
||||
/// number of sample steps (default: 25)
|
||||
/// </summary>
|
||||
public int SampleSteps { get; set; } = 25;
|
||||
|
||||
/// <summary>
|
||||
/// eta in DDIM, only for DDIM and TCD (default: 0)
|
||||
/// </summary>
|
||||
public float Eta { get; set; } = 0f;
|
||||
|
||||
public int ShiftedTimestep { get; set; } = 0;
|
||||
|
||||
internal SampleParameter() { }
|
||||
}
|
||||
27
StableDiffusion.NET/Models/Parameter/SlgParameter.cs
Normal file
27
StableDiffusion.NET/Models/Parameter/SlgParameter.cs
Normal file
@ -0,0 +1,27 @@
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
public sealed class SlgParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// Layers to skip for SLG steps: (default: [7,8,9])
|
||||
/// </summary>
|
||||
public int[] Layers { get; set; } = [7, 8, 9];
|
||||
|
||||
/// <summary>
|
||||
/// SLG enabling point: (default: 0.01)
|
||||
/// </summary>
|
||||
public float SkipLayerStart { get; set; } = 0.01f;
|
||||
|
||||
/// <summary>
|
||||
/// SLG disabling point: (default: 0.2)
|
||||
/// </summary>
|
||||
public float SkipLayerEnd { get; set; } = 0.2f;
|
||||
|
||||
/// <summary>
|
||||
/// skip layer guidance (SLG) scale, only for DiT models: (default: 0)
|
||||
/// 0 means disabled, a value of 2.5 is nice for sd3.5 medium
|
||||
/// </summary>
|
||||
public float Scale { get; set; } = 0f;
|
||||
|
||||
internal SlgParameter() { }
|
||||
}
|
||||
14
StableDiffusion.NET/Models/Parameter/TilingParameter.cs
Normal file
14
StableDiffusion.NET/Models/Parameter/TilingParameter.cs
Normal file
@ -0,0 +1,14 @@
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
public sealed class TilingParameter
|
||||
{
|
||||
public bool IsEnabled { get; set; }
|
||||
|
||||
public int TileSizeX { get; set; }
|
||||
public int TileSizeY { get; set; }
|
||||
public float TargetOverlap { get; set; }
|
||||
public float RelSizeX { get; set; }
|
||||
public float RelSizeY { get; set; }
|
||||
|
||||
internal TilingParameter() { }
|
||||
}
|
||||
@ -3,13 +3,15 @@
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
[PublicAPI]
|
||||
public sealed class UpscaleModelParameter : IQuantizedModelParameter
|
||||
public sealed class UpscaleModelParameter
|
||||
{
|
||||
/// <summary>
|
||||
/// path to esrgan model. Upscale images after generate, just RealESRGAN_x4plus_anime_6B supported by now
|
||||
/// </summary>
|
||||
public string ModelPath { get; set; } = string.Empty;
|
||||
|
||||
public bool OffloadParamsToCPU { get; set; } = false;
|
||||
|
||||
/// <summary>
|
||||
/// number of threads to use during computation (default: -1)
|
||||
/// If threads = -1, then threads will be set to the number of CPU physical cores
|
||||
@ -17,7 +19,10 @@ public sealed class UpscaleModelParameter : IQuantizedModelParameter
|
||||
public int ThreadCount { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// use Conv2d direct in the diffusion model
|
||||
/// This might crash if it is not supported by the backend.
|
||||
/// </summary>
|
||||
public Quantization Quantization { get; set; } = Quantization.F16;
|
||||
public bool ConvDirect { get; set; } = false;
|
||||
|
||||
public static UpscaleModelParameter Create() => new();
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
using HPPH;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
[PublicAPI]
|
||||
public sealed class VideoGenerationParameter
|
||||
{
|
||||
#region Properties & Fields
|
||||
|
||||
public string Prompt { get; set; } = string.Empty;
|
||||
|
||||
public string NegativePrompt { get; set; } = string.Empty;
|
||||
|
||||
public int ClipSkip { get; set; } = -1;
|
||||
|
||||
public IImage? InitImage { get; set; }
|
||||
|
||||
public IImage? EndImage { get; set; }
|
||||
|
||||
public IImage[]? ControlFrames { get; set; }
|
||||
|
||||
public int Width { get; set; }
|
||||
|
||||
public int Height { get; set; }
|
||||
|
||||
public SampleParameter SampleParameter { get; internal init; } = new();
|
||||
|
||||
public SampleParameter HighNoiseSampleParameter { get; internal init; } = new();
|
||||
|
||||
public float MoeBoundry { get; set; }
|
||||
|
||||
public float Strength { get; set; }
|
||||
|
||||
public long Seed { get; set; }
|
||||
|
||||
public int FrameCount { get; set; }
|
||||
|
||||
public float VaceStrength { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
public static VideoGenerationParameter Create() => new();
|
||||
|
||||
public static VideoGenerationParameter TextToVideo(string prompt) => Create().WithPrompt(prompt);
|
||||
}
|
||||
@ -13,7 +13,7 @@ public sealed unsafe class UpscaleModel : IDisposable
|
||||
|
||||
public UpscaleModelParameter ModelParameter { get; }
|
||||
|
||||
private Native.upscaler_ctx_t* _ctx;
|
||||
private Native.Types.upscaler_ctx_t* _ctx;
|
||||
|
||||
#endregion
|
||||
|
||||
@ -39,33 +39,21 @@ public sealed unsafe class UpscaleModel : IDisposable
|
||||
private void Initialize()
|
||||
{
|
||||
_ctx = Native.new_upscaler_ctx(ModelParameter.ModelPath,
|
||||
ModelParameter.ThreadCount,
|
||||
ModelParameter.Quantization);
|
||||
ModelParameter.OffloadParamsToCPU,
|
||||
ModelParameter.ConvDirect,
|
||||
ModelParameter.ThreadCount);
|
||||
|
||||
if (_ctx == null) throw new NullReferenceException("Failed to initialize upscale-model.");
|
||||
}
|
||||
|
||||
public IImage<ColorRGB> Upscale(IImage image, int upscaleFactor)
|
||||
public Image<ColorRGB> Upscale(IImage image, int upscaleFactor)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(upscaleFactor, 0, nameof(upscaleFactor));
|
||||
|
||||
if (_ctx == null) throw new NullReferenceException("The model is not initialized.");
|
||||
|
||||
if (image is not IImage<ColorRGB> sourceImage)
|
||||
sourceImage = image.ConvertTo<ColorRGB>();
|
||||
|
||||
fixed (byte* imagePtr = sourceImage.AsRefImage())
|
||||
{
|
||||
Native.sd_image_t result = Native.upscale(_ctx, sourceImage.ToSdImage(imagePtr), upscaleFactor);
|
||||
return ImageHelper.ToImage(result);
|
||||
}
|
||||
}
|
||||
|
||||
private IImage<ColorRGB> Upscale(Native.sd_image_t image, int upscaleFactor)
|
||||
{
|
||||
Native.sd_image_t result = Native.upscale(_ctx, image, upscaleFactor);
|
||||
return ImageHelper.ToImage(result);
|
||||
return Native.upscale(_ctx, image, (uint)upscaleFactor);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
||||
@ -0,0 +1,101 @@
|
||||
using System.Runtime.InteropServices.Marshalling;
|
||||
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
[CustomMarshaller(typeof(DiffusionModelParameter), MarshalMode.ManagedToUnmanagedIn, typeof(DiffusionModelParameterMarshaller))]
|
||||
[CustomMarshaller(typeof(DiffusionModelParameter), MarshalMode.ManagedToUnmanagedRef, typeof(DiffusionModelParameterMarshaller))]
|
||||
internal static unsafe class DiffusionModelParameterMarshaller
|
||||
{
|
||||
public static Native.Types.sd_ctx_params_t ConvertToUnmanaged(DiffusionModelParameter managed)
|
||||
=> new()
|
||||
{
|
||||
model_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.ModelPath),
|
||||
clip_l_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.ClipLPath),
|
||||
clip_g_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.ClipGPath),
|
||||
clip_vision_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.ClipVisionPath),
|
||||
t5xxl_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.T5xxlPath),
|
||||
qwen2vl_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.Qwen2VLPath),
|
||||
qwen2vl_vision_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.Qwen2VLVisionPath),
|
||||
diffusion_model_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.DiffusionModelPath),
|
||||
high_noise_diffusion_model_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.HighNoiseDiffusionModelPath),
|
||||
vae_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.VaePath),
|
||||
taesd_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.TaesdPath),
|
||||
control_net_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.ControlNetPath),
|
||||
lora_model_dir = AnsiStringMarshaller.ConvertToUnmanaged(managed.LoraModelDirectory),
|
||||
embedding_dir = AnsiStringMarshaller.ConvertToUnmanaged(managed.EmbeddingsDirectory),
|
||||
photo_maker_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.StackedIdEmbeddingsDirectory),
|
||||
vae_decode_only = (sbyte)(managed.VaeDecodeOnly ? 1 : 0),
|
||||
free_params_immediately = (sbyte)(managed.FreeParamsImmediately ? 1 : 0),
|
||||
n_threads = managed.ThreadCount,
|
||||
wtype = managed.Quantization,
|
||||
rng_type = managed.RngType,
|
||||
prediction = managed.Prediction,
|
||||
offload_params_to_cpu = (sbyte)(managed.OffloadParamsToCPU ? 1 : 0),
|
||||
keep_clip_on_cpu = (sbyte)(managed.KeepClipOnCPU ? 1 : 0),
|
||||
keep_control_net_on_cpu = (sbyte)(managed.KeepControlNetOnCPU ? 1 : 0),
|
||||
keep_vae_on_cpu = (sbyte)(managed.KeepVaeOnCPU ? 1 : 0),
|
||||
diffusion_flash_attn = (sbyte)(managed.FlashAttention ? 1 : 0),
|
||||
diffusion_conv_direct = (sbyte)(managed.DiffusionConvDirect ? 1 : 0),
|
||||
vae_conv_direct = (sbyte)(managed.VaeConvDirect ? 1 : 0),
|
||||
force_sdxl_vae_conv_scale = (sbyte)(managed.ForceSdxlVaeConvScale ? 1 : 0),
|
||||
chroma_use_dit_mask = (sbyte)(managed.ChromaUseDitMap ? 1 : 0),
|
||||
chroma_use_t5_mask = (sbyte)(managed.ChromaEnableT5Map ? 1 : 0),
|
||||
chroma_t5_mask_pad = managed.ChromaT5MaskPad,
|
||||
flow_shift = managed.FlowShift
|
||||
};
|
||||
|
||||
public static DiffusionModelParameter ConvertToManaged(Native.Types.sd_ctx_params_t unmanaged)
|
||||
=> new()
|
||||
{
|
||||
ModelPath = AnsiStringMarshaller.ConvertToManaged(unmanaged.model_path) ?? string.Empty,
|
||||
ClipLPath = AnsiStringMarshaller.ConvertToManaged(unmanaged.clip_l_path) ?? string.Empty,
|
||||
ClipGPath = AnsiStringMarshaller.ConvertToManaged(unmanaged.clip_g_path) ?? string.Empty,
|
||||
ClipVisionPath = AnsiStringMarshaller.ConvertToManaged(unmanaged.clip_vision_path) ?? string.Empty,
|
||||
T5xxlPath = AnsiStringMarshaller.ConvertToManaged(unmanaged.t5xxl_path) ?? string.Empty,
|
||||
Qwen2VLPath = AnsiStringMarshaller.ConvertToManaged(unmanaged.qwen2vl_path) ?? string.Empty,
|
||||
Qwen2VLVisionPath = AnsiStringMarshaller.ConvertToManaged(unmanaged.qwen2vl_vision_path) ?? string.Empty,
|
||||
DiffusionModelPath = AnsiStringMarshaller.ConvertToManaged(unmanaged.diffusion_model_path) ?? string.Empty,
|
||||
HighNoiseDiffusionModelPath = AnsiStringMarshaller.ConvertToManaged(unmanaged.high_noise_diffusion_model_path) ?? string.Empty,
|
||||
VaePath = AnsiStringMarshaller.ConvertToManaged(unmanaged.vae_path) ?? string.Empty,
|
||||
TaesdPath = AnsiStringMarshaller.ConvertToManaged(unmanaged.taesd_path) ?? string.Empty,
|
||||
ControlNetPath = AnsiStringMarshaller.ConvertToManaged(unmanaged.control_net_path) ?? string.Empty,
|
||||
LoraModelDirectory = AnsiStringMarshaller.ConvertToManaged(unmanaged.lora_model_dir) ?? string.Empty,
|
||||
EmbeddingsDirectory = AnsiStringMarshaller.ConvertToManaged(unmanaged.embedding_dir) ?? string.Empty,
|
||||
StackedIdEmbeddingsDirectory = AnsiStringMarshaller.ConvertToManaged(unmanaged.photo_maker_path) ?? string.Empty,
|
||||
VaeDecodeOnly = unmanaged.vae_decode_only == 1,
|
||||
FreeParamsImmediately = unmanaged.free_params_immediately == 1,
|
||||
ThreadCount = unmanaged.n_threads,
|
||||
Quantization = unmanaged.wtype,
|
||||
RngType = unmanaged.rng_type,
|
||||
Prediction = unmanaged.prediction,
|
||||
OffloadParamsToCPU = unmanaged.offload_params_to_cpu == 1,
|
||||
KeepClipOnCPU = unmanaged.keep_clip_on_cpu == 1,
|
||||
KeepControlNetOnCPU = unmanaged.keep_control_net_on_cpu == 1,
|
||||
KeepVaeOnCPU = unmanaged.keep_vae_on_cpu == 1,
|
||||
FlashAttention = unmanaged.diffusion_flash_attn == 1,
|
||||
DiffusionConvDirect = unmanaged.diffusion_conv_direct == 1,
|
||||
VaeConvDirect = unmanaged.vae_conv_direct == 1,
|
||||
ForceSdxlVaeConvScale = unmanaged.force_sdxl_vae_conv_scale == 1,
|
||||
ChromaUseDitMap = unmanaged.chroma_use_dit_mask == 1,
|
||||
ChromaEnableT5Map = unmanaged.chroma_use_t5_mask == 1,
|
||||
ChromaT5MaskPad = unmanaged.chroma_t5_mask_pad,
|
||||
FlowShift = unmanaged.flow_shift
|
||||
};
|
||||
|
||||
public static void Free(Native.Types.sd_ctx_params_t unmanaged)
|
||||
{
|
||||
AnsiStringMarshaller.Free(unmanaged.model_path);
|
||||
AnsiStringMarshaller.Free(unmanaged.clip_l_path);
|
||||
AnsiStringMarshaller.Free(unmanaged.clip_g_path);
|
||||
AnsiStringMarshaller.Free(unmanaged.t5xxl_path);
|
||||
AnsiStringMarshaller.Free(unmanaged.qwen2vl_path);
|
||||
AnsiStringMarshaller.Free(unmanaged.qwen2vl_vision_path);
|
||||
AnsiStringMarshaller.Free(unmanaged.diffusion_model_path);
|
||||
AnsiStringMarshaller.Free(unmanaged.vae_path);
|
||||
AnsiStringMarshaller.Free(unmanaged.taesd_path);
|
||||
AnsiStringMarshaller.Free(unmanaged.control_net_path);
|
||||
AnsiStringMarshaller.Free(unmanaged.lora_model_dir);
|
||||
AnsiStringMarshaller.Free(unmanaged.embedding_dir);
|
||||
AnsiStringMarshaller.Free(unmanaged.photo_maker_path);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,187 @@
|
||||
// ReSharper disable MemberCanBeMadeStatic.Global
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices.Marshalling;
|
||||
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
[CustomMarshaller(typeof(ImageGenerationParameter), MarshalMode.ManagedToUnmanagedIn, typeof(ImageGenerationParameterMarshallerIn))]
|
||||
[CustomMarshaller(typeof(ImageGenerationParameter), MarshalMode.ManagedToUnmanagedOut, typeof(ImageGenerationParameterMarshaller))]
|
||||
[CustomMarshaller(typeof(ImageGenerationParameter), MarshalMode.ManagedToUnmanagedRef, typeof(ImageGenerationParameterMarshallerRef))]
|
||||
internal static class ImageGenerationParameterMarshaller
|
||||
{
|
||||
public static unsafe ImageGenerationParameter ConvertToManaged(Native.Types.sd_img_gen_params_t unmanaged)
|
||||
{
|
||||
ImageGenerationParameter parameter = new()
|
||||
{
|
||||
Prompt = AnsiStringMarshaller.ConvertToManaged(unmanaged.prompt) ?? string.Empty,
|
||||
NegativePrompt = AnsiStringMarshaller.ConvertToManaged(unmanaged.negative_prompt) ?? string.Empty,
|
||||
ClipSkip = unmanaged.clip_skip,
|
||||
SampleParameter = SampleParameterMarshaller.ConvertToManaged(unmanaged.sample_params),
|
||||
InitImage = unmanaged.init_image.data == null ? null : unmanaged.init_image.ToImage(),
|
||||
RefImages = unmanaged.ref_images == null ? null : ImageHelper.ToImageArrayIFace(unmanaged.ref_images, unmanaged.ref_images_count),
|
||||
AutoResizeRefImage = unmanaged.auto_resize_ref_image == 1,
|
||||
MaskImage = unmanaged.mask_image.data == null ? null : unmanaged.mask_image.ToImage(),
|
||||
Width = unmanaged.width,
|
||||
Height = unmanaged.height,
|
||||
Strength = unmanaged.strength,
|
||||
Seed = unmanaged.seed,
|
||||
ControlNet =
|
||||
{
|
||||
Image = unmanaged.control_image.ToImage(),
|
||||
Strength = unmanaged.control_strength,
|
||||
},
|
||||
PhotoMaker =
|
||||
{
|
||||
IdImages = unmanaged.pm_params.id_images == null ? null : ImageHelper.ToImageArrayIFace(unmanaged.pm_params.id_images, unmanaged.pm_params.id_images_count),
|
||||
IdEmbedPath = AnsiStringMarshaller.ConvertToManaged(unmanaged.pm_params.id_embed_path) ?? string.Empty,
|
||||
StyleStrength = unmanaged.pm_params.style_strength,
|
||||
},
|
||||
VaeTiling =
|
||||
{
|
||||
IsEnabled = unmanaged.vae_tiling_params.enabled == 1,
|
||||
TileSizeX = unmanaged.vae_tiling_params.tile_size_x,
|
||||
TileSizeY = unmanaged.vae_tiling_params.tile_size_y,
|
||||
TargetOverlap = unmanaged.vae_tiling_params.target_overlap,
|
||||
RelSizeX = unmanaged.vae_tiling_params.rel_size_x,
|
||||
RelSizeY = unmanaged.vae_tiling_params.rel_size_y
|
||||
}
|
||||
};
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static unsafe void Free(Native.Types.sd_img_gen_params_t unmanaged)
|
||||
{
|
||||
AnsiStringMarshaller.Free(unmanaged.prompt);
|
||||
AnsiStringMarshaller.Free(unmanaged.negative_prompt);
|
||||
|
||||
unmanaged.init_image.Free();
|
||||
unmanaged.mask_image.Free();
|
||||
unmanaged.control_image.Free();
|
||||
|
||||
if (unmanaged.ref_images != null)
|
||||
ImageHelper.Free(unmanaged.ref_images, unmanaged.ref_images_count);
|
||||
|
||||
if (unmanaged.pm_params.id_images != null)
|
||||
ImageHelper.Free(unmanaged.pm_params.id_images, unmanaged.pm_params.id_images_count);
|
||||
|
||||
SampleParameterMarshaller.Free(unmanaged.sample_params);
|
||||
}
|
||||
|
||||
internal unsafe ref struct ImageGenerationParameterMarshallerIn
|
||||
{
|
||||
private SampleParameterMarshaller.SampleParameterMarshallerIn _sampleParameterMarshaller = new();
|
||||
private Native.Types.sd_img_gen_params_t _imgGenParams;
|
||||
|
||||
private Native.Types.sd_image_t _initImage;
|
||||
private Native.Types.sd_image_t _maskImage;
|
||||
private Native.Types.sd_image_t _controlNetImage;
|
||||
private Native.Types.sd_image_t* _refImages;
|
||||
private Native.Types.sd_image_t* _pmIdImages;
|
||||
|
||||
public ImageGenerationParameterMarshallerIn() { }
|
||||
|
||||
public void FromManaged(ImageGenerationParameter managed)
|
||||
{
|
||||
_sampleParameterMarshaller.FromManaged(managed.SampleParameter);
|
||||
|
||||
_initImage = managed.InitImage?.ToSdImage() ?? new Native.Types.sd_image_t();
|
||||
_controlNetImage = managed.ControlNet.Image?.ToSdImage() ?? new Native.Types.sd_image_t();
|
||||
_refImages = managed.RefImages == null ? null : managed.RefImages.ToSdImage();
|
||||
_pmIdImages = managed.PhotoMaker.IdImages == null ? null : managed.PhotoMaker.IdImages.ToSdImage();
|
||||
|
||||
if (managed.MaskImage != null)
|
||||
_maskImage = managed.MaskImage.ToSdImage(true);
|
||||
else if (managed.InitImage != null)
|
||||
{
|
||||
// DarthAffe 16.08.2025: Mask needs to be a 1 channel all max value image when it's not used - I really don't like this concept as it adds unnecessary allocations, but that's how it is :(
|
||||
uint maskImageByteSize = _initImage.width * _initImage.height;
|
||||
_maskImage = new Native.Types.sd_image_t
|
||||
{
|
||||
width = _initImage.width,
|
||||
height = _initImage.height,
|
||||
channel = 1,
|
||||
data = (byte*)NativeMemory.Alloc(maskImageByteSize)
|
||||
};
|
||||
new Span<byte>(_maskImage.data, (int)maskImageByteSize).Fill(byte.MaxValue);
|
||||
}
|
||||
|
||||
Native.Types.sd_pm_params_t photoMakerParams = new()
|
||||
{
|
||||
id_images = _pmIdImages,
|
||||
id_images_count = managed.PhotoMaker.IdImages?.Length ?? 0,
|
||||
id_embed_path = AnsiStringMarshaller.ConvertToUnmanaged(managed.PhotoMaker.IdEmbedPath),
|
||||
style_strength = managed.PhotoMaker.StyleStrength
|
||||
};
|
||||
|
||||
Native.Types.sd_tiling_params_t tilingParams = new()
|
||||
{
|
||||
enabled = (sbyte)(managed.VaeTiling.IsEnabled ? 1 : 0),
|
||||
tile_size_x = managed.VaeTiling.TileSizeX,
|
||||
tile_size_y = managed.VaeTiling.TileSizeY,
|
||||
target_overlap = managed.VaeTiling.TargetOverlap,
|
||||
rel_size_x = managed.VaeTiling.RelSizeX,
|
||||
rel_size_y = managed.VaeTiling.RelSizeY
|
||||
};
|
||||
|
||||
_imgGenParams = new Native.Types.sd_img_gen_params_t
|
||||
{
|
||||
prompt = AnsiStringMarshaller.ConvertToUnmanaged(managed.Prompt),
|
||||
negative_prompt = AnsiStringMarshaller.ConvertToUnmanaged(managed.NegativePrompt),
|
||||
clip_skip = managed.ClipSkip,
|
||||
sample_params = _sampleParameterMarshaller.ToUnmanaged(),
|
||||
init_image = _initImage,
|
||||
ref_images = _refImages,
|
||||
ref_images_count = managed.RefImages?.Length ?? 0,
|
||||
auto_resize_ref_image = (sbyte)(managed.AutoResizeRefImage ? 1 : 0),
|
||||
mask_image = _maskImage,
|
||||
width = managed.Width,
|
||||
height = managed.Height,
|
||||
strength = managed.Strength,
|
||||
seed = managed.Seed,
|
||||
batch_count = 1,
|
||||
control_image = _controlNetImage,
|
||||
control_strength = managed.ControlNet.Strength,
|
||||
pm_params = photoMakerParams,
|
||||
vae_tiling_params = tilingParams
|
||||
};
|
||||
}
|
||||
|
||||
public Native.Types.sd_img_gen_params_t ToUnmanaged() => _imgGenParams;
|
||||
|
||||
public void Free()
|
||||
{
|
||||
AnsiStringMarshaller.Free(_imgGenParams.prompt);
|
||||
AnsiStringMarshaller.Free(_imgGenParams.negative_prompt);
|
||||
AnsiStringMarshaller.Free(_imgGenParams.pm_params.id_embed_path);
|
||||
|
||||
_initImage.Free();
|
||||
_maskImage.Free();
|
||||
_controlNetImage.Free();
|
||||
|
||||
if (_refImages != null)
|
||||
ImageHelper.Free(_refImages, _imgGenParams.ref_images_count);
|
||||
|
||||
if (_pmIdImages != null)
|
||||
ImageHelper.Free(_pmIdImages, _imgGenParams.pm_params.id_images_count);
|
||||
|
||||
_sampleParameterMarshaller.Free();
|
||||
}
|
||||
}
|
||||
|
||||
internal ref struct ImageGenerationParameterMarshallerRef()
|
||||
{
|
||||
private ImageGenerationParameterMarshallerIn _inMarshaller = new();
|
||||
private ImageGenerationParameter? _parameter;
|
||||
|
||||
public void FromManaged(ImageGenerationParameter managed) => _inMarshaller.FromManaged(managed);
|
||||
public Native.Types.sd_img_gen_params_t ToUnmanaged() => _inMarshaller.ToUnmanaged();
|
||||
|
||||
public void FromUnmanaged(Native.Types.sd_img_gen_params_t unmanaged) => _parameter = ConvertToManaged(unmanaged);
|
||||
public ImageGenerationParameter ToManaged() => _parameter!;
|
||||
|
||||
public void Free() => _inMarshaller.Free();
|
||||
}
|
||||
}
|
||||
24
StableDiffusion.NET/Native/Marshaller/ImageMarshaller.cs
Normal file
24
StableDiffusion.NET/Native/Marshaller/ImageMarshaller.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using HPPH;
|
||||
using System.Runtime.InteropServices.Marshalling;
|
||||
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
[CustomMarshaller(typeof(IImage), MarshalMode.ManagedToUnmanagedIn, typeof(ImageMarshallerIn))]
|
||||
[CustomMarshaller(typeof(Image<ColorRGB>), MarshalMode.ManagedToUnmanagedOut, typeof(ImageMarshaller))]
|
||||
internal static class ImageMarshaller
|
||||
{
|
||||
public static Image<ColorRGB> ConvertToManaged(Native.Types.sd_image_t unmanaged) => unmanaged.ToImage();
|
||||
|
||||
public static void Free(Native.Types.sd_image_t unmanaged) => unmanaged.Free();
|
||||
|
||||
internal ref struct ImageMarshallerIn
|
||||
{
|
||||
private Native.Types.sd_image_t _image;
|
||||
|
||||
public void FromManaged(IImage managed) => _image = managed.ToSdImage();
|
||||
|
||||
public Native.Types.sd_image_t ToUnmanaged() => _image;
|
||||
|
||||
public void Free() => _image.Free();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,113 @@
|
||||
// ReSharper disable MemberCanBeMadeStatic.Global
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices.Marshalling;
|
||||
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
[CustomMarshaller(typeof(SampleParameter), MarshalMode.ManagedToUnmanagedIn, typeof(SampleParameterMarshallerIn))]
|
||||
[CustomMarshaller(typeof(SampleParameter), MarshalMode.ManagedToUnmanagedOut, typeof(SampleParameterMarshaller))]
|
||||
[CustomMarshaller(typeof(SampleParameter), MarshalMode.ManagedToUnmanagedRef, typeof(SampleParameterMarshallerRef))]
|
||||
internal static class SampleParameterMarshaller
|
||||
{
|
||||
public static unsafe SampleParameter ConvertToManaged(Native.Types.sd_sample_params_t unmanaged)
|
||||
{
|
||||
SampleParameter parameter = new()
|
||||
{
|
||||
Guidance =
|
||||
{
|
||||
TxtCfg = unmanaged.guidance.txt_cfg,
|
||||
ImgCfg = unmanaged.guidance.img_cfg,
|
||||
MinCfg = unmanaged.guidance.min_cfg,
|
||||
DistilledGuidance = unmanaged.guidance.distilled_guidance,
|
||||
Slg =
|
||||
{
|
||||
Layers = new int[unmanaged.guidance.slg.layer_count],
|
||||
SkipLayerStart = unmanaged.guidance.slg.layer_start,
|
||||
SkipLayerEnd = unmanaged.guidance.slg.layer_end,
|
||||
Scale = unmanaged.guidance.slg.scale
|
||||
}
|
||||
},
|
||||
Scheduler = unmanaged.scheduler,
|
||||
SampleMethod = unmanaged.sample_method,
|
||||
SampleSteps = unmanaged.sample_steps,
|
||||
Eta = unmanaged.eta,
|
||||
ShiftedTimestep = unmanaged.shifted_timestep
|
||||
};
|
||||
|
||||
if (unmanaged.guidance.slg.layers != null)
|
||||
new Span<int>(unmanaged.guidance.slg.layers, (int)unmanaged.guidance.slg.layer_count).CopyTo(parameter.Guidance.Slg.Layers);
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static unsafe void Free(Native.Types.sd_sample_params_t unmanaged)
|
||||
{
|
||||
if (unmanaged.guidance.slg.layers != null)
|
||||
NativeMemory.Free(unmanaged.guidance.slg.layers);
|
||||
}
|
||||
|
||||
internal unsafe ref struct SampleParameterMarshallerIn
|
||||
{
|
||||
private Native.Types.sd_sample_params_t _sampleParams;
|
||||
|
||||
private int* _slgLayers;
|
||||
|
||||
public void FromManaged(SampleParameter managed)
|
||||
{
|
||||
_slgLayers = (int*)NativeMemory.Alloc((nuint)managed.Guidance.Slg.Layers.Length, (nuint)Marshal.SizeOf<int>());
|
||||
managed.Guidance.Slg.Layers.AsSpan().CopyTo(new Span<int>(_slgLayers, managed.Guidance.Slg.Layers.Length));
|
||||
|
||||
Native.Types.sd_slg_params_t slg = new()
|
||||
{
|
||||
layers = _slgLayers,
|
||||
layer_count = (uint)managed.Guidance.Slg.Layers.Length,
|
||||
layer_start = managed.Guidance.Slg.SkipLayerStart,
|
||||
layer_end = managed.Guidance.Slg.SkipLayerEnd,
|
||||
scale = managed.Guidance.Slg.Scale,
|
||||
};
|
||||
|
||||
Native.Types.sd_guidance_params_t guidance = new()
|
||||
{
|
||||
txt_cfg = managed.Guidance.TxtCfg,
|
||||
img_cfg = managed.Guidance.ImgCfg,
|
||||
min_cfg = managed.Guidance.MinCfg,
|
||||
distilled_guidance = managed.Guidance.DistilledGuidance,
|
||||
slg = slg
|
||||
};
|
||||
|
||||
_sampleParams = new Native.Types.sd_sample_params_t
|
||||
{
|
||||
guidance = guidance,
|
||||
scheduler = managed.Scheduler,
|
||||
sample_method = managed.SampleMethod,
|
||||
sample_steps = managed.SampleSteps,
|
||||
eta = managed.Eta,
|
||||
shifted_timestep = managed.ShiftedTimestep
|
||||
};
|
||||
}
|
||||
|
||||
public Native.Types.sd_sample_params_t ToUnmanaged() => _sampleParams;
|
||||
|
||||
public void Free()
|
||||
{
|
||||
if (_slgLayers != null)
|
||||
NativeMemory.Free(_slgLayers);
|
||||
}
|
||||
}
|
||||
|
||||
internal ref struct SampleParameterMarshallerRef()
|
||||
{
|
||||
private SampleParameterMarshallerIn _inMarshaller = new();
|
||||
private SampleParameter? _parameter;
|
||||
|
||||
public void FromManaged(SampleParameter managed) => _inMarshaller.FromManaged(managed);
|
||||
public Native.Types.sd_sample_params_t ToUnmanaged() => _inMarshaller.ToUnmanaged();
|
||||
|
||||
public void FromUnmanaged(Native.Types.sd_sample_params_t unmanaged) => _parameter = ConvertToManaged(unmanaged);
|
||||
public SampleParameter ToManaged() => _parameter ?? throw new NullReferenceException($"{nameof(FromUnmanaged)} needs to be called before ToManaged.");
|
||||
|
||||
public void Free() => _inMarshaller.Free();
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,124 @@
|
||||
// ReSharper disable MemberCanBeMadeStatic.Global
|
||||
|
||||
using System.Runtime.InteropServices.Marshalling;
|
||||
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
[CustomMarshaller(typeof(VideoGenerationParameter), MarshalMode.ManagedToUnmanagedIn, typeof(VideoGenerationParameterMarshallerIn))]
|
||||
[CustomMarshaller(typeof(VideoGenerationParameter), MarshalMode.ManagedToUnmanagedOut, typeof(VideoGenerationParameterMarshaller))]
|
||||
[CustomMarshaller(typeof(VideoGenerationParameter), MarshalMode.ManagedToUnmanagedRef, typeof(VideoGenerationParameterMarshallerRef))]
|
||||
internal static class VideoGenerationParameterMarshaller
|
||||
{
|
||||
public static unsafe VideoGenerationParameter ConvertToManaged(Native.Types.sd_vid_gen_params_t unmanaged)
|
||||
{
|
||||
VideoGenerationParameter parameter = new()
|
||||
{
|
||||
Prompt = AnsiStringMarshaller.ConvertToManaged(unmanaged.prompt) ?? string.Empty,
|
||||
NegativePrompt = AnsiStringMarshaller.ConvertToManaged(unmanaged.negative_prompt) ?? string.Empty,
|
||||
ClipSkip = unmanaged.clip_skip,
|
||||
InitImage = unmanaged.init_image.data == null ? null : unmanaged.init_image.ToImage(),
|
||||
EndImage = unmanaged.end_image.data == null ? null : unmanaged.end_image.ToImage(),
|
||||
ControlFrames = unmanaged.control_frames == null ? null : ImageHelper.ToImageArrayIFace(unmanaged.control_frames, unmanaged.control_frames_size),
|
||||
Width = unmanaged.width,
|
||||
Height = unmanaged.height,
|
||||
SampleParameter = SampleParameterMarshaller.ConvertToManaged(unmanaged.sample_params),
|
||||
HighNoiseSampleParameter = SampleParameterMarshaller.ConvertToManaged(unmanaged.high_noise_sample_params),
|
||||
MoeBoundry = unmanaged.moe_boundary,
|
||||
Strength = unmanaged.strength,
|
||||
Seed = unmanaged.seed,
|
||||
FrameCount = unmanaged.video_frames,
|
||||
VaceStrength = unmanaged.vace_strength
|
||||
};
|
||||
|
||||
return parameter;
|
||||
}
|
||||
|
||||
public static unsafe void Free(Native.Types.sd_vid_gen_params_t unmanaged)
|
||||
{
|
||||
AnsiStringMarshaller.Free(unmanaged.prompt);
|
||||
AnsiStringMarshaller.Free(unmanaged.negative_prompt);
|
||||
|
||||
unmanaged.init_image.Free();
|
||||
unmanaged.end_image.Free();
|
||||
|
||||
if (unmanaged.control_frames != null)
|
||||
ImageHelper.Free(unmanaged.control_frames, unmanaged.control_frames_size);
|
||||
|
||||
SampleParameterMarshaller.Free(unmanaged.sample_params);
|
||||
SampleParameterMarshaller.Free(unmanaged.high_noise_sample_params);
|
||||
}
|
||||
|
||||
internal unsafe ref struct VideoGenerationParameterMarshallerIn
|
||||
{
|
||||
private SampleParameterMarshaller.SampleParameterMarshallerIn _sampleParameterMarshaller = new();
|
||||
private SampleParameterMarshaller.SampleParameterMarshallerIn _highNoiseSampleParameterMarshaller = new();
|
||||
private Native.Types.sd_vid_gen_params_t _vidGenParams;
|
||||
|
||||
private Native.Types.sd_image_t _initImage;
|
||||
private Native.Types.sd_image_t _endImage;
|
||||
private Native.Types.sd_image_t* _controlFrames;
|
||||
|
||||
public VideoGenerationParameterMarshallerIn() { }
|
||||
|
||||
public void FromManaged(VideoGenerationParameter managed)
|
||||
{
|
||||
_sampleParameterMarshaller.FromManaged(managed.SampleParameter);
|
||||
_highNoiseSampleParameterMarshaller.FromManaged(managed.HighNoiseSampleParameter);
|
||||
|
||||
_initImage = managed.InitImage?.ToSdImage() ?? new Native.Types.sd_image_t();
|
||||
_endImage = managed.EndImage?.ToSdImage() ?? new Native.Types.sd_image_t();
|
||||
_controlFrames = managed.ControlFrames == null ? null : managed.ControlFrames.ToSdImage();
|
||||
|
||||
_vidGenParams = new Native.Types.sd_vid_gen_params_t
|
||||
{
|
||||
prompt = AnsiStringMarshaller.ConvertToUnmanaged(managed.Prompt),
|
||||
negative_prompt = AnsiStringMarshaller.ConvertToUnmanaged(managed.NegativePrompt),
|
||||
clip_skip = managed.ClipSkip,
|
||||
init_image = _initImage,
|
||||
end_image = _endImage,
|
||||
control_frames = _controlFrames,
|
||||
control_frames_size = managed.ControlFrames?.Length ?? 0,
|
||||
width = managed.Width,
|
||||
height = managed.Height,
|
||||
sample_params = _sampleParameterMarshaller.ToUnmanaged(),
|
||||
high_noise_sample_params = _highNoiseSampleParameterMarshaller.ToUnmanaged(),
|
||||
moe_boundary = managed.MoeBoundry,
|
||||
strength = managed.Strength,
|
||||
seed = managed.Seed,
|
||||
video_frames = managed.FrameCount,
|
||||
vace_strength = managed.VaceStrength,
|
||||
};
|
||||
}
|
||||
|
||||
public Native.Types.sd_vid_gen_params_t ToUnmanaged() => _vidGenParams;
|
||||
|
||||
public void Free()
|
||||
{
|
||||
AnsiStringMarshaller.Free(_vidGenParams.prompt);
|
||||
AnsiStringMarshaller.Free(_vidGenParams.negative_prompt);
|
||||
|
||||
_initImage.Free();
|
||||
_endImage.Free();
|
||||
|
||||
if (_controlFrames != null)
|
||||
ImageHelper.Free(_controlFrames, _vidGenParams.control_frames_size);
|
||||
|
||||
_sampleParameterMarshaller.Free();
|
||||
_highNoiseSampleParameterMarshaller.Free();
|
||||
}
|
||||
}
|
||||
|
||||
internal ref struct VideoGenerationParameterMarshallerRef()
|
||||
{
|
||||
private VideoGenerationParameterMarshallerIn _inMarshaller = new();
|
||||
private VideoGenerationParameter? _parameter;
|
||||
|
||||
public void FromManaged(VideoGenerationParameter managed) => _inMarshaller.FromManaged(managed);
|
||||
public Native.Types.sd_vid_gen_params_t ToUnmanaged() => _inMarshaller.ToUnmanaged();
|
||||
|
||||
public void FromUnmanaged(Native.Types.sd_vid_gen_params_t unmanaged) => _parameter = ConvertToManaged(unmanaged);
|
||||
public VideoGenerationParameter ToManaged() => _parameter!;
|
||||
|
||||
public void Free() => _inMarshaller.Free();
|
||||
}
|
||||
}
|
||||
@ -38,7 +38,7 @@ internal static partial class Native
|
||||
return false;
|
||||
}
|
||||
|
||||
private static nint ResolveDllImport(string libraryname, Assembly assembly, DllImportSearchPath? searchpath)
|
||||
private static nint ResolveDllImport(string libraryname, Assembly _, DllImportSearchPath? __)
|
||||
{
|
||||
if (libraryname != LIB_NAME) return nint.Zero;
|
||||
if (_loadedLibraryHandle != nint.Zero) return _loadedLibraryHandle;
|
||||
|
||||
@ -1,17 +1,32 @@
|
||||
#pragma warning disable CS0169 // Field is never used
|
||||
#pragma warning disable IDE1006
|
||||
#pragma warning disable IDE1006
|
||||
// ReSharper disable InconsistentNaming
|
||||
// ReSharper disable ArrangeTypeMemberModifiers
|
||||
// ReSharper disable UseSymbolAlias
|
||||
|
||||
using HPPH;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.InteropServices.Marshalling;
|
||||
|
||||
namespace StableDiffusion.NET;
|
||||
|
||||
using int32_t = int;
|
||||
using int64_t = long;
|
||||
using rng_type_t = RngType;
|
||||
using sample_method_t = Sampler;
|
||||
using schedule_t = Schedule;
|
||||
using sd_type_t = Quantization;
|
||||
using scheduler_t = Scheduler;
|
||||
using prediction_t = Prediction;
|
||||
using sd_ctx_params_t = DiffusionModelParameter;
|
||||
using sd_ctx_t = Native.Types.sd_ctx_t;
|
||||
using sd_image_t = Native.Types.sd_image_t;
|
||||
using sd_sample_params_t = SampleParameter;
|
||||
using sd_img_gen_params_t = ImageGenerationParameter;
|
||||
using sd_log_level_t = LogLevel;
|
||||
using sd_type_t = Quantization;
|
||||
using sd_vid_gen_params_t = VideoGenerationParameter;
|
||||
using size_t = nuint;
|
||||
using uint32_t = uint;
|
||||
using uint8_t = byte;
|
||||
using upscaler_ctx_t = Native.Types.upscaler_ctx_t;
|
||||
|
||||
internal unsafe partial class Native
|
||||
{
|
||||
@ -21,6 +36,154 @@ internal unsafe partial class Native
|
||||
|
||||
#endregion
|
||||
|
||||
internal static class Types
|
||||
{
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct sd_tiling_params_t
|
||||
{
|
||||
public sbyte enabled;
|
||||
public int tile_size_x;
|
||||
public int tile_size_y;
|
||||
public float target_overlap;
|
||||
public float rel_size_x;
|
||||
public float rel_size_y;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct sd_ctx_params_t
|
||||
{
|
||||
public byte* model_path;
|
||||
public byte* clip_l_path;
|
||||
public byte* clip_g_path;
|
||||
public byte* clip_vision_path;
|
||||
public byte* t5xxl_path;
|
||||
public byte* qwen2vl_path;
|
||||
public byte* qwen2vl_vision_path;
|
||||
public byte* diffusion_model_path;
|
||||
public byte* high_noise_diffusion_model_path;
|
||||
public byte* vae_path;
|
||||
public byte* taesd_path;
|
||||
public byte* control_net_path;
|
||||
public byte* lora_model_dir;
|
||||
public byte* embedding_dir;
|
||||
public byte* photo_maker_path;
|
||||
public sbyte vae_decode_only;
|
||||
public sbyte free_params_immediately;
|
||||
public int n_threads;
|
||||
public sd_type_t wtype;
|
||||
public rng_type_t rng_type;
|
||||
public prediction_t prediction;
|
||||
public sbyte offload_params_to_cpu;
|
||||
public sbyte keep_clip_on_cpu;
|
||||
public sbyte keep_control_net_on_cpu;
|
||||
public sbyte keep_vae_on_cpu;
|
||||
public sbyte diffusion_flash_attn;
|
||||
public sbyte diffusion_conv_direct;
|
||||
public sbyte vae_conv_direct;
|
||||
public sbyte force_sdxl_vae_conv_scale;
|
||||
public sbyte chroma_use_dit_mask;
|
||||
public sbyte chroma_use_t5_mask;
|
||||
public int chroma_t5_mask_pad;
|
||||
public float flow_shift;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct sd_image_t
|
||||
{
|
||||
public uint32_t width;
|
||||
public uint32_t height;
|
||||
public uint32_t channel;
|
||||
public uint8_t* data;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct sd_slg_params_t
|
||||
{
|
||||
public int* layers;
|
||||
public size_t layer_count;
|
||||
public float layer_start;
|
||||
public float layer_end;
|
||||
public float scale;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct sd_guidance_params_t
|
||||
{
|
||||
public float txt_cfg;
|
||||
public float img_cfg;
|
||||
public float min_cfg;
|
||||
public float distilled_guidance;
|
||||
public sd_slg_params_t slg;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct sd_sample_params_t
|
||||
{
|
||||
public sd_guidance_params_t guidance;
|
||||
public scheduler_t scheduler;
|
||||
public sample_method_t sample_method;
|
||||
public int sample_steps;
|
||||
public float eta;
|
||||
public int shifted_timestep;
|
||||
}
|
||||
|
||||
internal struct sd_pm_params_t
|
||||
{
|
||||
public sd_image_t* id_images;
|
||||
public int id_images_count;
|
||||
public byte* id_embed_path;
|
||||
public float style_strength;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct sd_img_gen_params_t
|
||||
{
|
||||
public byte* prompt;
|
||||
public byte* negative_prompt;
|
||||
public int clip_skip;
|
||||
public sd_image_t init_image;
|
||||
public sd_image_t* ref_images;
|
||||
public int ref_images_count;
|
||||
public sbyte auto_resize_ref_image;
|
||||
public sbyte increase_ref_index;
|
||||
public sd_image_t mask_image;
|
||||
public int width;
|
||||
public int height;
|
||||
public sd_sample_params_t sample_params;
|
||||
public float strength;
|
||||
public int64_t seed;
|
||||
public int batch_count;
|
||||
public sd_image_t control_image;
|
||||
public float control_strength;
|
||||
public sd_pm_params_t pm_params;
|
||||
public sd_tiling_params_t vae_tiling_params;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct sd_vid_gen_params_t
|
||||
{
|
||||
public byte* prompt;
|
||||
public byte* negative_prompt;
|
||||
public int clip_skip;
|
||||
public sd_image_t init_image;
|
||||
public sd_image_t end_image;
|
||||
public sd_image_t* control_frames;
|
||||
public int control_frames_size;
|
||||
public int width;
|
||||
public int height;
|
||||
public sd_sample_params_t sample_params;
|
||||
public sd_sample_params_t high_noise_sample_params;
|
||||
public float moe_boundary;
|
||||
public float strength;
|
||||
public int64_t seed;
|
||||
public int video_frames;
|
||||
public float vace_strength;
|
||||
}
|
||||
|
||||
internal struct sd_ctx_t;
|
||||
internal struct upscaler_ctx_t;
|
||||
}
|
||||
|
||||
#region Delegates
|
||||
|
||||
internal delegate void sd_log_cb_t(sd_log_level_t level, [MarshalAs(UnmanagedType.LPStr)] string text, void* data);
|
||||
@ -28,179 +191,7 @@ internal unsafe partial class Native
|
||||
|
||||
#endregion
|
||||
|
||||
#region DLL-Import
|
||||
|
||||
internal struct sd_ctx_t;
|
||||
internal struct upscaler_ctx_t;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
internal struct sd_image_t
|
||||
{
|
||||
internal uint width;
|
||||
internal uint height;
|
||||
internal uint channel;
|
||||
internal byte* data;
|
||||
}
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "get_num_physical_cores")]
|
||||
internal static partial int get_num_physical_cores();
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "sd_get_system_info")]
|
||||
internal static partial void* sd_get_system_info();
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "new_sd_ctx")]
|
||||
internal static partial sd_ctx_t* new_sd_ctx([MarshalAs(UnmanagedType.LPStr)] string model_path,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string clip_l_path,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string clip_g_path,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string t5xxl_path,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string diffusion_model_path,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string vae_path,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string taesd_path,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string control_net_path_c_str,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string lora_model_dir,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string embed_dir_c_str,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string stacked_id_embed_dir_c_str,
|
||||
[MarshalAs(UnmanagedType.I1)] bool vae_decode_only,
|
||||
[MarshalAs(UnmanagedType.I1)] bool vae_tiling,
|
||||
[MarshalAs(UnmanagedType.I1)] bool free_params_immediately,
|
||||
int n_threads,
|
||||
sd_type_t wtype,
|
||||
rng_type_t rng_type,
|
||||
schedule_t s,
|
||||
[MarshalAs(UnmanagedType.I1)] bool keep_clip_on_cpu,
|
||||
[MarshalAs(UnmanagedType.I1)] bool keep_control_net_cpu,
|
||||
[MarshalAs(UnmanagedType.I1)] bool keep_vae_on_cpu,
|
||||
[MarshalAs(UnmanagedType.I1)] bool diffusion_flash_attn,
|
||||
[MarshalAs(UnmanagedType.I1)] bool chroma_use_dit_mask,
|
||||
[MarshalAs(UnmanagedType.I1)] bool chroma_use_t5_mask,
|
||||
int chroma_t5_mask_pad);
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "free_sd_ctx")]
|
||||
internal static partial void free_sd_ctx(sd_ctx_t* sd_ctx);
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "txt2img")]
|
||||
internal static partial sd_image_t* txt2img(sd_ctx_t* sd_ctx,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string prompt,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string negative_prompt,
|
||||
int clip_skip,
|
||||
float cfg_scale,
|
||||
float guidance,
|
||||
float eta,
|
||||
int width,
|
||||
int height,
|
||||
sample_method_t sample_method,
|
||||
int sample_steps,
|
||||
long seed,
|
||||
int batch_count,
|
||||
sd_image_t* control_cond,
|
||||
float control_strength,
|
||||
float style_strength,
|
||||
[MarshalAs(UnmanagedType.I1)] bool normalize_input,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string input_id_images_path,
|
||||
in int[] skip_layers,
|
||||
int skip_layers_count,
|
||||
float slg_scale,
|
||||
float skip_layer_start,
|
||||
float skip_layer_end);
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "img2img")]
|
||||
internal static partial sd_image_t* img2img(sd_ctx_t* sd_ctx,
|
||||
sd_image_t init_image,
|
||||
sd_image_t mask_image,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string prompt,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string negative_prompt,
|
||||
int clip_skip,
|
||||
float cfg_scale,
|
||||
float guidance,
|
||||
int width,
|
||||
int height,
|
||||
sample_method_t sample_method,
|
||||
int sample_steps,
|
||||
float strength,
|
||||
long seed,
|
||||
int batch_count,
|
||||
sd_image_t* control_cond,
|
||||
float control_strength,
|
||||
float style_strength,
|
||||
[MarshalAs(UnmanagedType.I1)] bool normalize_input,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string input_id_images_path,
|
||||
in int[] skip_layers,
|
||||
int skip_layers_count,
|
||||
float slg_scale,
|
||||
float skip_layer_start,
|
||||
float skip_layer_end);
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "img2vid")]
|
||||
internal static partial sd_image_t* img2vid(sd_ctx_t* sd_ctx,
|
||||
sd_image_t init_image,
|
||||
int width,
|
||||
int height,
|
||||
int video_frames,
|
||||
int motion_bucket_id,
|
||||
int fps,
|
||||
float augmentation_level,
|
||||
float min_cfg,
|
||||
float cfg_scale,
|
||||
sample_method_t sample_method,
|
||||
int sample_steps,
|
||||
float strength,
|
||||
long seed);
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "edit")]
|
||||
internal static partial sd_image_t* edit(sd_ctx_t* sd_ctx,
|
||||
sd_image_t* ref_images,
|
||||
int ref_images_count,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string prompt,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string negative_prompt,
|
||||
int clip_skip,
|
||||
float cfg_scale,
|
||||
float guidance,
|
||||
float eta,
|
||||
int width,
|
||||
int height,
|
||||
sample_method_t sample_method,
|
||||
int sample_steps,
|
||||
float strength,
|
||||
long seed,
|
||||
int batch_count,
|
||||
sd_image_t* control_cond,
|
||||
float control_strength,
|
||||
float style_strength,
|
||||
[MarshalAs(UnmanagedType.I1)] bool normalize_input,
|
||||
in int[] skip_layers,
|
||||
int skip_layers_count,
|
||||
float slg_scale,
|
||||
float skip_layer_start,
|
||||
float skip_layer_end);
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "new_upscaler_ctx")]
|
||||
internal static partial upscaler_ctx_t* new_upscaler_ctx([MarshalAs(UnmanagedType.LPStr)] string esrgan_path,
|
||||
int n_threads,
|
||||
sd_type_t wtype);
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "free_upscaler_ctx")]
|
||||
internal static partial void free_upscaler_ctx(upscaler_ctx_t* upscaler_ctx);
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "upscale")]
|
||||
internal static partial sd_image_t upscale(upscaler_ctx_t* upscaler_ctx,
|
||||
sd_image_t input_image,
|
||||
int upscale_factor);
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "convert")]
|
||||
internal static partial void convert([MarshalAs(UnmanagedType.LPStr)] string input_path,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string vae_path,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string output_path,
|
||||
sd_type_t output_type);
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "preprocess_canny")]
|
||||
internal static partial byte* preprocess_canny(byte* img,
|
||||
int width,
|
||||
int height,
|
||||
float high_threshold,
|
||||
float low_threshold,
|
||||
float weak,
|
||||
float strong,
|
||||
[MarshalAs(UnmanagedType.I1)] bool inverse);
|
||||
#region Methods
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "sd_set_log_callback")]
|
||||
internal static partial void sd_set_log_callback(sd_log_cb_t sd_log_cb, void* data);
|
||||
@ -208,5 +199,137 @@ internal unsafe partial class Native
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "sd_set_progress_callback")]
|
||||
internal static partial void sd_set_progress_callback(sd_progress_cb_t cb, void* data);
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "get_num_physical_cores")]
|
||||
internal static partial int32_t get_num_physical_cores();
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "sd_get_system_info")]
|
||||
[return: MarshalAs(UnmanagedType.LPStr)]
|
||||
internal static partial string sd_get_system_info();
|
||||
|
||||
//
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "sd_type_name")]
|
||||
[return: MarshalAs(UnmanagedType.LPStr)]
|
||||
internal static partial string sd_type_name(sd_type_t type);
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "str_to_sd_type")]
|
||||
internal static partial sd_type_t str_to_sd_type([MarshalAs(UnmanagedType.LPStr)] string str);
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "sd_rng_type_name")]
|
||||
[return: MarshalAs(UnmanagedType.LPStr)]
|
||||
internal static partial string sd_rng_type_name(rng_type_t rng_type);
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "str_to_rng_type")]
|
||||
internal static partial rng_type_t str_to_rng_type([MarshalAs(UnmanagedType.LPStr)] string str);
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "sd_sample_method_name")]
|
||||
[return: MarshalAs(UnmanagedType.LPStr)]
|
||||
internal static partial string sd_sample_method_name(sample_method_t sample_method);
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "str_to_sample_method")]
|
||||
internal static partial sample_method_t str_to_sample_method([MarshalAs(UnmanagedType.LPStr)] string str);
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "sd_schedule_name")]
|
||||
[return: MarshalAs(UnmanagedType.LPStr)]
|
||||
internal static partial string sd_schedule_name(scheduler_t schedule);
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "str_to_schedule")]
|
||||
internal static partial scheduler_t str_to_schedule([MarshalAs(UnmanagedType.LPStr)] string str);
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "sd_prediction_name")]
|
||||
[return: MarshalAs(UnmanagedType.LPStr)]
|
||||
internal static partial string sd_prediction_name(prediction_t prediction);
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "str_to_prediction")]
|
||||
internal static partial prediction_t str_to_prediction([MarshalAs(UnmanagedType.LPStr)] string str);
|
||||
|
||||
//
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "sd_ctx_params_init")]
|
||||
internal static partial void sd_ctx_params_init([MarshalUsing(typeof(DiffusionModelParameterMarshaller))] ref sd_ctx_params_t sd_ctx_params);
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "sd_ctx_params_to_str")]
|
||||
[return: MarshalAs(UnmanagedType.LPStr)]
|
||||
internal static partial string sd_ctx_params_to_str([MarshalUsing(typeof(DiffusionModelParameterMarshaller))] in sd_ctx_params_t sd_ctx_params);
|
||||
|
||||
//
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "new_sd_ctx")]
|
||||
internal static partial sd_ctx_t* new_sd_ctx([MarshalUsing(typeof(DiffusionModelParameterMarshaller))] in sd_ctx_params_t sd_ctx_params);
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "free_sd_ctx")]
|
||||
internal static partial void free_sd_ctx(sd_ctx_t* sd_ctx);
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "sd_get_default_sample_method")]
|
||||
internal static partial sample_method_t sd_get_default_sample_method(sd_ctx_t* sd_ctx);
|
||||
|
||||
//
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "sd_sample_params_init")]
|
||||
internal static partial void sd_sample_params_init([MarshalUsing(typeof(SampleParameterMarshaller))] ref sd_sample_params_t sample_params);
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "sd_sample_params_to_str")]
|
||||
internal static partial char* sd_sample_params_to_str([MarshalUsing(typeof(SampleParameterMarshaller))] in sd_sample_params_t sample_params);
|
||||
|
||||
//
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "sd_img_gen_params_init")]
|
||||
internal static partial void sd_img_gen_params_init([MarshalUsing(typeof(ImageGenerationParameterMarshaller))] ref sd_img_gen_params_t sd_img_gen_params);
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "sd_img_gen_params_to_str")]
|
||||
[return: MarshalAs(UnmanagedType.LPStr)]
|
||||
internal static partial string sd_img_gen_params_to_str([MarshalUsing(typeof(ImageGenerationParameterMarshaller))] in sd_img_gen_params_t sd_img_gen_params);
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "generate_image")]
|
||||
internal static partial sd_image_t* generate_image(sd_ctx_t* sd_ctx, [MarshalUsing(typeof(ImageGenerationParameterMarshaller))] in sd_img_gen_params_t sd_img_gen_params);
|
||||
|
||||
//
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "sd_vid_gen_params_init")]
|
||||
internal static partial void sd_vid_gen_params_init([MarshalUsing(typeof(VideoGenerationParameterMarshaller))] ref sd_vid_gen_params_t sd_vid_gen_params);
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "generate_video")]
|
||||
internal static partial sd_image_t* generate_video(sd_ctx_t* sd_ctx, [MarshalUsing(typeof(VideoGenerationParameterMarshaller))] in sd_vid_gen_params_t sd_vid_gen_params, out int num_frames_out);
|
||||
|
||||
//
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "new_upscaler_ctx")]
|
||||
internal static partial upscaler_ctx_t* new_upscaler_ctx([MarshalAs(UnmanagedType.LPStr)] string esrgan_path,
|
||||
[MarshalAs(UnmanagedType.I1)] bool offload_params_to_cpu,
|
||||
[MarshalAs(UnmanagedType.I1)] bool direct,
|
||||
int n_threads);
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "free_upscaler_ctx")]
|
||||
internal static partial void free_upscaler_ctx(upscaler_ctx_t* upscaler_ctx);
|
||||
|
||||
//
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "upscale")]
|
||||
[return: MarshalUsing(typeof(ImageMarshaller))]
|
||||
internal static partial Image<ColorRGB> upscale(upscaler_ctx_t* upscaler_ctx, [MarshalUsing(typeof(ImageMarshaller))] IImage input_image, uint32_t upscale_factor);
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "get_upscale_factor")]
|
||||
internal static partial int get_upscale_factor(upscaler_ctx_t* upscaler_ctx);
|
||||
|
||||
//
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "convert")]
|
||||
[return: MarshalAs(UnmanagedType.I1)]
|
||||
internal static partial bool convert([MarshalAs(UnmanagedType.LPStr)] string input_path,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string vae_path,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string output_path,
|
||||
sd_type_t output_type,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string tensor_type_rules);
|
||||
|
||||
//
|
||||
|
||||
[LibraryImport(LIB_NAME, EntryPoint = "preprocess_canny")]
|
||||
[return: MarshalAs(UnmanagedType.I1)]
|
||||
internal static partial bool preprocess_canny(sd_image_t image,
|
||||
float high_threshold,
|
||||
float low_threshold,
|
||||
float weak,
|
||||
float strong,
|
||||
[MarshalAs(UnmanagedType.I1)] bool inverse);
|
||||
|
||||
#endregion
|
||||
}
|
||||
@ -56,6 +56,6 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="HPPH" Version="1.0.0" />
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2024.2.0" />
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2025.2.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
||||
@ -10,7 +10,10 @@
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cbuilder/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cbuilder_005Cextensions/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cbuilder_005Cinterfaces/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cextensions/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cinterfaces/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cparameter/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cparameter_005Cextensions/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=models_005Cparameter_005Cinterfaces/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=native/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=native/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=native_005Cmarshaller/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||
@ -1,5 +1,5 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using HPPH;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace StableDiffusion.NET;
|
||||
@ -10,8 +10,8 @@ public static unsafe class StableDiffusionCpp
|
||||
#region Properties & Fields
|
||||
|
||||
// ReSharper disable NotAccessedField.Local - They are important, the delegate can be collected if it's not stored!
|
||||
private static readonly Native.sd_log_cb_t LOG_CALLBACK;
|
||||
private static readonly Native.sd_progress_cb_t PROGRESS_CALLBACK;
|
||||
private static Native.sd_log_cb_t? _logCallback;
|
||||
private static Native.sd_progress_cb_t? _progressCallback;
|
||||
// ReSharper restore NotAccessedField.Local
|
||||
|
||||
#endregion
|
||||
@ -23,38 +23,54 @@ public static unsafe class StableDiffusionCpp
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
static StableDiffusionCpp()
|
||||
{
|
||||
Native.sd_set_log_callback(LOG_CALLBACK = OnNativeLog, null);
|
||||
Native.sd_set_progress_callback(PROGRESS_CALLBACK = OnNativeProgress, null);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
public static bool LoadNativeLibrary(string libraryPath) => Native.LoadNativeLibrary(libraryPath);
|
||||
|
||||
public static void Convert(string modelPath, string vaePath, Quantization quantization, string outputPath)
|
||||
public static void InitializeEvents()
|
||||
{
|
||||
Native.sd_set_log_callback(_logCallback = OnNativeLog, null);
|
||||
Native.sd_set_progress_callback(_progressCallback = OnNativeProgress, null);
|
||||
}
|
||||
|
||||
public static void Convert(string modelPath, string vaePath, Quantization quantization, string outputPath, string tensorTypeRules = "")
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(nameof(modelPath));
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(nameof(outputPath));
|
||||
ArgumentNullException.ThrowIfNull(vaePath);
|
||||
if (!Enum.IsDefined(quantization)) throw new ArgumentOutOfRangeException(nameof(quantization));
|
||||
|
||||
Native.convert(modelPath, vaePath, outputPath, quantization);
|
||||
Native.convert(modelPath, vaePath, outputPath, quantization, tensorTypeRules);
|
||||
}
|
||||
|
||||
public static string GetSystemInfo()
|
||||
{
|
||||
void* s = Native.sd_get_system_info();
|
||||
return Marshal.PtrToStringUTF8((nint)s) ?? "";
|
||||
}
|
||||
public static string GetSystemInfo() => Native.sd_get_system_info();
|
||||
|
||||
public static int GetNumPhysicalCores() => Native.get_num_physical_cores();
|
||||
|
||||
public static Image<ColorRGB> PreprocessCanny(CannyParameter parameter)
|
||||
{
|
||||
parameter.Validate();
|
||||
|
||||
IImage<ColorRGB> controlImage = parameter.Image as IImage<ColorRGB> ?? parameter.Image!.ConvertTo<ColorRGB>();
|
||||
|
||||
Native.Types.sd_image_t sdImage = controlImage.ToSdImage();
|
||||
try
|
||||
{
|
||||
bool result = Native.preprocess_canny(sdImage,
|
||||
parameter.HighThreshold,
|
||||
parameter.LowThreshold,
|
||||
parameter.Weak,
|
||||
parameter.Strong,
|
||||
parameter.Inverse);
|
||||
|
||||
return sdImage.ToImage();
|
||||
}
|
||||
finally
|
||||
{
|
||||
sdImage.Free();
|
||||
}
|
||||
}
|
||||
|
||||
private static void OnNativeLog(LogLevel level, string text, void* data)
|
||||
{
|
||||
try
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user