stable-diffusion.cpp 一个文件解决stable-diffusion所有环境,不需要python,stable-diffusion.dll动态库C#调用Demo
目录
介绍
效果
Text To Image
Image To Image
Upscale
项目
代码
Native.cs
SDHelper.cs
MainForm.cs
下载
介绍
stable-diffusion.cpp 地址:https://github.com/leejet/stable-diffusion.cpp
StableDiffusionSharp 地址:https://github.com/IntptrMax/StableDiffusionSharp
测试模型下载地址:https://huggingface.co/runwayml/stable-diffusion-v1-5
放大模型下载地址:https://github.com/xinntao/Real-ESRGAN/releases/download/v0.2.2.4/RealESRGAN_x4plus_anime_6B.pth
效果
Text To Image
Image To Image
Upscale
项目
代码
Native.cs
using System;
using System.Runtime.InteropServices;
namespace StableDiffusionSharp
{
using static StableDiffusionSharp.Structs;
using int32_t = Int32;
using int64_t = Int64;
using SdContext = IntPtr;
using SDImagePtr = IntPtr;
using UpscalerContext = IntPtr;
internal class Native
{
const string DllName = "stable-diffusion";
internal delegate void SdLogCallback(SdLogLevel level, [MarshalAs(UnmanagedType.LPStr)] string text, IntPtr data);
internal delegate void SdProgressCallback(int step, int steps, float time, IntPtr data);
[DllImport(DllName, EntryPoint = "new_sd_ctx", CallingConvention = CallingConvention.Cdecl)]
internal extern static SdContext new_sd_ctx(string model_path,
string vae_path,
string taesd_path,
string control_net_path_c_str,
string lora_model_dir,
string embed_dir_c_str,
string stacked_id_embed_dir_c_str,
bool vae_decode_only,
bool vae_tiling,
bool free_params_immediately,
int n_threads,
WeightType weightType,
RngType rng_type,
ScheduleType s,
bool keep_clip_on_cpu,
bool keep_control_net_cpu,
bool keep_vae_on_cpu);
[DllImport(DllName, EntryPoint = "txt2img", CallingConvention = CallingConvention.Cdecl)]
internal static extern SDImagePtr txt2img(SdContext sd_ctx,
string prompt,
string negative_prompt,
int clip_skip,
float cfg_scale,
int width,
int height,
SampleMethod sample_method,
int sample_steps,
int64_t seed,
int batch_count,
SDImagePtr control_cond,
float control_strength,
float style_strength,
bool normalize_input,
string input_id_images_path);
[DllImport(DllName, EntryPoint = "img2img", CallingConvention = CallingConvention.Cdecl)]
internal static extern SDImagePtr img2img(SdContext sd_ctx,
SDImage init_image,
string prompt_c_str,
string negative_prompt_c_str,
int clip_skip,
float cfg_scale,
int width,
int height,
SampleMethod sample_method,
int sample_steps,
float strength,
int64_t seed,
int batch_count);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr preprocess_canny(IntPtr imgData,
int width,
int height,
float high_threshold,
float low_threshold,
float weak,
float h2,
bool inverse);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern UpscalerContext new_upscaler_ctx(string esrgan_path,
int n_threads,
WeightType wtype);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern int32_t get_num_physical_cores();
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern void free_sd_ctx(SdContext sd_ctx);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern void free_upscaler_ctx(UpscalerContext upscaler_ctx);
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
internal static extern SDImage upscale(UpscalerContext upscaler_ctx, SDImage input_image, int upscale_factor);
[DllImport(DllName, EntryPoint = "sd_set_log_callback", CallingConvention = CallingConvention.Cdecl)]
internal static extern void sd_set_log_callback(SdLogCallback cb, IntPtr data);
[DllImport(DllName, EntryPoint = "sd_set_progress_callback", CallingConvention = CallingConvention.Cdecl)]
internal static extern void sd_set_progress_callback(SdProgressCallback cb, IntPtr data);
}
}
using System; using System.Runtime.InteropServices; namespace StableDiffusionSharp { using static StableDiffusionSharp.Structs; using int32_t = Int32; using int64_t = Int64; using SdContext = IntPtr; using SDImagePtr = IntPtr; using UpscalerContext = IntPtr; internal class Native { const string DllName = "stable-diffusion"; internal delegate void SdLogCallback(SdLogLevel level, [MarshalAs(UnmanagedType.LPStr)] string text, IntPtr data); internal delegate void SdProgressCallback(int step, int steps, float time, IntPtr data); [DllImport(DllName, EntryPoint = "new_sd_ctx", CallingConvention = CallingConvention.Cdecl)] internal extern static SdContext new_sd_ctx(string model_path, string vae_path, string taesd_path, string control_net_path_c_str, string lora_model_dir, string embed_dir_c_str, string stacked_id_embed_dir_c_str, bool vae_decode_only, bool vae_tiling, bool free_params_immediately, int n_threads, WeightType weightType, RngType rng_type, ScheduleType s, bool keep_clip_on_cpu, bool keep_control_net_cpu, bool keep_vae_on_cpu); [DllImport(DllName, EntryPoint = "txt2img", CallingConvention = CallingConvention.Cdecl)] internal static extern SDImagePtr txt2img(SdContext sd_ctx, string prompt, string negative_prompt, int clip_skip, float cfg_scale, int width, int height, SampleMethod sample_method, int sample_steps, int64_t seed, int batch_count, SDImagePtr control_cond, float control_strength, float style_strength, bool normalize_input, string input_id_images_path); [DllImport(DllName, EntryPoint = "img2img", CallingConvention = CallingConvention.Cdecl)] internal static extern SDImagePtr img2img(SdContext sd_ctx, SDImage init_image, string prompt_c_str, string negative_prompt_c_str, int clip_skip, float cfg_scale, int width, int height, SampleMethod sample_method, int sample_steps, float strength, int64_t seed, int batch_count); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] internal static extern IntPtr preprocess_canny(IntPtr imgData, int width, int height, float high_threshold, float low_threshold, float weak, float h2, bool inverse); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] internal static extern UpscalerContext new_upscaler_ctx(string esrgan_path, int n_threads, WeightType wtype); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] internal static extern int32_t get_num_physical_cores(); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] internal static extern void free_sd_ctx(SdContext sd_ctx); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] internal static extern void free_upscaler_ctx(UpscalerContext upscaler_ctx); [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)] internal static extern SDImage upscale(UpscalerContext upscaler_ctx, SDImage input_image, int upscale_factor); [DllImport(DllName, EntryPoint = "sd_set_log_callback", CallingConvention = CallingConvention.Cdecl)] internal static extern void sd_set_log_callback(SdLogCallback cb, IntPtr data); [DllImport(DllName, EntryPoint = "sd_set_progress_callback", CallingConvention = CallingConvention.Cdecl)] internal static extern void sd_set_progress_callback(SdProgressCallback cb, IntPtr data); } }
SDHelper.cs
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
namespace StableDiffusionSharp
{
using static StableDiffusionSharp.Structs;
using SdContext = IntPtr;
using SDImagePtr = IntPtr;
using UpscalerContext = IntPtr;
public class SDHelper
{
public bool IsInitialized => SdContext.Zero != sd_ctx;
public bool IsUpscalerInitialized => UpscalerContext.Zero != upscaler_ctx;
private SdContext sd_ctx = new SdContext();
private UpscalerContext upscaler_ctx = new UpscalerContext();
public static event EventHandler<StableDiffusionEventArgs.StableDiffusionLogEventArgs> Log;
public static event EventHandler<StableDiffusionEventArgs.StableDiffusionProgressEventArgs> Progress;
static readonly Native.SdLogCallback sd_Log_Cb;
static readonly Native.SdProgressCallback sd_Progress_Cb;
static SDHelper()
{
sd_Log_Cb = new Native.SdLogCallback(OnNativeLog);
Native.sd_set_log_callback(sd_Log_Cb, IntPtr.Zero);
sd_Progress_Cb = new Native.SdProgressCallback(OnProgressRunning);
Native.sd_set_progress_callback(sd_Progress_Cb, IntPtr.Zero);
}
public bool Initialize(ModelParams modelParams)
{
sd_ctx = Native.new_sd_ctx(modelParams.ModelPath,
modelParams.VaePath,
modelParams.TaesdPath,
modelParams.ControlnetPath,
modelParams.LoraModelDir,
modelParams.EmbeddingsPath,
modelParams.StackedIdEmbeddingsPath,
modelParams.VaeDecodeOnly,
modelParams.VaeTiling,
modelParams.FreeParamsImmediately,
modelParams.Threads,
modelParams.SdType,
modelParams.RngType,
modelParams.Schedule,
modelParams.KeepClipOnCpu,
modelParams.KeepControlNetOnCpu,
modelParams.KeepVaeOnCpu);
return SdContext.Zero != sd_ctx;
}
public bool InitializeUpscaler(UpscalerParams @params)
{
upscaler_ctx = Native.new_upscaler_ctx(@params.ESRGANPath, @params.Threads, @params.SdType);
return UpscalerContext.Zero != upscaler_ctx;
}
public void FreeSD()
{
if (SdContext.Zero != sd_ctx)
{
Native.free_sd_ctx(sd_ctx);
sd_ctx = SdContext.Zero;
}
}
public void FreeUpscaler()
{
if (UpscalerContext.Zero != upscaler_ctx)
{
Native.free_upscaler_ctx(upscaler_ctx);
upscaler_ctx = UpscalerContext.Zero;
}
}
public Bitmap[] TextToImage(TextToImageParams textToImageParams)
{
if (!IsInitialized) throw new ArgumentNullException("Model not loaded!");
SDImagePtr sd_Image_ptr = Native.txt2img(sd_ctx,
textToImageParams.Prompt,
textToImageParams.NegativePrompt,
textToImageParams.ClipSkip,
textToImageParams.CfgScale,
textToImageParams.Width,
textToImageParams.Height,
textToImageParams.SampleMethod,
textToImageParams.SampleSteps,
textToImageParams.Seed,
textToImageParams.BatchCount,
SDImagePtr.Zero,
textToImageParams.ControlStrength,
textToImageParams.StyleStrength,
textToImageParams.NormalizeInput,
textToImageParams.InputIdImagesPath);
Bitmap[] images = new Bitmap[textToImageParams.BatchCount];
for (int i = 0; i < textToImageParams.BatchCount; i++)
{
SDImage sd_image = Marshal.PtrToStructure<SDImage>(sd_Image_ptr + i * Marshal.SizeOf<SDImage>());
images[i] = GetBitmapFromSdImage(sd_image);
}
return images;
}
public Bitmap ImageToImage(ImageToImageParams imageToImageParams)
{
if (!IsInitialized) throw new ArgumentNullException("Model not loaded!");
SDImage input_sd_image = GetSDImageFromBitmap(imageToImageParams.InputImage);
SDImagePtr sdImgPtr = Native.img2img(sd_ctx,
input_sd_image,
imageToImageParams.Prompt,
imageToImageParams.NegativePrompt,
imageToImageParams.ClipSkip,
imageToImageParams.CfgScale,
imageToImageParams.Width,
imageToImageParams.Height,
imageToImageParams.SampleMethod,
imageToImageParams.SampleSteps,
imageToImageParams.Strength,
imageToImageParams.Seed,
imageToImageParams.BatchCount);
SDImage sdImg = Marshal.PtrToStructure<SDImage>(sdImgPtr);
return GetBitmapFromSdImage(sdImg);
}
public Bitmap UpscaleImage(Bitmap image, int upscaleFactor)
{
if (!IsUpscalerInitialized) throw new ArgumentNullException("Upscaler not loaded!");
SDImage inputSDImg = GetSDImageFromBitmap(image);
SDImage result = Native.upscale(upscaler_ctx, inputSDImg, upscaleFactor);
return GetBitmapFromSdImage(result);
}
private Bitmap GetBitmapFromSdImage(SDImage sd_Image)
{
int width = (int)sd_Image.Width;
int height = (int)sd_Image.Height;
int channel = (int)sd_Image.Channel;
byte[] bytes = new byte[width * height * channel];
Marshal.Copy(sd_Image.Data, bytes, 0, bytes.Length);
Bitmap bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb);
int stride = bmp.Width * channel;
byte[] des = new byte[bytes.Length];
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
des[stride * i + channel * j + 0] = bytes[stride * i + channel * j + 2];
des[stride * i + channel * j + 1] = bytes[stride * i + channel * j + 1];
des[stride * i + channel * j + 2] = bytes[stride * i + channel * j + 0];
}
}
BitmapData bitmapData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, bmp.PixelFormat);
Marshal.Copy(des, 0, bitmapData.Scan0, bytes.Length);
bmp.UnlockBits(bitmapData);
return bmp;
}
private SDImage GetSDImageFromBitmap(Bitmap bmp)
{
int width = bmp.Width;
int height = bmp.Height;
int channel = Bitmap.GetPixelFormatSize(bmp.PixelFormat) / 8;
int stride = width * channel;
byte[] bytes = new byte[width * height * channel];
BitmapData bitmapData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, bmp.PixelFormat);
Marshal.Copy(bitmapData.Scan0, bytes, 0, bytes.Length);
bmp.UnlockBits(bitmapData);
byte[] sdImageBytes = new byte[bytes.Length];
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
sdImageBytes[stride * i + j * 3 + 0] = bytes[stride * i + j * 3 + 2];
sdImageBytes[stride * i + j * 3 + 1] = bytes[stride * i + j * 3 + 1];
sdImageBytes[stride * i + j * 3 + 2] = bytes[stride * i + j * 3 + 0];
}
}
SDImage sd_Image = new SDImage
{
Width = (uint)width,
Height = (uint)height,
Channel = 3,
Data = Marshal.UnsafeAddrOfPinnedArrayElement(sdImageBytes, 0),
};
return sd_Image;
}
private static void OnNativeLog(SdLogLevel level, string text, IntPtr data)
{
Log?.Invoke(null, new StableDiffusionEventArgs.StableDiffusionLogEventArgs { Level = level, Text = text });
}
private static void OnProgressRunning(int step, int steps, float time, IntPtr data)
{
Progress?.Invoke(null, new StableDiffusionEventArgs.StableDiffusionProgressEventArgs { Step = step, Steps = steps, Time = time });
}
}
}
using System; using System.Drawing; using System.Drawing.Imaging; using System.Runtime.InteropServices; namespace StableDiffusionSharp { using static StableDiffusionSharp.Structs; using SdContext = IntPtr; using SDImagePtr = IntPtr; using UpscalerContext = IntPtr; public class SDHelper { public bool IsInitialized => SdContext.Zero != sd_ctx; public bool IsUpscalerInitialized => UpscalerContext.Zero != upscaler_ctx; private SdContext sd_ctx = new SdContext(); private UpscalerContext upscaler_ctx = new UpscalerContext(); public static event EventHandler<StableDiffusionEventArgs.StableDiffusionLogEventArgs> Log; public static event EventHandler<StableDiffusionEventArgs.StableDiffusionProgressEventArgs> Progress; static readonly Native.SdLogCallback sd_Log_Cb; static readonly Native.SdProgressCallback sd_Progress_Cb; static SDHelper() { sd_Log_Cb = new Native.SdLogCallback(OnNativeLog); Native.sd_set_log_callback(sd_Log_Cb, IntPtr.Zero); sd_Progress_Cb = new Native.SdProgressCallback(OnProgressRunning); Native.sd_set_progress_callback(sd_Progress_Cb, IntPtr.Zero); } public bool Initialize(ModelParams modelParams) { sd_ctx = Native.new_sd_ctx(modelParams.ModelPath, modelParams.VaePath, modelParams.TaesdPath, modelParams.ControlnetPath, modelParams.LoraModelDir, modelParams.EmbeddingsPath, modelParams.StackedIdEmbeddingsPath, modelParams.VaeDecodeOnly, modelParams.VaeTiling, modelParams.FreeParamsImmediately, modelParams.Threads, modelParams.SdType, modelParams.RngType, modelParams.Schedule, modelParams.KeepClipOnCpu, modelParams.KeepControlNetOnCpu, modelParams.KeepVaeOnCpu); return SdContext.Zero != sd_ctx; } public bool InitializeUpscaler(UpscalerParams @params) { upscaler_ctx = Native.new_upscaler_ctx(@params.ESRGANPath, @params.Threads, @params.SdType); return UpscalerContext.Zero != upscaler_ctx; } public void FreeSD() { if (SdContext.Zero != sd_ctx) { Native.free_sd_ctx(sd_ctx); sd_ctx = SdContext.Zero; } } public void FreeUpscaler() { if (UpscalerContext.Zero != upscaler_ctx) { Native.free_upscaler_ctx(upscaler_ctx); upscaler_ctx = UpscalerContext.Zero; } } public Bitmap[] TextToImage(TextToImageParams textToImageParams) { if (!IsInitialized) throw new ArgumentNullException("Model not loaded!"); SDImagePtr sd_Image_ptr = Native.txt2img(sd_ctx, textToImageParams.Prompt, textToImageParams.NegativePrompt, textToImageParams.ClipSkip, textToImageParams.CfgScale, textToImageParams.Width, textToImageParams.Height, textToImageParams.SampleMethod, textToImageParams.SampleSteps, textToImageParams.Seed, textToImageParams.BatchCount, SDImagePtr.Zero, textToImageParams.ControlStrength, textToImageParams.StyleStrength, textToImageParams.NormalizeInput, textToImageParams.InputIdImagesPath); Bitmap[] images = new Bitmap[textToImageParams.BatchCount]; for (int i = 0; i < textToImageParams.BatchCount; i++) { SDImage sd_image = Marshal.PtrToStructure<SDImage>(sd_Image_ptr + i * Marshal.SizeOf<SDImage>()); images[i] = GetBitmapFromSdImage(sd_image); } return images; } public Bitmap ImageToImage(ImageToImageParams imageToImageParams) { if (!IsInitialized) throw new ArgumentNullException("Model not loaded!"); SDImage input_sd_image = GetSDImageFromBitmap(imageToImageParams.InputImage); SDImagePtr sdImgPtr = Native.img2img(sd_ctx, input_sd_image, imageToImageParams.Prompt, imageToImageParams.NegativePrompt, imageToImageParams.ClipSkip, imageToImageParams.CfgScale, imageToImageParams.Width, imageToImageParams.Height, imageToImageParams.SampleMethod, imageToImageParams.SampleSteps, imageToImageParams.Strength, imageToImageParams.Seed, imageToImageParams.BatchCount); SDImage sdImg = Marshal.PtrToStructure<SDImage>(sdImgPtr); return GetBitmapFromSdImage(sdImg); } public Bitmap UpscaleImage(Bitmap image, int upscaleFactor) { if (!IsUpscalerInitialized) throw new ArgumentNullException("Upscaler not loaded!"); SDImage inputSDImg = GetSDImageFromBitmap(image); SDImage result = Native.upscale(upscaler_ctx, inputSDImg, upscaleFactor); return GetBitmapFromSdImage(result); } private Bitmap GetBitmapFromSdImage(SDImage sd_Image) { int width = (int)sd_Image.Width; int height = (int)sd_Image.Height; int channel = (int)sd_Image.Channel; byte[] bytes = new byte[width * height * channel]; Marshal.Copy(sd_Image.Data, bytes, 0, bytes.Length); Bitmap bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb); int stride = bmp.Width * channel; byte[] des = new byte[bytes.Length]; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { des[stride * i + channel * j + 0] = bytes[stride * i + channel * j + 2]; des[stride * i + channel * j + 1] = bytes[stride * i + channel * j + 1]; des[stride * i + channel * j + 2] = bytes[stride * i + channel * j + 0]; } } BitmapData bitmapData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, bmp.PixelFormat); Marshal.Copy(des, 0, bitmapData.Scan0, bytes.Length); bmp.UnlockBits(bitmapData); return bmp; } private SDImage GetSDImageFromBitmap(Bitmap bmp) { int width = bmp.Width; int height = bmp.Height; int channel = Bitmap.GetPixelFormatSize(bmp.PixelFormat) / 8; int stride = width * channel; byte[] bytes = new byte[width * height * channel]; BitmapData bitmapData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, bmp.PixelFormat); Marshal.Copy(bitmapData.Scan0, bytes, 0, bytes.Length); bmp.UnlockBits(bitmapData); byte[] sdImageBytes = new byte[bytes.Length]; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { sdImageBytes[stride * i + j * 3 + 0] = bytes[stride * i + j * 3 + 2]; sdImageBytes[stride * i + j * 3 + 1] = bytes[stride * i + j * 3 + 1]; sdImageBytes[stride * i + j * 3 + 2] = bytes[stride * i + j * 3 + 0]; } } SDImage sd_Image = new SDImage { Width = (uint)width, Height = (uint)height, Channel = 3, Data = Marshal.UnsafeAddrOfPinnedArrayElement(sdImageBytes, 0), }; return sd_Image; } private static void OnNativeLog(SdLogLevel level, string text, IntPtr data) { Log?.Invoke(null, new StableDiffusionEventArgs.StableDiffusionLogEventArgs { Level = level, Text = text }); } private static void OnProgressRunning(int step, int steps, float time, IntPtr data) { Progress?.Invoke(null, new StableDiffusionEventArgs.StableDiffusionProgressEventArgs { Step = step, Steps = steps, Time = time }); } } }
MainForm.cs
using StableDiffusionSharp; using System; using System.Diagnostics; using System.Drawing; using System.IO; using System.Threading.Tasks; using System.Windows.Forms; namespace StableDiffusionSharpGUI { public partial class MainForm : Form { private readonly SDHelper helper = new SDHelper(); public MainForm() { InitializeComponent(); } private void Button_LoadModel_Click(object sender, EventArgs e) { if (Button_LoadModel.Text == "Load Model") { if (!helper.IsInitialized) { string modelPath = TextBox_ModelPath.Text; string vaePath = TextBox_VaePath.Text; string loraModelDir = TextBox_LoraModelDir.Text; bool keepVaeOnCpu = CheckBox_CpuVae.Checked; bool vaeTiling = CheckBox_VaeTiling.Checked; if (!File.Exists(modelPath)) { Button_LoadModel.Enabled = true; MessageBox.Show("Cannot find the Model"); return; } Task.Run(() => { Button_LoadModel.Invoke((Action)delegate { Button_LoadModel.Enabled = false; TextBox_ModelPath.Enabled = false; TextBox_VaePath.Enabled = false; TextBox_LoraModelDir.Enabled = false; CheckBox_CpuVae.Enabled = false; CheckBox_VaeTiling.Enabled = false; Button_ScanLoraPath.Enabled = false; Button_ScanModelPath.Enabled = false; Button_ScanVaePath.Enabled = false; }); Structs.ModelParams modelParams = new Structs.ModelParams { ModelPath = modelPath, VaePath = vaePath, RngType = Structs.RngType.CUDA_RNG, KeepVaeOnCpu = keepVaeOnCpu, VaeTiling = vaeTiling, LoraModelDir = loraModelDir, }; bool result = helper.Initialize(modelParams); Debug.WriteLine(result ? "Model loaded" : "Model not loaded"); Button_LoadModel.Invoke((Action)delegate { Button_LoadModel.Text = "Unload Model"; Button_LoadModel.Enabled = true; }); }); } } else { helper.FreeSD(); Button_LoadModel.Text = "Load Model"; TextBox_ModelPath.Enabled = true; TextBox_VaePath.Enabled = true; TextBox_LoraModelDir.Enabled = true; CheckBox_CpuVae.Enabled = true; CheckBox_VaeTiling.Enabled = true; Button_ScanLoraPath.Enabled = true; Button_ScanModelPath.Enabled = true; Button_ScanVaePath.Enabled = true; } } private void Helper_Progress(object sender, StableDiffusionEventArgs.StableDiffusionProgressEventArgs e) { base.Invoke((Action)delegate { label11.Text = $"{e.Step}/{e.Steps}"; label14.Text = $"{e.IterationsPerSecond:f2} it/s"; ProgressBar_Progress.Value = (int)((e.Progress > 1 ? 1 : e.Progress) * 100); }); } private void Button_TextToImage_Click(object sender, EventArgs e) { if (!helper.IsInitialized) { MessageBox.Show("Please load Model first"); return; } Math.DivRem((int)NumericUpDown_Width.Value, 64, out int result1); Math.DivRem((int)NumericUpDown_Height.Value, 64, out int result2); if (result1 != 0 || result2 != 0) { MessageBox.Show("The width and height of the generated image must be a multiple of 64"); return; } Button_TextToImage.Enabled = false; Button_ImageToImage.Enabled = false; Structs.TextToImageParams textToImageParams = new Structs.TextToImageParams { Prompt = TextBox_Prompt.Text, NegativePrompt = TextBox_NegativePrompt.Text, SampleMethod = (Structs.SampleMethod)Enum.Parse(typeof(Structs.SampleMethod), ComboBox_SampleMethod.Text), Width = (int)NumericUpDown_Width.Value, Height = (int)NumericUpDown_Height.Value, NormalizeInput = true, ClipSkip = (int)NumericUpDown_ClipSkip.Value, CfgScale = (float)NumericUpDown_CFG.Value, SampleSteps = (int)NumericUpDown_SampleSteps.Value, Seed = (long)NumericUpDown_Seed.Value, }; Task.Run(() => { Stopwatch stopwatch = new Stopwatch(); stopwatch.Restart(); Bitmap[] outputImages = helper.TextToImage(textToImageParams); for (int i = 0; i < outputImages.Length; i++) { if (!Directory.Exists("output")) { Directory.CreateDirectory("output"); } if (!Directory.Exists("./output/txt2img")) { Directory.CreateDirectory("./output/txt2img"); } outputImages[i].Save($"./output/txt2img/{DateTime.Now:yyyyMMddHHmmss}-{i}.png"); } base.Invoke((Action)delegate { PictureBox_OutputImage.Image = outputImages[0]; Button_TextToImage.Enabled = true; Button_ImageToImage.Enabled = true; }); Debug.WriteLine($"Time to elapsed: {stopwatch.ElapsedMilliseconds} ms"); }); } private void MainForm_Load(object sender, EventArgs e) { SDHelper.Log += SDHelper_Log; SDHelper.Progress += Helper_Progress; ComboBox_SampleMethod.Items.AddRange(Enum.GetNames(typeof(Structs.SampleMethod))); ComboBox_SampleMethod.SelectedIndex = 0; PictureBox_InputImage.AllowDrop = true; PictureBox_UpscaleInput.AllowDrop = true; } private void SDHelper_Log(object sender, StableDiffusionEventArgs.StableDiffusionLogEventArgs e) { Console.WriteLine($"time:{DateTime.Now}, {e.Level}: {e.Text}"); if (e.Text.Contains("vae compute")) { base.Invoke((Action)delegate { label12.Text = "VAE Progress"; }); } else if (e.Text.Contains("generating image")) { base.Invoke((Action)delegate { label12.Text = "Generate Progress"; }); } } private void Button_ScanModelPath_Click(object sender, EventArgs e) { FileDialog fileDialog = new OpenFileDialog { Filter = "Safetensors Files (*.safetensors)|*.safetensors|CheckPoint Files (*.ckpt)|*.ckpt|GGUF Files (*.gguf)|*.gguf|All Files (*.*)|*.*" }; if (fileDialog.ShowDialog() == DialogResult.OK) { TextBox_ModelPath.Text = fileDialog.FileName; } } private void Button_ScanVaePath_Click(object sender, EventArgs e) { FileDialog fileDialog = new OpenFileDialog { Filter = "Safetensors Files (*.safetensors)|*.safetensors|CheckPoint Files (*.ckpt)|*.ckpt|GGUF Files (*.gguf)|*.gguf|All Files (*.*)|*.*" }; if (fileDialog.ShowDialog() == DialogResult.OK) { TextBox_VaePath.Text = fileDialog.FileName; } } private void Button_ScanLoraPath_Click(object sender, EventArgs e) { FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog(); if (folderBrowserDialog.ShowDialog() == DialogResult.OK) { TextBox_LoraModelDir.Text = folderBrowserDialog.SelectedPath; } } private void Button_ImageToImage_Click(object sender, EventArgs e) { if (!helper.IsInitialized) { MessageBox.Show("Please load a Model"); return; } if (null == PictureBox_InputImage.Image) { MessageBox.Show("Please select an Image"); return; } Bitmap inputBitmap = PictureBox_InputImage.Image.Clone() as Bitmap; Math.DivRem(inputBitmap.Width, 64, out int result1); Math.DivRem(inputBitmap.Height, 64, out int result2); if (result1 != 0 || result2 != 0) { MessageBox.Show("The width and height of the generated image must be a multiple of 64"); return; } Button_TextToImage.Enabled = false; Button_ImageToImage.Enabled = false; Structs.ImageToImageParams imageToImageParams = new Structs.ImageToImageParams { InputImage = inputBitmap, Prompt = TextBox_Prompt.Text, NegativePrompt = TextBox_NegativePrompt.Text, CfgScale = (float)NumericUpDown_CFG.Value, Width = inputBitmap.Width, Height = inputBitmap.Height, SampleMethod = (Structs.SampleMethod)Enum.Parse(typeof(Structs.SampleMethod), ComboBox_SampleMethod.Text), SampleSteps = (int)NumericUpDown_SampleSteps.Value, Strength = (float)NumericUpDown_ReDrawStrength.Value, Seed = (long)NumericUpDown_Seed.Value, ClipSkip = (int)NumericUpDown_ClipSkip.Value, }; Task.Run(() => { Bitmap outputImage = helper.ImageToImage(imageToImageParams); if (!Directory.Exists("output")) { Directory.CreateDirectory("output"); } if (!Directory.Exists("./output/img2img")) { Directory.CreateDirectory("./output/img2img"); } outputImage.Save($"./output/img2img/{DateTime.Now:yyyyMMddHHmmss}.png"); base.Invoke((Action)delegate { PictureBox_OutputImage.Image = outputImage; Button_TextToImage.Enabled = true; Button_ImageToImage.Enabled = true; Button_TextToImage.Enabled = true; }); }); } private void Form1_FormClosed(object sender, FormClosedEventArgs e) { helper.FreeSD(); helper.FreeUpscaler(); GC.Collect(); } private void Button_RandomSeed_Click(object sender, EventArgs e) { Random random = new Random(); int randomPositiveInteger = random.Next(1, int.MaxValue); NumericUpDown_Seed.Value = randomPositiveInteger; } private void PictureBox_InputImage_Click(object sender, EventArgs e) { OpenFileDialog openFileDialog = new OpenFileDialog { Filter = "Image Files (*.png, *.jpg, *.bmp)|*.png;*.jpg;*.bmp" }; if (openFileDialog.ShowDialog() == DialogResult.OK) { Bitmap bitmap = new Bitmap(openFileDialog.FileName); PictureBox_InputImage.Image = bitmap; } } private void PictureBox_InputImage_DragEnter(object sender, DragEventArgs e) { if (e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effect = DragDropEffects.Link; else e.Effect = DragDropEffects.None; } private void PictureBox_InputImage_DragDrop(object sender, DragEventArgs e) { string fileName = ((Array)e.Data.GetData(DataFormats.FileDrop)).GetValue(0).ToString(); Bitmap bitmap = new Bitmap(fileName); PictureBox_InputImage.Image = bitmap; } private void Button_ScanUpscaleModelPath_Click(object sender, EventArgs e) { OpenFileDialog openFileDialog = new OpenFileDialog { Filter = "ESRGAN Files (*.pth)|*.pth" }; if (openFileDialog.ShowDialog() == DialogResult.OK) { TextBox_UpscaleModelPath.Text = openFileDialog.FileName; } } private void PictureBox_UpscaleInput_DragDrop(object sender, DragEventArgs e) { string fileName = ((Array)e.Data.GetData(DataFormats.FileDrop)).GetValue(0).ToString(); Bitmap bitmap = new Bitmap(fileName); PictureBox_UpscaleInput.Image = bitmap; } private void PictureBox_UpscaleInput_DragEnter(object sender, DragEventArgs e) { if (e.Data.GetDataPresent(DataFormats.FileDrop)) e.Effect = DragDropEffects.Link; else e.Effect = DragDropEffects.None; } private void Button_Upscale_Click(object sender, EventArgs e) { if (string.IsNullOrEmpty(TextBox_UpscaleModelPath.Text)) { MessageBox.Show("Please select a upscale Model"); return; } bool upscalerInited = helper.InitializeUpscaler(new Structs.UpscalerParams { ESRGANPath = TextBox_UpscaleModelPath.Text, }); if (!upscalerInited) { MessageBox.Show("There is an error in loading upscale Model"); return; } if (PictureBox_UpscaleInput.Image == null) { MessageBox.Show("Please select an Image"); return; } Bitmap upscaleInputImage = PictureBox_UpscaleInput.Image as Bitmap; Button_Upscale.Enabled = false; Task.Run(() => { try { Button_Upscale.Enabled = false; Bitmap bitmap = helper.UpscaleImage(PictureBox_UpscaleInput.Image as Bitmap, 4); helper.FreeUpscaler(); if (!Directory.Exists("output")) { Directory.CreateDirectory("output"); } if (!Directory.Exists("./output/upscale")) { Directory.CreateDirectory("./output/upscale"); } bitmap.Save($"./output/upscale/{DateTime.Now:yyyyMMddHHmmss}.png"); base.Invoke((Action)delegate { PictureBox_UpscaleOutput.Image = bitmap; }); } catch (Exception ex) { MessageBox.Show(ex.Message); } finally { base.Invoke((Action)delegate { Button_Upscale.Enabled = true; }); helper.FreeUpscaler(); } }); } private void PictureBox_UpscaleInput_Click(object sender, EventArgs e) { OpenFileDialog openFileDialog = new OpenFileDialog { Filter = "Image Files (*.png, *.jpg, *.bmp)|*.png;*.jpg;*.bmp" }; if (openFileDialog.ShowDialog() == DialogResult.OK) { Bitmap bitmap = new Bitmap(openFileDialog.FileName); PictureBox_UpscaleInput.Image = bitmap; } } } }
下载
源码下载
diffusionnativeivastablediffusionideclitpuctopromptstemcpuclipragactionganthreadselopngatscreate