当前位置:   article > 正文

stable-diffusion.cpp 一个文件解决stable diffusion所有环境,不需要python,stable-diffusion.dll动态库C#调用Demo_stable diffusion cpp

stable diffusion cpp

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 strong,
                                 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);

    }
}

  1. using System;
  2. using System.Runtime.InteropServices;
  3. namespace StableDiffusionSharp
  4. {
  5. using static StableDiffusionSharp.Structs;
  6. using int32_t = Int32;
  7. using int64_t = Int64;
  8. using SdContext = IntPtr;
  9. using SDImagePtr = IntPtr;
  10. using UpscalerContext = IntPtr;
  11. internal class Native
  12. {
  13. const string DllName = "stable-diffusion";
  14. internal delegate void SdLogCallback(SdLogLevel level, [MarshalAs(UnmanagedType.LPStr)] string text, IntPtr data);
  15. internal delegate void SdProgressCallback(int step, int steps, float time, IntPtr data);
  16. [DllImport(DllName, EntryPoint = "new_sd_ctx", CallingConvention = CallingConvention.Cdecl)]
  17. internal extern static SdContext new_sd_ctx(string model_path,
  18. string vae_path,
  19. string taesd_path,
  20. string control_net_path_c_str,
  21. string lora_model_dir,
  22. string embed_dir_c_str,
  23. string stacked_id_embed_dir_c_str,
  24. bool vae_decode_only,
  25. bool vae_tiling,
  26. bool free_params_immediately,
  27. int n_threads,
  28. WeightType weightType,
  29. RngType rng_type,
  30. ScheduleType s,
  31. bool keep_clip_on_cpu,
  32. bool keep_control_net_cpu,
  33. bool keep_vae_on_cpu);
  34. [DllImport(DllName, EntryPoint = "txt2img", CallingConvention = CallingConvention.Cdecl)]
  35. internal static extern SDImagePtr txt2img(SdContext sd_ctx,
  36. string prompt,
  37. string negative_prompt,
  38. int clip_skip,
  39. float cfg_scale,
  40. int width,
  41. int height,
  42. SampleMethod sample_method,
  43. int sample_steps,
  44. int64_t seed,
  45. int batch_count,
  46. SDImagePtr control_cond,
  47. float control_strength,
  48. float style_strength,
  49. bool normalize_input,
  50. string input_id_images_path);
  51. [DllImport(DllName, EntryPoint = "img2img", CallingConvention = CallingConvention.Cdecl)]
  52. internal static extern SDImagePtr img2img(SdContext sd_ctx,
  53. SDImage init_image,
  54. string prompt_c_str,
  55. string negative_prompt_c_str,
  56. int clip_skip,
  57. float cfg_scale,
  58. int width,
  59. int height,
  60. SampleMethod sample_method,
  61. int sample_steps,
  62. float strength,
  63. int64_t seed,
  64. int batch_count);
  65. [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
  66. internal static extern IntPtr preprocess_canny(IntPtr imgData,
  67. int width,
  68. int height,
  69. float high_threshold,
  70. float low_threshold,
  71. float weak,
  72. float strong,
  73. bool inverse);
  74. [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
  75. internal static extern UpscalerContext new_upscaler_ctx(string esrgan_path,
  76. int n_threads,
  77. WeightType wtype);
  78. [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
  79. internal static extern int32_t get_num_physical_cores();
  80. [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
  81. internal static extern void free_sd_ctx(SdContext sd_ctx);
  82. [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
  83. internal static extern void free_upscaler_ctx(UpscalerContext upscaler_ctx);
  84. [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
  85. internal static extern SDImage upscale(UpscalerContext upscaler_ctx, SDImage input_image, int upscale_factor);
  86. [DllImport(DllName, EntryPoint = "sd_set_log_callback", CallingConvention = CallingConvention.Cdecl)]
  87. internal static extern void sd_set_log_callback(SdLogCallback cb, IntPtr data);
  88. [DllImport(DllName, EntryPoint = "sd_set_progress_callback", CallingConvention = CallingConvention.Cdecl)]
  89. internal static extern void sd_set_progress_callback(SdProgressCallback cb, IntPtr data);
  90. }
  91. }

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 });
        }


    }
}

  1. using System;
  2. using System.Drawing;
  3. using System.Drawing.Imaging;
  4. using System.Runtime.InteropServices;
  5. namespace StableDiffusionSharp
  6. {
  7. using static StableDiffusionSharp.Structs;
  8. using SdContext = IntPtr;
  9. using SDImagePtr = IntPtr;
  10. using UpscalerContext = IntPtr;
  11. public class SDHelper
  12. {
  13. public bool IsInitialized => SdContext.Zero != sd_ctx;
  14. public bool IsUpscalerInitialized => UpscalerContext.Zero != upscaler_ctx;
  15. private SdContext sd_ctx = new SdContext();
  16. private UpscalerContext upscaler_ctx = new UpscalerContext();
  17. public static event EventHandler<StableDiffusionEventArgs.StableDiffusionLogEventArgs> Log;
  18. public static event EventHandler<StableDiffusionEventArgs.StableDiffusionProgressEventArgs> Progress;
  19. static readonly Native.SdLogCallback sd_Log_Cb;
  20. static readonly Native.SdProgressCallback sd_Progress_Cb;
  21. static SDHelper()
  22. {
  23. sd_Log_Cb = new Native.SdLogCallback(OnNativeLog);
  24. Native.sd_set_log_callback(sd_Log_Cb, IntPtr.Zero);
  25. sd_Progress_Cb = new Native.SdProgressCallback(OnProgressRunning);
  26. Native.sd_set_progress_callback(sd_Progress_Cb, IntPtr.Zero);
  27. }
  28. public bool Initialize(ModelParams modelParams)
  29. {
  30. sd_ctx = Native.new_sd_ctx(modelParams.ModelPath,
  31. modelParams.VaePath,
  32. modelParams.TaesdPath,
  33. modelParams.ControlnetPath,
  34. modelParams.LoraModelDir,
  35. modelParams.EmbeddingsPath,
  36. modelParams.StackedIdEmbeddingsPath,
  37. modelParams.VaeDecodeOnly,
  38. modelParams.VaeTiling,
  39. modelParams.FreeParamsImmediately,
  40. modelParams.Threads,
  41. modelParams.SdType,
  42. modelParams.RngType,
  43. modelParams.Schedule,
  44. modelParams.KeepClipOnCpu,
  45. modelParams.KeepControlNetOnCpu,
  46. modelParams.KeepVaeOnCpu);
  47. return SdContext.Zero != sd_ctx;
  48. }
  49. public bool InitializeUpscaler(UpscalerParams @params)
  50. {
  51. upscaler_ctx = Native.new_upscaler_ctx(@params.ESRGANPath, @params.Threads, @params.SdType);
  52. return UpscalerContext.Zero != upscaler_ctx;
  53. }
  54. public void FreeSD()
  55. {
  56. if (SdContext.Zero != sd_ctx)
  57. {
  58. Native.free_sd_ctx(sd_ctx);
  59. sd_ctx = SdContext.Zero;
  60. }
  61. }
  62. public void FreeUpscaler()
  63. {
  64. if (UpscalerContext.Zero != upscaler_ctx)
  65. {
  66. Native.free_upscaler_ctx(upscaler_ctx);
  67. upscaler_ctx = UpscalerContext.Zero;
  68. }
  69. }
  70. public Bitmap[] TextToImage(TextToImageParams textToImageParams)
  71. {
  72. if (!IsInitialized) throw new ArgumentNullException("Model not loaded!");
  73. SDImagePtr sd_Image_ptr = Native.txt2img(sd_ctx,
  74. textToImageParams.Prompt,
  75. textToImageParams.NegativePrompt,
  76. textToImageParams.ClipSkip,
  77. textToImageParams.CfgScale,
  78. textToImageParams.Width,
  79. textToImageParams.Height,
  80. textToImageParams.SampleMethod,
  81. textToImageParams.SampleSteps,
  82. textToImageParams.Seed,
  83. textToImageParams.BatchCount,
  84. SDImagePtr.Zero,
  85. textToImageParams.ControlStrength,
  86. textToImageParams.StyleStrength,
  87. textToImageParams.NormalizeInput,
  88. textToImageParams.InputIdImagesPath);
  89. Bitmap[] images = new Bitmap[textToImageParams.BatchCount];
  90. for (int i = 0; i < textToImageParams.BatchCount; i++)
  91. {
  92. SDImage sd_image = Marshal.PtrToStructure<SDImage>(sd_Image_ptr + i * Marshal.SizeOf<SDImage>());
  93. images[i] = GetBitmapFromSdImage(sd_image);
  94. }
  95. return images;
  96. }
  97. public Bitmap ImageToImage(ImageToImageParams imageToImageParams)
  98. {
  99. if (!IsInitialized) throw new ArgumentNullException("Model not loaded!");
  100. SDImage input_sd_image = GetSDImageFromBitmap(imageToImageParams.InputImage);
  101. SDImagePtr sdImgPtr = Native.img2img(sd_ctx,
  102. input_sd_image,
  103. imageToImageParams.Prompt,
  104. imageToImageParams.NegativePrompt,
  105. imageToImageParams.ClipSkip,
  106. imageToImageParams.CfgScale,
  107. imageToImageParams.Width,
  108. imageToImageParams.Height,
  109. imageToImageParams.SampleMethod,
  110. imageToImageParams.SampleSteps,
  111. imageToImageParams.Strength,
  112. imageToImageParams.Seed,
  113. imageToImageParams.BatchCount);
  114. SDImage sdImg = Marshal.PtrToStructure<SDImage>(sdImgPtr);
  115. return GetBitmapFromSdImage(sdImg);
  116. }
  117. public Bitmap UpscaleImage(Bitmap image, int upscaleFactor)
  118. {
  119. if (!IsUpscalerInitialized) throw new ArgumentNullException("Upscaler not loaded!");
  120. SDImage inputSDImg = GetSDImageFromBitmap(image);
  121. SDImage result = Native.upscale(upscaler_ctx, inputSDImg, upscaleFactor);
  122. return GetBitmapFromSdImage(result);
  123. }
  124. private Bitmap GetBitmapFromSdImage(SDImage sd_Image)
  125. {
  126. int width = (int)sd_Image.Width;
  127. int height = (int)sd_Image.Height;
  128. int channel = (int)sd_Image.Channel;
  129. byte[] bytes = new byte[width * height * channel];
  130. Marshal.Copy(sd_Image.Data, bytes, 0, bytes.Length);
  131. Bitmap bmp = new Bitmap(width, height, PixelFormat.Format24bppRgb);
  132. int stride = bmp.Width * channel;
  133. byte[] des = new byte[bytes.Length];
  134. for (int i = 0; i < height; i++)
  135. {
  136. for (int j = 0; j < width; j++)
  137. {
  138. des[stride * i + channel * j + 0] = bytes[stride * i + channel * j + 2];
  139. des[stride * i + channel * j + 1] = bytes[stride * i + channel * j + 1];
  140. des[stride * i + channel * j + 2] = bytes[stride * i + channel * j + 0];
  141. }
  142. }
  143. BitmapData bitmapData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, bmp.PixelFormat);
  144. Marshal.Copy(des, 0, bitmapData.Scan0, bytes.Length);
  145. bmp.UnlockBits(bitmapData);
  146. return bmp;
  147. }
  148. private SDImage GetSDImageFromBitmap(Bitmap bmp)
  149. {
  150. int width = bmp.Width;
  151. int height = bmp.Height;
  152. int channel = Bitmap.GetPixelFormatSize(bmp.PixelFormat) / 8;
  153. int stride = width * channel;
  154. byte[] bytes = new byte[width * height * channel];
  155. BitmapData bitmapData = bmp.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, bmp.PixelFormat);
  156. Marshal.Copy(bitmapData.Scan0, bytes, 0, bytes.Length);
  157. bmp.UnlockBits(bitmapData);
  158. byte[] sdImageBytes = new byte[bytes.Length];
  159. for (int i = 0; i < height; i++)
  160. {
  161. for (int j = 0; j < width; j++)
  162. {
  163. sdImageBytes[stride * i + j * 3 + 0] = bytes[stride * i + j * 3 + 2];
  164. sdImageBytes[stride * i + j * 3 + 1] = bytes[stride * i + j * 3 + 1];
  165. sdImageBytes[stride * i + j * 3 + 2] = bytes[stride * i + j * 3 + 0];
  166. }
  167. }
  168. SDImage sd_Image = new SDImage
  169. {
  170. Width = (uint)width,
  171. Height = (uint)height,
  172. Channel = 3,
  173. Data = Marshal.UnsafeAddrOfPinnedArrayElement(sdImageBytes, 0),
  174. };
  175. return sd_Image;
  176. }
  177. private static void OnNativeLog(SdLogLevel level, string text, IntPtr data)
  178. {
  179. Log?.Invoke(null, new StableDiffusionEventArgs.StableDiffusionLogEventArgs { Level = level, Text = text });
  180. }
  181. private static void OnProgressRunning(int step, int steps, float time, IntPtr data)
  182. {
  183. Progress?.Invoke(null, new StableDiffusionEventArgs.StableDiffusionProgressEventArgs { Step = step, Steps = steps, Time = time });
  184. }
  185. }
  186. }

MainForm.cs

  1. using StableDiffusionSharp;
  2. using System;
  3. using System.Diagnostics;
  4. using System.Drawing;
  5. using System.IO;
  6. using System.Threading.Tasks;
  7. using System.Windows.Forms;
  8. namespace StableDiffusionSharpGUI
  9. {
  10. public partial class MainForm : Form
  11. {
  12. private readonly SDHelper helper = new SDHelper();
  13. public MainForm()
  14. {
  15. InitializeComponent();
  16. }
  17. private void Button_LoadModel_Click(object sender, EventArgs e)
  18. {
  19. if (Button_LoadModel.Text == "Load Model")
  20. {
  21. if (!helper.IsInitialized)
  22. {
  23. string modelPath = TextBox_ModelPath.Text;
  24. string vaePath = TextBox_VaePath.Text;
  25. string loraModelDir = TextBox_LoraModelDir.Text;
  26. bool keepVaeOnCpu = CheckBox_CpuVae.Checked;
  27. bool vaeTiling = CheckBox_VaeTiling.Checked;
  28. if (!File.Exists(modelPath))
  29. {
  30. Button_LoadModel.Enabled = true;
  31. MessageBox.Show("Cannot find the Model");
  32. return;
  33. }
  34. Task.Run(() =>
  35. {
  36. Button_LoadModel.Invoke((Action)delegate
  37. {
  38. Button_LoadModel.Enabled = false;
  39. TextBox_ModelPath.Enabled = false;
  40. TextBox_VaePath.Enabled = false;
  41. TextBox_LoraModelDir.Enabled = false;
  42. CheckBox_CpuVae.Enabled = false;
  43. CheckBox_VaeTiling.Enabled = false;
  44. Button_ScanLoraPath.Enabled = false;
  45. Button_ScanModelPath.Enabled = false;
  46. Button_ScanVaePath.Enabled = false;
  47. });
  48. Structs.ModelParams modelParams = new Structs.ModelParams
  49. {
  50. ModelPath = modelPath,
  51. VaePath = vaePath,
  52. RngType = Structs.RngType.CUDA_RNG,
  53. KeepVaeOnCpu = keepVaeOnCpu,
  54. VaeTiling = vaeTiling,
  55. LoraModelDir = loraModelDir,
  56. };
  57. bool result = helper.Initialize(modelParams);
  58. Debug.WriteLine(result ? "Model loaded" : "Model not loaded");
  59. Button_LoadModel.Invoke((Action)delegate
  60. {
  61. Button_LoadModel.Text = "Unload Model";
  62. Button_LoadModel.Enabled = true;
  63. });
  64. });
  65. }
  66. }
  67. else
  68. {
  69. helper.FreeSD();
  70. Button_LoadModel.Text = "Load Model";
  71. TextBox_ModelPath.Enabled = true;
  72. TextBox_VaePath.Enabled = true;
  73. TextBox_LoraModelDir.Enabled = true;
  74. CheckBox_CpuVae.Enabled = true;
  75. CheckBox_VaeTiling.Enabled = true;
  76. Button_ScanLoraPath.Enabled = true;
  77. Button_ScanModelPath.Enabled = true;
  78. Button_ScanVaePath.Enabled = true;
  79. }
  80. }
  81. private void Helper_Progress(object sender, StableDiffusionEventArgs.StableDiffusionProgressEventArgs e)
  82. {
  83. base.Invoke((Action)delegate
  84. {
  85. label11.Text = $"{e.Step}/{e.Steps}";
  86. label14.Text = $"{e.IterationsPerSecond:f2} it/s";
  87. ProgressBar_Progress.Value = (int)((e.Progress > 1 ? 1 : e.Progress) * 100);
  88. });
  89. }
  90. private void Button_TextToImage_Click(object sender, EventArgs e)
  91. {
  92. if (!helper.IsInitialized)
  93. {
  94. MessageBox.Show("Please load Model first");
  95. return;
  96. }
  97. Math.DivRem((int)NumericUpDown_Width.Value, 64, out int result1);
  98. Math.DivRem((int)NumericUpDown_Height.Value, 64, out int result2);
  99. if (result1 != 0 || result2 != 0)
  100. {
  101. MessageBox.Show("The width and height of the generated image must be a multiple of 64");
  102. return;
  103. }
  104. Button_TextToImage.Enabled = false;
  105. Button_ImageToImage.Enabled = false;
  106. Structs.TextToImageParams textToImageParams = new Structs.TextToImageParams
  107. {
  108. Prompt = TextBox_Prompt.Text,
  109. NegativePrompt = TextBox_NegativePrompt.Text,
  110. SampleMethod = (Structs.SampleMethod)Enum.Parse(typeof(Structs.SampleMethod), ComboBox_SampleMethod.Text),
  111. Width = (int)NumericUpDown_Width.Value,
  112. Height = (int)NumericUpDown_Height.Value,
  113. NormalizeInput = true,
  114. ClipSkip = (int)NumericUpDown_ClipSkip.Value,
  115. CfgScale = (float)NumericUpDown_CFG.Value,
  116. SampleSteps = (int)NumericUpDown_SampleSteps.Value,
  117. Seed = (long)NumericUpDown_Seed.Value,
  118. };
  119. Task.Run(() =>
  120. {
  121. Stopwatch stopwatch = new Stopwatch();
  122. stopwatch.Restart();
  123. Bitmap[] outputImages = helper.TextToImage(textToImageParams);
  124. for (int i = 0; i < outputImages.Length; i++)
  125. {
  126. if (!Directory.Exists("output"))
  127. {
  128. Directory.CreateDirectory("output");
  129. }
  130. if (!Directory.Exists("./output/txt2img"))
  131. {
  132. Directory.CreateDirectory("./output/txt2img");
  133. }
  134. outputImages[i].Save($"./output/txt2img/{DateTime.Now:yyyyMMddHHmmss}-{i}.png");
  135. }
  136. base.Invoke((Action)delegate
  137. {
  138. PictureBox_OutputImage.Image = outputImages[0];
  139. Button_TextToImage.Enabled = true;
  140. Button_ImageToImage.Enabled = true;
  141. });
  142. Debug.WriteLine($"Time to elapsed: {stopwatch.ElapsedMilliseconds} ms");
  143. });
  144. }
  145. private void MainForm_Load(object sender, EventArgs e)
  146. {
  147. SDHelper.Log += SDHelper_Log;
  148. SDHelper.Progress += Helper_Progress;
  149. ComboBox_SampleMethod.Items.AddRange(Enum.GetNames(typeof(Structs.SampleMethod)));
  150. ComboBox_SampleMethod.SelectedIndex = 0;
  151. PictureBox_InputImage.AllowDrop = true;
  152. PictureBox_UpscaleInput.AllowDrop = true;
  153. }
  154. private void SDHelper_Log(object sender, StableDiffusionEventArgs.StableDiffusionLogEventArgs e)
  155. {
  156. Console.WriteLine($"time:{DateTime.Now}, {e.Level}: {e.Text}");
  157. if (e.Text.Contains("vae compute"))
  158. {
  159. base.Invoke((Action)delegate { label12.Text = "VAE Progress"; });
  160. }
  161. else if (e.Text.Contains("generating image"))
  162. {
  163. base.Invoke((Action)delegate { label12.Text = "Generate Progress"; });
  164. }
  165. }
  166. private void Button_ScanModelPath_Click(object sender, EventArgs e)
  167. {
  168. FileDialog fileDialog = new OpenFileDialog
  169. {
  170. Filter = "Safetensors Files (*.safetensors)|*.safetensors|CheckPoint Files (*.ckpt)|*.ckpt|GGUF Files (*.gguf)|*.gguf|All Files (*.*)|*.*"
  171. };
  172. if (fileDialog.ShowDialog() == DialogResult.OK)
  173. {
  174. TextBox_ModelPath.Text = fileDialog.FileName;
  175. }
  176. }
  177. private void Button_ScanVaePath_Click(object sender, EventArgs e)
  178. {
  179. FileDialog fileDialog = new OpenFileDialog
  180. {
  181. Filter = "Safetensors Files (*.safetensors)|*.safetensors|CheckPoint Files (*.ckpt)|*.ckpt|GGUF Files (*.gguf)|*.gguf|All Files (*.*)|*.*"
  182. };
  183. if (fileDialog.ShowDialog() == DialogResult.OK)
  184. {
  185. TextBox_VaePath.Text = fileDialog.FileName;
  186. }
  187. }
  188. private void Button_ScanLoraPath_Click(object sender, EventArgs e)
  189. {
  190. FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
  191. if (folderBrowserDialog.ShowDialog() == DialogResult.OK)
  192. {
  193. TextBox_LoraModelDir.Text = folderBrowserDialog.SelectedPath;
  194. }
  195. }
  196. private void Button_ImageToImage_Click(object sender, EventArgs e)
  197. {
  198. if (!helper.IsInitialized)
  199. {
  200. MessageBox.Show("Please load a Model");
  201. return;
  202. }
  203. if (null == PictureBox_InputImage.Image)
  204. {
  205. MessageBox.Show("Please select an Image");
  206. return;
  207. }
  208. Bitmap inputBitmap = PictureBox_InputImage.Image.Clone() as Bitmap;
  209. Math.DivRem(inputBitmap.Width, 64, out int result1);
  210. Math.DivRem(inputBitmap.Height, 64, out int result2);
  211. if (result1 != 0 || result2 != 0)
  212. {
  213. MessageBox.Show("The width and height of the generated image must be a multiple of 64");
  214. return;
  215. }
  216. Button_TextToImage.Enabled = false;
  217. Button_ImageToImage.Enabled = false;
  218. Structs.ImageToImageParams imageToImageParams = new Structs.ImageToImageParams
  219. {
  220. InputImage = inputBitmap,
  221. Prompt = TextBox_Prompt.Text,
  222. NegativePrompt = TextBox_NegativePrompt.Text,
  223. CfgScale = (float)NumericUpDown_CFG.Value,
  224. Width = inputBitmap.Width,
  225. Height = inputBitmap.Height,
  226. SampleMethod = (Structs.SampleMethod)Enum.Parse(typeof(Structs.SampleMethod), ComboBox_SampleMethod.Text),
  227. SampleSteps = (int)NumericUpDown_SampleSteps.Value,
  228. Strength = (float)NumericUpDown_ReDrawStrength.Value,
  229. Seed = (long)NumericUpDown_Seed.Value,
  230. ClipSkip = (int)NumericUpDown_ClipSkip.Value,
  231. };
  232. Task.Run(() =>
  233. {
  234. Bitmap outputImage = helper.ImageToImage(imageToImageParams);
  235. if (!Directory.Exists("output"))
  236. {
  237. Directory.CreateDirectory("output");
  238. }
  239. if (!Directory.Exists("./output/img2img"))
  240. {
  241. Directory.CreateDirectory("./output/img2img");
  242. }
  243. outputImage.Save($"./output/img2img/{DateTime.Now:yyyyMMddHHmmss}.png");
  244. base.Invoke((Action)delegate
  245. {
  246. PictureBox_OutputImage.Image = outputImage;
  247. Button_TextToImage.Enabled = true;
  248. Button_ImageToImage.Enabled = true;
  249. Button_TextToImage.Enabled = true;
  250. });
  251. });
  252. }
  253. private void Form1_FormClosed(object sender, FormClosedEventArgs e)
  254. {
  255. helper.FreeSD();
  256. helper.FreeUpscaler();
  257. GC.Collect();
  258. }
  259. private void Button_RandomSeed_Click(object sender, EventArgs e)
  260. {
  261. Random random = new Random();
  262. int randomPositiveInteger = random.Next(1, int.MaxValue);
  263. NumericUpDown_Seed.Value = randomPositiveInteger;
  264. }
  265. private void PictureBox_InputImage_Click(object sender, EventArgs e)
  266. {
  267. OpenFileDialog openFileDialog = new OpenFileDialog
  268. {
  269. Filter = "Image Files (*.png, *.jpg, *.bmp)|*.png;*.jpg;*.bmp"
  270. };
  271. if (openFileDialog.ShowDialog() == DialogResult.OK)
  272. {
  273. Bitmap bitmap = new Bitmap(openFileDialog.FileName);
  274. PictureBox_InputImage.Image = bitmap;
  275. }
  276. }
  277. private void PictureBox_InputImage_DragEnter(object sender, DragEventArgs e)
  278. {
  279. if (e.Data.GetDataPresent(DataFormats.FileDrop))
  280. e.Effect = DragDropEffects.Link;
  281. else e.Effect = DragDropEffects.None;
  282. }
  283. private void PictureBox_InputImage_DragDrop(object sender, DragEventArgs e)
  284. {
  285. string fileName = ((Array)e.Data.GetData(DataFormats.FileDrop)).GetValue(0).ToString();
  286. Bitmap bitmap = new Bitmap(fileName);
  287. PictureBox_InputImage.Image = bitmap;
  288. }
  289. private void Button_ScanUpscaleModelPath_Click(object sender, EventArgs e)
  290. {
  291. OpenFileDialog openFileDialog = new OpenFileDialog
  292. {
  293. Filter = "ESRGAN Files (*.pth)|*.pth"
  294. };
  295. if (openFileDialog.ShowDialog() == DialogResult.OK)
  296. {
  297. TextBox_UpscaleModelPath.Text = openFileDialog.FileName;
  298. }
  299. }
  300. private void PictureBox_UpscaleInput_DragDrop(object sender, DragEventArgs e)
  301. {
  302. string fileName = ((Array)e.Data.GetData(DataFormats.FileDrop)).GetValue(0).ToString();
  303. Bitmap bitmap = new Bitmap(fileName);
  304. PictureBox_UpscaleInput.Image = bitmap;
  305. }
  306. private void PictureBox_UpscaleInput_DragEnter(object sender, DragEventArgs e)
  307. {
  308. if (e.Data.GetDataPresent(DataFormats.FileDrop))
  309. e.Effect = DragDropEffects.Link;
  310. else e.Effect = DragDropEffects.None;
  311. }
  312. private void Button_Upscale_Click(object sender, EventArgs e)
  313. {
  314. if (string.IsNullOrEmpty(TextBox_UpscaleModelPath.Text))
  315. {
  316. MessageBox.Show("Please select a upscale Model");
  317. return;
  318. }
  319. bool upscalerInited = helper.InitializeUpscaler(new Structs.UpscalerParams
  320. {
  321. ESRGANPath = TextBox_UpscaleModelPath.Text,
  322. });
  323. if (!upscalerInited)
  324. {
  325. MessageBox.Show("There is an error in loading upscale Model");
  326. return;
  327. }
  328. if (PictureBox_UpscaleInput.Image == null)
  329. {
  330. MessageBox.Show("Please select an Image");
  331. return;
  332. }
  333. Bitmap upscaleInputImage = PictureBox_UpscaleInput.Image as Bitmap;
  334. Button_Upscale.Enabled = false;
  335. Task.Run(() =>
  336. {
  337. try
  338. {
  339. Button_Upscale.Enabled = false;
  340. Bitmap bitmap = helper.UpscaleImage(PictureBox_UpscaleInput.Image as Bitmap, 4);
  341. helper.FreeUpscaler();
  342. if (!Directory.Exists("output"))
  343. {
  344. Directory.CreateDirectory("output");
  345. }
  346. if (!Directory.Exists("./output/upscale"))
  347. {
  348. Directory.CreateDirectory("./output/upscale");
  349. }
  350. bitmap.Save($"./output/upscale/{DateTime.Now:yyyyMMddHHmmss}.png");
  351. base.Invoke((Action)delegate { PictureBox_UpscaleOutput.Image = bitmap; });
  352. }
  353. catch (Exception ex)
  354. {
  355. MessageBox.Show(ex.Message);
  356. }
  357. finally
  358. {
  359. base.Invoke((Action)delegate { Button_Upscale.Enabled = true; });
  360. helper.FreeUpscaler();
  361. }
  362. });
  363. }
  364. private void PictureBox_UpscaleInput_Click(object sender, EventArgs e)
  365. {
  366. OpenFileDialog openFileDialog = new OpenFileDialog
  367. {
  368. Filter = "Image Files (*.png, *.jpg, *.bmp)|*.png;*.jpg;*.bmp"
  369. };
  370. if (openFileDialog.ShowDialog() == DialogResult.OK)
  371. {
  372. Bitmap bitmap = new Bitmap(openFileDialog.FileName);
  373. PictureBox_UpscaleInput.Image = bitmap;
  374. }
  375. }
  376. }
  377. }

下载 

源码下载

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/正经夜光杯/article/detail/739779
推荐阅读
相关标签
  

闽ICP备14008679号