├── .gitignore ├── .gitmodules ├── LICENSE.txt ├── docs ├── interrogation example.png ├── main window.png ├── project settings.png ├── settings.png └── yolo mask generation.png ├── publish.ps1 ├── readme.md └── src ├── .gitignore ├── ImageUtil ├── ImageConverter.cs ├── ImageUtil.csproj ├── Interrogation │ ├── CogVLM2Interrogator.cs │ ├── ConfiguredInterrogationContext.cs │ ├── INaturalLanguageInterrogator.cs │ ├── ITagInterrogator.cs │ ├── JoyCaptionAlphaOne.cs │ ├── JoyCaptionAlphaTwo.cs │ ├── JoyCaptionBetaOne.cs │ ├── JoyCaptionPreAlpha.cs │ └── SWTagger.cs ├── KumikoWrapper.cs ├── MetaTags.cs ├── PythonImageEngine.cs ├── PythonUtilities.cs ├── PythonWrapper.cs ├── Utility.cs └── python │ ├── cogvlm2 │ ├── interrogate.py │ └── requirements.txt │ ├── joycaption │ └── interrogate.py │ ├── joycaptionalphaone │ └── interrogate.py │ ├── joycaptionalphatwo │ └── interrogate.py │ ├── joycaptionbetaone │ └── interrogate.py │ ├── sw │ └── interrogate.py │ └── utilities │ ├── main.py │ └── requirements.txt ├── SdWebUiApi ├── Api │ └── DefaultApi.cs ├── Client │ ├── ApiClient.cs │ ├── ApiException.cs │ ├── ApiResponse.cs │ ├── ClientUtils.cs │ ├── Configuration.cs │ ├── ExceptionFactory.cs │ ├── GlobalConfiguration.cs │ ├── HttpMethod.cs │ ├── IApiAccessor.cs │ ├── IAsynchronousClient.cs │ ├── IReadableConfiguration.cs │ ├── ISynchronousClient.cs │ ├── Multimap.cs │ ├── OpenAPIDateConverter.cs │ ├── RequestOptions.cs │ └── RetryConfiguration.cs ├── InterrogateMethod.cs ├── InterrogateResult.cs ├── MaskedContent.cs ├── Model │ ├── AbstractOpenAPISchema.cs │ ├── BodyDetectControlnetDetectPost.cs │ ├── BodyRembgRemoveRembgPost.cs │ ├── CreateResponse.cs │ ├── EmbeddingItem.cs │ ├── EmbeddingsResponse.cs │ ├── Estimation.cs │ ├── ExtrasBatchImagesRequest.cs │ ├── ExtrasBatchImagesResponse.cs │ ├── ExtrasSingleImageRequest.cs │ ├── ExtrasSingleImageResponse.cs │ ├── FaceRestorerItem.cs │ ├── FileData.cs │ ├── Flags.cs │ ├── HTTPValidationError.cs │ ├── HypernetworkItem.cs │ ├── ImageToImageResponse.cs │ ├── InterrogateRequest.cs │ ├── LatentUpscalerModeItem.cs │ ├── LocationInner.cs │ ├── MemoryResponse.cs │ ├── ModulesApiModelsProgressResponse.cs │ ├── ModulesProgressProgressResponse.cs │ ├── Options.cs │ ├── PNGInfoRequest.cs │ ├── PNGInfoResponse.cs │ ├── Person.cs │ ├── PoseData.cs │ ├── PredictBody.cs │ ├── PreprocessResponse.cs │ ├── ProgressRequest.cs │ ├── PromptStyleItem.cs │ ├── QuicksettingsHint.cs │ ├── RealesrganItem.cs │ ├── Request.cs │ ├── ResetBody.cs │ ├── SDModelItem.cs │ ├── SDVaeItem.cs │ ├── SamplerItem.cs │ ├── ScriptArg.cs │ ├── ScriptInfo.cs │ ├── ScriptsList.cs │ ├── StableDiffusionProcessingImg2Img.cs │ ├── StableDiffusionProcessingTxt2Img.cs │ ├── TextToImageResponse.cs │ ├── TrainResponse.cs │ ├── UpscalerItem.cs │ └── ValidationError.cs ├── RemBgModels.cs ├── RemBgResult.cs ├── SamplingMethod.cs └── SdWebUiApi.csproj ├── StableDiffusionTagManager.sln ├── StableDiffusionTagManager ├── .gitignore ├── App.axaml ├── App.axaml.cs ├── Assets │ └── logo.ico ├── Attributes │ ├── ServiceAttribute.cs │ └── SupportedPlatformsAttribute.cs ├── Behaviors │ └── CloseWindowOnEventBehavior.cs ├── Collections │ └── OrderedSetObservableCollection.cs ├── Controls │ ├── AdvancedImageBox.axaml │ ├── AdvancedImageBox.axaml.cs │ ├── HeaderControl.cs │ ├── IDialogWithResult.cs │ ├── ImageBoxWithControls.axaml │ ├── ImageBoxWithControls.axaml.cs │ ├── TagAutoCompleteBox.axaml │ └── TagAutoCompleteBox.axaml.cs ├── Converters │ ├── BitmapPixelSizeConverter.cs │ ├── ColorBrushConverter.cs │ ├── ImageViewerModeToBoolConverter.cs │ ├── InterrogateMethodToBooleanConverter.cs │ ├── MaskedContentToStringConverter.cs │ ├── ReviewModeToBoolConverter.cs │ └── TagCollectionBackgroundConverter.cs ├── Extensions │ ├── BitmapExtensions.cs │ ├── ByteArrayExtensions.cs │ ├── IEnumerableExtensions.cs │ ├── LockedFramebufferExtensions.cs │ ├── MaskResult.cs │ ├── PixelFormatExtensions.cs │ └── StringExtensions.cs ├── Models │ ├── ImageAspectRatioSet.cs │ ├── ImageFilterMode.cs │ ├── ImageResolution.cs │ ├── Project.cs │ ├── Settings.cs │ ├── TagCategorySet.cs │ ├── TagCollection.cs │ ├── TagCountModel.cs │ └── XmlSettingsFile.cs ├── Program.cs ├── Roots.xml ├── ServiceCollectionExtensions.cs ├── Services │ ├── ComicPanelExtractor.cs │ ├── DialogHandler.cs │ ├── ViewModelFactory.cs │ └── WebApiFactory.cs ├── StableDiffusionTagManager.csproj ├── Styles │ ├── Controls │ │ ├── Checkbox.axaml │ │ ├── Dialog.axaml │ │ ├── HeaderControl.axaml │ │ ├── InputForm.axaml │ │ ├── NumericUpDown.axaml │ │ ├── Overlay.axaml │ │ ├── Tag.axaml │ │ └── Toolbar.axaml │ ├── Icons.axaml │ └── Styles.axaml ├── ViewLocator.cs ├── ViewModels │ ├── CheckBoxViewModel.cs │ ├── DefaultNaturalLanguageInterrogationViewModel.cs │ ├── DefaultTagInterrogationViewModel.cs │ ├── DropdownSelectItem.cs │ ├── INaturalLanguageInterrogatorViewModelFactory.cs │ ├── ITaggerViewModelFactory.cs │ ├── ImageReviewViewModel.cs │ ├── ImageWithTagsViewModel.cs │ ├── InterrogationDialogViewModel.cs │ ├── InterrogatorViewModel.cs │ ├── JoyCaptionAlphaTwoNaturalLanguageInterrogationViewModel.cs │ ├── JoyCaptionAlphaTwoTagInterrogationViewModel.cs │ ├── JoyCaptionBetaOneNaturalLanguageInterrogationViewModel.cs │ ├── JoyCaptionBetaOneTagInterrogationViewModel.cs │ ├── MainWindowViewModel.cs │ ├── TagCollectionViewModel.cs │ ├── TagCountLetterGroupViewModel.cs │ ├── TagCountViewModel.cs │ ├── TagPrioritySetButtonViewModel.cs │ ├── TagPrioritySetViewModel.cs │ ├── TagViewModel.cs │ ├── ViewModelBase.cs │ ├── YOLOModelSelectorDialogViewModel.cs │ └── YOLOModelSelectorViewModel.cs ├── Views │ ├── ColorPickerDialog.axaml │ ├── ColorPickerDialog.axaml.cs │ ├── DefaultNaturalLanguageInterrogationView.axaml │ ├── DefaultNaturalLanguageInterrogationView.axaml.cs │ ├── DefaultTagInterrogationView.axaml │ ├── DefaultTagInterrogationView.axaml.cs │ ├── DropdownSelectDialog.axaml │ ├── DropdownSelectDialog.axaml.cs │ ├── ExpandImageDialog.axaml │ ├── ExpandImageDialog.axaml.cs │ ├── ImageReviewDialog.axaml │ ├── ImageReviewDialog.axaml.cs │ ├── ImageTouchupDialog.axaml │ ├── ImageTouchupDialog.axaml.cs │ ├── ImageViewerWindow.axaml │ ├── ImageViewerWindow.axaml.cs │ ├── InterrogationDialog.axaml │ ├── InterrogationDialog.axaml.cs │ ├── JoyCaptionAlphaTwoNaturalLanguageInterrogationView.axaml │ ├── JoyCaptionAlphaTwoNaturalLanguageInterrogationView.axaml.cs │ ├── JoyCaptionAlphaTwoTagInterrogationView.axaml │ ├── JoyCaptionAlphaTwoTagInterrogationView.axaml.cs │ ├── JoyCaptionBetaOneNaturalLanguageInterrogationView.axaml │ ├── JoyCaptionBetaOneNaturalLanguageInterrogationView.axaml.cs │ ├── JoyCaptionBetaOneTagInterrogationView.axaml │ ├── JoyCaptionBetaOneTagInterrogationView.axaml.cs │ ├── MainWindow.axaml │ ├── MainWindow.axaml.cs │ ├── NewItemNameDialog.axaml │ ├── NewItemNameDialog.axaml.cs │ ├── ProjectSettingsDialog.axaml │ ├── ProjectSettingsDialog.axaml.cs │ ├── SettingsDialog.axaml │ ├── SettingsDialog.axaml.cs │ ├── TagPrioritySetManagerDialog.axaml │ ├── TagPrioritySetManagerDialog.axaml.cs │ ├── TagSearchDialog.axaml │ ├── TagSearchDialog.axaml.cs │ ├── TextInputDialog.axaml │ ├── TextInputDialog.axaml.cs │ ├── YOLOModelSelectorDialog.axaml │ ├── YOLOModelSelectorDialog.axaml.cs │ ├── YOLOModelSelectorView.axaml │ └── YOLOModelSelectorView.axaml.cs └── app.manifest └── TagUtil ├── FolderTagSets.cs ├── ImageData.cs ├── StringExtensions.cs ├── TagSet.cs └── TagUtil.csproj /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "submodules/kumiko"] 2 | path = submodules/kumiko 3 | url = https://github.com/njean42/kumiko.git 4 | -------------------------------------------------------------------------------- /docs/interrogation example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PMahern/StableDiffusionTagManager/687d4d433c96565bd5c7ea6089ddb4141da9197c/docs/interrogation example.png -------------------------------------------------------------------------------- /docs/main window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PMahern/StableDiffusionTagManager/687d4d433c96565bd5c7ea6089ddb4141da9197c/docs/main window.png -------------------------------------------------------------------------------- /docs/project settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PMahern/StableDiffusionTagManager/687d4d433c96565bd5c7ea6089ddb4141da9197c/docs/project settings.png -------------------------------------------------------------------------------- /docs/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PMahern/StableDiffusionTagManager/687d4d433c96565bd5c7ea6089ddb4141da9197c/docs/settings.png -------------------------------------------------------------------------------- /docs/yolo mask generation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PMahern/StableDiffusionTagManager/687d4d433c96565bd5c7ea6089ddb4141da9197c/docs/yolo mask generation.png -------------------------------------------------------------------------------- /publish.ps1: -------------------------------------------------------------------------------- 1 | $versionsuffix = "0.22.0" 2 | $projectpath = "src/StableDiffusionTagManager/StableDiffusionTagManager.csproj" 3 | $platforms = "win10-x64", "linux-x64", "osx-x64" 4 | 5 | function publish($platform) { 6 | dotnet publish $projectpath -c Release -r $platform /p:PublishSingleFile=true --version-suffix $versionsuffix -o "publish\$($platform)" 7 | } 8 | 9 | foreach($platform in $platforms) { 10 | publish($platform) 11 | } 12 | 13 | 14 | $osxzip = "publish\sdtm-osx-x64-$($versionsuffix).zip" 15 | $windowszip = "publish\sdtm-win10-x64-$($versionsuffix).zip" 16 | $linuxtemptar = "publish\temp.tar" 17 | $linuxtargz = "publish\sdtm-linux-x64-$($versionsuffix).tgz" 18 | 19 | if(Test-Path $osxzip) { 20 | Remove-Item $osxzip 21 | } 22 | if(Test-Path $windowszip) { 23 | Remove-Item $windowszip 24 | } 25 | if(Test-Path $linuxtemptar) { 26 | Remove-Item $linuxtemptar 27 | } 28 | if(Test-Path $linuxtargz) { 29 | Remove-Item $linuxtargz 30 | } 31 | 32 | $originalDir = Get-Location 33 | Set-Location .\publish\osx-x64 34 | 7z a -tzip ..\..\$osxzip "*" 35 | Set-Location $originalDir\publish\win10-x64 36 | 7z a -tzip ..\..\$windowszip "*" 37 | Set-Location $originalDir\publish\linux-x64 38 | 7z a ..\..\$linuxtemptar "*" 39 | 7z a ..\..\$linuxtargz ..\..\$linuxtemptar 40 | Remove-Item ..\..\$linuxtemptar 41 | Set-Location $originalDir -------------------------------------------------------------------------------- /src/ImageUtil/ImageConverter.cs: -------------------------------------------------------------------------------- 1 | using SixLabors.ImageSharp; 2 | 3 | namespace ImageUtil 4 | { 5 | public static class ImageConverter 6 | { 7 | public static void ConvertImageFileToPng(string filename) 8 | { 9 | var image = Image.Load(filename); 10 | 11 | var newFileName = Path.Combine(Path.GetDirectoryName(filename), $"{Path.GetFileNameWithoutExtension(filename)}.png"); 12 | 13 | image.Save(newFileName); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/ImageUtil/ImageUtil.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net6.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | PreserveNewest 41 | Assets\python\%(RecursiveDir)%(FileName)%(Extension) 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /src/ImageUtil/Interrogation/CogVLM2Interrogator.cs: -------------------------------------------------------------------------------- 1 |  2 | using System.Runtime.InteropServices; 3 | 4 | namespace ImageUtil.Interrogation 5 | { 6 | public class CogVLM2Interrogator : INaturalLanguageInterrogator 7 | { 8 | private readonly string model; 9 | private PythonImageEngine pythonImageEngine; 10 | private bool initialized = false; 11 | private bool disposed = false; 12 | 13 | public async Task Initialize(Action updateCallBack, Action consoleCallBack) 14 | { 15 | if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) 16 | { 17 | throw new Exception("Attempted to initialize CogVLM2 interrogator on non linux platform. CogVLM2 is only supported on Linux."); 18 | } 19 | 20 | if (!initialized) 21 | { 22 | var relativeWorkingDirectory = Path.Join("taggers", "cogvlm2"); 23 | var absoluteWorkingDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, relativeWorkingDirectory); 24 | var assetDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Path.Join("Assets", "python", "cogvlm2")); 25 | 26 | Directory.CreateDirectory(absoluteWorkingDirectory); 27 | 28 | File.Copy(Path.Combine(assetDirectory, "interrogate.py"), Path.Join(absoluteWorkingDirectory, "interrogate.py"), true); 29 | File.Copy(Path.Combine(assetDirectory, "requirements.txt"), Path.Join(absoluteWorkingDirectory, "requirements.txt"), true); 30 | 31 | await Utility.CreateVenv(absoluteWorkingDirectory, updateCallBack, consoleCallBack, "requirements.txt"); 32 | 33 | pythonImageEngine = new PythonImageEngine("interrogate.py", "", relativeWorkingDirectory, true); 34 | } 35 | initialized = true; 36 | } 37 | 38 | public async Task CaptionImage(string prompt, byte[] imageData, Action consoleCallBack) 39 | { 40 | if (!initialized) 41 | throw new InvalidOperationException("Tried to access an uninitialized CogVLM2Interrogator."); 42 | 43 | if (disposed) 44 | throw new ObjectDisposedException("Tried to access a disposed CogVLM2Interrogator."); 45 | await pythonImageEngine.SendString(prompt); 46 | 47 | await pythonImageEngine.SendImage(imageData, consoleCallBack); 48 | return await pythonImageEngine.WaitForGenerationResultString(consoleCallBack); 49 | } 50 | 51 | public void Dispose() 52 | { 53 | disposed = true; 54 | pythonImageEngine.Dispose(); 55 | } 56 | } 57 | } 58 | 59 | -------------------------------------------------------------------------------- /src/ImageUtil/Interrogation/ConfiguredInterrogationContext.cs: -------------------------------------------------------------------------------- 1 | namespace ImageUtil.Interrogation 2 | { 3 | public class ConfiguredInterrogationContext : IDisposable 4 | { 5 | bool isDisposed = false; 6 | private readonly IDisposable wrapped; 7 | 8 | public Func, Action, Task> InitializeOperation { get; } 9 | public Func, Action, Task> InterrogateOperation { get; } 10 | 11 | public ConfiguredInterrogationContext(IDisposable wrapped, 12 | Func, Action, Task> initializeOperation, 13 | Func, Action, Task> interrogateOperation) 14 | { 15 | this.wrapped = wrapped; 16 | InitializeOperation = initializeOperation; 17 | InterrogateOperation = interrogateOperation; 18 | } 19 | 20 | public void Dispose() 21 | { 22 | if(isDisposed) 23 | { 24 | throw new ObjectDisposedException("Attempted to dispose of an already disposed interrogation context."); 25 | } 26 | isDisposed = true; 27 | wrapped.Dispose(); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/ImageUtil/Interrogation/INaturalLanguageInterrogator.cs: -------------------------------------------------------------------------------- 1 | namespace ImageUtil 2 | { 3 | public interface INaturalLanguageInterrogator : IDisposable 4 | { 5 | Task Initialize(Action updateCallBack, Action consoleCallBack); 6 | Task CaptionImage(TArgs args, byte[] imageData, Action consoleCallBack); 7 | } 8 | } -------------------------------------------------------------------------------- /src/ImageUtil/Interrogation/ITagInterrogator.cs: -------------------------------------------------------------------------------- 1 | namespace ImageUtil 2 | { 3 | public interface ITagInterrogator : IDisposable 4 | { 5 | Task Initialize(Action updateCallBack, Action consoleCallBack); 6 | Task> TagImage(TArgs args, byte[] imageData, Action consoleCallBack); 7 | } 8 | } -------------------------------------------------------------------------------- /src/ImageUtil/Interrogation/JoyCaptionPreAlpha.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.InteropServices; 2 | 3 | namespace ImageUtil 4 | { 5 | public class JoyCaptionPreAlpha : INaturalLanguageInterrogator 6 | { 7 | private readonly string model; 8 | private PythonImageEngine pythonImageEngine; 9 | private bool initialized = false; 10 | private bool disposed = false; 11 | 12 | public async Task Initialize(Action updateCallBack, Action consoleCallBack) 13 | { 14 | if (!initialized) 15 | { 16 | string repoUrl = "https://huggingface.co/spaces/fancyfeast/joy-caption-pre-alpha"; 17 | var absoluteWorkingDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Path.Join("taggers", "joycaption")); 18 | 19 | await Utility.CloneRepo(repoUrl, absoluteWorkingDirectory, updateCallBack); 20 | 21 | File.Copy(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Assets", "python", "joycaption", "interrogate.py"), Path.Join(absoluteWorkingDirectory, "interrogate.py"), true); 22 | 23 | var additionalPackages = new List { "Pillow", "spaces", "protobuf", "bitsandbytes" }; 24 | 25 | if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) 26 | { 27 | additionalPackages.Add("torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu124"); 28 | } 29 | 30 | await Utility.CreateVenv(absoluteWorkingDirectory, updateCallBack, consoleCallBack, "requirements.txt", additionalPackages); 31 | 32 | pythonImageEngine = new PythonImageEngine("interrogate.py", "", Path.Join("taggers", "joycaption"), true); 33 | } 34 | initialized = true; 35 | } 36 | 37 | public async Task CaptionImage(string prompt, byte[] imageData, Action consoleCallBack) 38 | { 39 | if (!initialized) 40 | throw new InvalidOperationException("Tried to access an uninitialized Joy Captioner."); 41 | 42 | if (disposed) 43 | throw new ObjectDisposedException("Tried to access a disposed Joy Captioner."); 44 | 45 | await pythonImageEngine.SendString(prompt); 46 | 47 | await pythonImageEngine.SendImage(imageData, consoleCallBack); 48 | return await pythonImageEngine.WaitForGenerationResultString(consoleCallBack); 49 | } 50 | 51 | public void Dispose() 52 | { 53 | disposed = true; 54 | pythonImageEngine.Dispose(); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/ImageUtil/Interrogation/SWTagger.cs: -------------------------------------------------------------------------------- 1 | using Newtonsoft.Json; 2 | using System.Text.RegularExpressions; 3 | 4 | namespace ImageUtil 5 | { 6 | public class SWTagger : ITagInterrogator 7 | { 8 | private readonly string model; 9 | private PythonImageEngine pythonImageEngine; 10 | private bool initialized = false; 11 | private bool disposed = false; 12 | 13 | public SWTagger(string model) 14 | { 15 | this.model = model; 16 | } 17 | 18 | public void Dispose() 19 | { 20 | disposed = true; 21 | pythonImageEngine?.Dispose(); 22 | } 23 | 24 | public async Task Initialize(Action updateCallBack, Action consoleCallBack) 25 | { 26 | if (!initialized) 27 | { 28 | string repoUrl = "https://huggingface.co/spaces/SmilingWolf/wd-tagger"; 29 | var absoluteWorkingDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Path.Join("taggers", "sw")); 30 | 31 | await Utility.CloneRepo(repoUrl, absoluteWorkingDirectory, updateCallBack); 32 | 33 | File.Copy(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Assets", "python", "sw", "interrogate.py"), Path.Join(absoluteWorkingDirectory, "interrogate.py"), true); 34 | 35 | var additionalPackages = new List { "gradio" }; 36 | await Utility.CreateVenv(absoluteWorkingDirectory, updateCallBack, consoleCallBack, "requirements.txt", additionalPackages); 37 | 38 | pythonImageEngine = new PythonImageEngine("interrogate.py", $"{model} 0.5", Path.Join("taggers", "sw"), true); 39 | } 40 | initialized = true; 41 | } 42 | 43 | public async Task> TagImage(float threshold, byte[] imageData, Action consoleCallBack) 44 | { 45 | if (!initialized) 46 | throw new InvalidOperationException("Tried to access an unitialized SW Tagger."); 47 | 48 | if (disposed) 49 | throw new ObjectDisposedException("Tried to access a disposed SW Tagger."); 50 | 51 | await pythonImageEngine.SendImage(imageData, consoleCallBack); 52 | var output = await pythonImageEngine.WaitForGenerationResultString(consoleCallBack); 53 | // We use Trim to remove any leading white spaces 54 | var match = Regex.Match(output, @"^\('([^']*)',"); 55 | 56 | if (match.Success) 57 | { 58 | string listPart = match.Groups[1].Value; 59 | return new List(listPart.Split(new[] { ", " }, StringSplitOptions.None)); 60 | } 61 | else 62 | { 63 | return new List(); 64 | } 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/ImageUtil/PythonWrapper.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.Runtime.InteropServices; 3 | using System.Text; 4 | 5 | namespace ImageUtil 6 | { 7 | public static class PythonWrapper 8 | { 9 | public static async Task RunPythonScript(string scriptPath, string arguments, byte[] data, string workingdirectory, bool isvenv = false) 10 | { 11 | var sb = new StringBuilder(); 12 | 13 | using (Process p = new Process()) 14 | { 15 | ProcessStartInfo info = new ProcessStartInfo(); 16 | 17 | var pythonExe = "python"; 18 | var absoluteWorkingDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, workingdirectory); 19 | if (isvenv) 20 | { 21 | pythonExe = Path.Join(absoluteWorkingDirectory, (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? 22 | Path.Join("venv", "Scripts", "python.exe") : 23 | Path.Join("venv", "bin", "python"))); 24 | } 25 | 26 | info.FileName = pythonExe; 27 | info.Arguments = $"{scriptPath} {arguments}"; 28 | info.RedirectStandardInput = true; 29 | info.UseShellExecute = false; 30 | info.CreateNoWindow = true; 31 | info.WorkingDirectory = absoluteWorkingDirectory; 32 | info.RedirectStandardOutput = true; 33 | info.RedirectStandardError = true; 34 | 35 | p.OutputDataReceived += (sender, args) => 36 | { 37 | if (args.Data != null && !string.IsNullOrWhiteSpace(args.Data)) 38 | sb.AppendLine(args.Data); 39 | }; 40 | 41 | p.ErrorDataReceived += (sender, args) => 42 | { 43 | if (args.Data != null && !string.IsNullOrWhiteSpace(args.Data)) 44 | sb.AppendLine(args.Data); 45 | }; 46 | 47 | p.StartInfo = info; 48 | p.Start(); 49 | 50 | p.BeginOutputReadLine(); 51 | p.BeginErrorReadLine(); 52 | 53 | try 54 | { 55 | if (data != null) 56 | { 57 | using (Stream stdin = p.StandardInput.BaseStream) 58 | { 59 | stdin.Write(data, 0, data.Length); 60 | stdin.Flush(); 61 | stdin.Close(); 62 | } 63 | } 64 | } 65 | catch (Exception) 66 | { 67 | throw new Exception($"Python script failed. Full output is {sb.ToString()}"); 68 | } 69 | 70 | await p.WaitForExitAsync(); 71 | 72 | if (p.ExitCode != 0) 73 | { 74 | throw new Exception($"Python script failed with exit code {p.ExitCode}. Full output is {sb.ToString()}"); 75 | } 76 | } 77 | 78 | return sb.ToString(); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/ImageUtil/python/cogvlm2/interrogate.py: -------------------------------------------------------------------------------- 1 | """ 2 | Original source taken from https://github.com/THUDM/CogVLM2/blob/main/basic_demo/cli_demo.py modified to support StableDiffusionTagManager and always load 4bit 3 | """ 4 | 5 | import torch 6 | from PIL import Image 7 | from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig 8 | import sys 9 | import base64 10 | from io import BytesIO 11 | 12 | MODEL_PATH = "THUDM/cogvlm2-llama3-chat-19B" 13 | DEVICE = 'cuda' if torch.cuda.is_available() else 'cpu' 14 | TORCH_TYPE = torch.bfloat16 if torch.cuda.is_available() and torch.cuda.get_device_capability()[ 15 | 0] >= 8 else torch.float16 16 | 17 | tokenizer = AutoTokenizer.from_pretrained( 18 | MODEL_PATH, 19 | trust_remote_code=True 20 | ) 21 | 22 | model = AutoModelForCausalLM.from_pretrained( 23 | MODEL_PATH, 24 | torch_dtype=TORCH_TYPE, 25 | trust_remote_code=True, 26 | quantization_config=BitsAndBytesConfig(load_in_4bit=True), 27 | low_cpu_mem_usage=True 28 | ).eval() 29 | 30 | def main(): 31 | while True: 32 | promptdata = sys.stdin.readline().strip() 33 | 34 | imagedata = sys.stdin.readline().strip() 35 | binary_data = base64.b64decode(imagedata) 36 | image_bytes = BytesIO(binary_data) 37 | 38 | with Image.open(image_bytes).convert("RGB") as image: 39 | history = [] 40 | 41 | input_by_model = model.build_conversation_input_ids( 42 | tokenizer, 43 | query=promptdata, 44 | history=history, 45 | images=[image], 46 | template_version='chat' 47 | ) 48 | 49 | inputs = { 50 | 'input_ids': input_by_model['input_ids'].unsqueeze(0).to(DEVICE), 51 | 'token_type_ids': input_by_model['token_type_ids'].unsqueeze(0).to(DEVICE), 52 | 'attention_mask': input_by_model['attention_mask'].unsqueeze(0).to(DEVICE), 53 | 'images': [[input_by_model['images'][0].to(DEVICE).to(TORCH_TYPE)]] if image is not None else None, 54 | } 55 | 56 | gen_kwargs = { 57 | "max_new_tokens": 2048, 58 | "pad_token_id": 128002, 59 | "top_k": 1, 60 | } 61 | 62 | with torch.no_grad(): 63 | outputs = model.generate(**inputs, **gen_kwargs) 64 | outputs = outputs[:, inputs['input_ids'].shape[1]:] 65 | response = tokenizer.decode(outputs[0], skip_special_tokens=True) 66 | print("GENERATION START") 67 | print(response) 68 | print("GENERATION END") 69 | sys.stdout.flush() 70 | 71 | if __name__ == "__main__": 72 | main() -------------------------------------------------------------------------------- /src/ImageUtil/python/cogvlm2/requirements.txt: -------------------------------------------------------------------------------- 1 | xformers 2 | torch>=2.0.0 3 | torchvision 4 | transformers>=4.40 5 | huggingface-hub>=0.23.0 6 | pillow 7 | pydantic>=2.7.1 8 | timm>=0.9.16 9 | openai>=1.30.1 10 | loguru>=0.7.2 11 | pydantic>=2.7.1 12 | einops 13 | sse-starlette>=2.1.0 14 | bitsandbytes>=0.43.1 # for int4 quantization 15 | triton 16 | accelerate -------------------------------------------------------------------------------- /src/ImageUtil/python/sw/interrogate.py: -------------------------------------------------------------------------------- 1 | from PIL import Image 2 | import sys 3 | from app import Predictor 4 | from io import BytesIO 5 | import time 6 | import base64 7 | 8 | def main(): 9 | predictor = Predictor() 10 | 11 | while True: 12 | 13 | imagedata = sys.stdin.readline().strip() 14 | binary_data = base64.b64decode(imagedata) 15 | image_bytes = BytesIO(binary_data) 16 | 17 | with Image.open(image_bytes).convert("RGBA") as img: 18 | tagresults = predictor.predict(img, sys.argv[1], float(sys.argv[2]), 0, float(sys.argv[2]), 0) 19 | print("GENERATION START") 20 | print(tagresults) 21 | print("GENERATION END") 22 | sys.stdout.flush() 23 | 24 | if __name__ == "__main__": 25 | main() -------------------------------------------------------------------------------- /src/ImageUtil/python/utilities/requirements.txt: -------------------------------------------------------------------------------- 1 | simple-lama-inpainting 2 | ultralytics 3 | huggingface_hub 4 | torch 5 | torchvision 6 | requests 7 | dill 8 | numpy 9 | onnxruntime 10 | rembg -------------------------------------------------------------------------------- /src/SdWebUiApi/Client/ApiException.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * FastAPI 3 | * 4 | * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 5 | * 6 | * The version of the OpenAPI document: 0.1.0 7 | * Generated by: https://github.com/openapitools/openapi-generator.git 8 | */ 9 | 10 | 11 | using System; 12 | 13 | namespace SdWebUiApi.Client 14 | { 15 | /// 16 | /// API Exception 17 | /// 18 | public class ApiException : Exception 19 | { 20 | /// 21 | /// Gets or sets the error code (HTTP status code) 22 | /// 23 | /// The error code (HTTP status code). 24 | public int ErrorCode { get; set; } 25 | 26 | /// 27 | /// Gets or sets the error content (body json object) 28 | /// 29 | /// The error content (Http response body). 30 | public object ErrorContent { get; private set; } 31 | 32 | /// 33 | /// Gets or sets the HTTP headers 34 | /// 35 | /// HTTP headers 36 | public Multimap Headers { get; private set; } 37 | 38 | /// 39 | /// Initializes a new instance of the class. 40 | /// 41 | public ApiException() { } 42 | 43 | /// 44 | /// Initializes a new instance of the class. 45 | /// 46 | /// HTTP status code. 47 | /// Error message. 48 | public ApiException(int errorCode, string message) : base(message) 49 | { 50 | this.ErrorCode = errorCode; 51 | } 52 | 53 | /// 54 | /// Initializes a new instance of the class. 55 | /// 56 | /// HTTP status code. 57 | /// Error message. 58 | /// Error content. 59 | /// HTTP Headers. 60 | public ApiException(int errorCode, string message, object errorContent = null, Multimap headers = null) : base(message) 61 | { 62 | this.ErrorCode = errorCode; 63 | this.ErrorContent = errorContent; 64 | this.Headers = headers; 65 | } 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/SdWebUiApi/Client/ExceptionFactory.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * FastAPI 3 | * 4 | * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 5 | * 6 | * The version of the OpenAPI document: 0.1.0 7 | * Generated by: https://github.com/openapitools/openapi-generator.git 8 | */ 9 | 10 | 11 | using System; 12 | 13 | namespace SdWebUiApi.Client 14 | { 15 | /// 16 | /// A delegate to ExceptionFactory method 17 | /// 18 | /// Method name 19 | /// Response 20 | /// Exceptions 21 | public delegate Exception ExceptionFactory(string methodName, IApiResponse response); 22 | } 23 | -------------------------------------------------------------------------------- /src/SdWebUiApi/Client/GlobalConfiguration.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * FastAPI 3 | * 4 | * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 5 | * 6 | * The version of the OpenAPI document: 0.1.0 7 | * Generated by: https://github.com/openapitools/openapi-generator.git 8 | */ 9 | 10 | 11 | using System.Collections.Generic; 12 | 13 | namespace SdWebUiApi.Client 14 | { 15 | /// 16 | /// provides a compile-time extension point for globally configuring 17 | /// API Clients. 18 | /// 19 | /// 20 | /// A customized implementation via partial class may reside in another file and may 21 | /// be excluded from automatic generation via a .openapi-generator-ignore file. 22 | /// 23 | public partial class GlobalConfiguration : Configuration 24 | { 25 | #region Private Members 26 | 27 | private static readonly object GlobalConfigSync = new { }; 28 | private static IReadableConfiguration _globalConfiguration; 29 | 30 | #endregion Private Members 31 | 32 | #region Constructors 33 | 34 | /// 35 | private GlobalConfiguration() 36 | { 37 | } 38 | 39 | /// 40 | public GlobalConfiguration(IDictionary defaultHeader, IDictionary apiKey, IDictionary apiKeyPrefix, string basePath = "http://localhost:3000/api") : base(defaultHeader, apiKey, apiKeyPrefix, basePath) 41 | { 42 | } 43 | 44 | static GlobalConfiguration() 45 | { 46 | Instance = new GlobalConfiguration(); 47 | } 48 | 49 | #endregion Constructors 50 | 51 | /// 52 | /// Gets or sets the default Configuration. 53 | /// 54 | /// Configuration. 55 | public static IReadableConfiguration Instance 56 | { 57 | get { return _globalConfiguration; } 58 | set 59 | { 60 | lock (GlobalConfigSync) 61 | { 62 | _globalConfiguration = value; 63 | } 64 | } 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/SdWebUiApi/Client/HttpMethod.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * FastAPI 3 | * 4 | * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 5 | * 6 | * The version of the OpenAPI document: 0.1.0 7 | * Generated by: https://github.com/openapitools/openapi-generator.git 8 | */ 9 | 10 | 11 | namespace SdWebUiApi.Client 12 | { 13 | /// 14 | /// Http methods supported by swagger 15 | /// 16 | public enum HttpMethod 17 | { 18 | /// HTTP GET request. 19 | Get, 20 | /// HTTP POST request. 21 | Post, 22 | /// HTTP PUT request. 23 | Put, 24 | /// HTTP DELETE request. 25 | Delete, 26 | /// HTTP HEAD request. 27 | Head, 28 | /// HTTP OPTIONS request. 29 | Options, 30 | /// HTTP PATCH request. 31 | Patch 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/SdWebUiApi/Client/IApiAccessor.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * FastAPI 3 | * 4 | * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 5 | * 6 | * The version of the OpenAPI document: 0.1.0 7 | * Generated by: https://github.com/openapitools/openapi-generator.git 8 | */ 9 | 10 | 11 | using System; 12 | 13 | namespace SdWebUiApi.Client 14 | { 15 | /// 16 | /// Represents configuration aspects required to interact with the API endpoints. 17 | /// 18 | public interface IApiAccessor 19 | { 20 | /// 21 | /// Gets or sets the configuration object 22 | /// 23 | /// An instance of the Configuration 24 | IReadableConfiguration Configuration { get; set; } 25 | 26 | /// 27 | /// Gets the base path of the API client. 28 | /// 29 | /// The base path 30 | string GetBasePath(); 31 | 32 | /// 33 | /// Provides a factory method hook for the creation of exceptions. 34 | /// 35 | ExceptionFactory ExceptionFactory { get; set; } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/SdWebUiApi/Client/OpenAPIDateConverter.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * FastAPI 3 | * 4 | * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 5 | * 6 | * The version of the OpenAPI document: 0.1.0 7 | * Generated by: https://github.com/openapitools/openapi-generator.git 8 | */ 9 | 10 | using Newtonsoft.Json.Converters; 11 | 12 | namespace SdWebUiApi.Client 13 | { 14 | /// 15 | /// Formatter for 'date' openapi formats ss defined by full-date - RFC3339 16 | /// see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#data-types 17 | /// 18 | public class OpenAPIDateConverter : IsoDateTimeConverter 19 | { 20 | /// 21 | /// Initializes a new instance of the class. 22 | /// 23 | public OpenAPIDateConverter() 24 | { 25 | // full-date = date-fullyear "-" date-month "-" date-mday 26 | DateTimeFormat = "yyyy-MM-dd"; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/SdWebUiApi/Client/RequestOptions.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * FastAPI 3 | * 4 | * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 5 | * 6 | * The version of the OpenAPI document: 0.1.0 7 | * Generated by: https://github.com/openapitools/openapi-generator.git 8 | */ 9 | 10 | 11 | using System; 12 | using System.Collections.Generic; 13 | using System.IO; 14 | using System.Net; 15 | 16 | namespace SdWebUiApi.Client 17 | { 18 | /// 19 | /// A container for generalized request inputs. This type allows consumers to extend the request functionality 20 | /// by abstracting away from the default (built-in) request framework (e.g. RestSharp). 21 | /// 22 | public class RequestOptions 23 | { 24 | /// 25 | /// Parameters to be bound to path parts of the Request's URL 26 | /// 27 | public Dictionary PathParameters { get; set; } 28 | 29 | /// 30 | /// Query parameters to be applied to the request. 31 | /// Keys may have 1 or more values associated. 32 | /// 33 | public Multimap QueryParameters { get; set; } 34 | 35 | /// 36 | /// Header parameters to be applied to the request. 37 | /// Keys may have 1 or more values associated. 38 | /// 39 | public Multimap HeaderParameters { get; set; } 40 | 41 | /// 42 | /// Form parameters to be sent along with the request. 43 | /// 44 | public Dictionary FormParameters { get; set; } 45 | 46 | /// 47 | /// File parameters to be sent along with the request. 48 | /// 49 | public Multimap FileParameters { get; set; } 50 | 51 | /// 52 | /// Cookies to be sent along with the request. 53 | /// 54 | public List Cookies { get; set; } 55 | 56 | /// 57 | /// Operation associated with the request path. 58 | /// 59 | public string Operation { get; set; } 60 | 61 | /// 62 | /// Index associated with the operation. 63 | /// 64 | public int OperationIndex { get; set; } 65 | 66 | /// 67 | /// Any data associated with a request body. 68 | /// 69 | public Object Data { get; set; } 70 | 71 | /// 72 | /// Constructs a new instance of 73 | /// 74 | public RequestOptions() 75 | { 76 | PathParameters = new Dictionary(); 77 | QueryParameters = new Multimap(); 78 | HeaderParameters = new Multimap(); 79 | FormParameters = new Dictionary(); 80 | FileParameters = new Multimap(); 81 | Cookies = new List(); 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/SdWebUiApi/Client/RetryConfiguration.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * FastAPI 3 | * 4 | * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 5 | * 6 | * The version of the OpenAPI document: 0.1.0 7 | * Generated by: https://github.com/openapitools/openapi-generator.git 8 | */ 9 | 10 | 11 | using Polly; 12 | using RestSharp; 13 | 14 | namespace SdWebUiApi.Client 15 | { 16 | /// 17 | /// Configuration class to set the polly retry policies to be applied to the requests. 18 | /// 19 | public static class RetryConfiguration 20 | { 21 | /// 22 | /// Retry policy 23 | /// 24 | public static Policy RetryPolicy { get; set; } 25 | 26 | /// 27 | /// Async retry policy 28 | /// 29 | public static AsyncPolicy AsyncRetryPolicy { get; set; } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/SdWebUiApi/InterrogateMethod.cs: -------------------------------------------------------------------------------- 1 | namespace SdWebUiApi 2 | { 3 | public enum InterrogateMethod 4 | { 5 | Clip = 1, 6 | DeepDanBooru = 2, 7 | JoyCaption = 3 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/SdWebUiApi/InterrogateResult.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace StableDiffusionTagManager.Models 8 | { 9 | /// 10 | /// This was needed since the generated api returns an object when calling the interrogate function on the SD WebUI. 11 | /// 12 | public class InterrogateResult 13 | { 14 | public string caption { get; set; } = ""; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/SdWebUiApi/MaskedContent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace SdWebUiApi 8 | { 9 | public enum MaskedContent : int 10 | { 11 | Fill = 0, 12 | Original = 1, 13 | LatentNoise = 2, 14 | LatentNothing = 3 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/SdWebUiApi/Model/AbstractOpenAPISchema.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * FastAPI 3 | * 4 | * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 5 | * 6 | * The version of the OpenAPI document: 0.1.0 7 | * Generated by: https://github.com/openapitools/openapi-generator.git 8 | */ 9 | 10 | 11 | using System; 12 | using Newtonsoft.Json; 13 | using Newtonsoft.Json.Serialization; 14 | 15 | namespace SdWebUiApi.Model 16 | { 17 | /// 18 | /// Abstract base class for oneOf, anyOf schemas in the OpenAPI specification 19 | /// 20 | public abstract partial class AbstractOpenAPISchema 21 | { 22 | /// 23 | /// Custom JSON serializer 24 | /// 25 | static public readonly JsonSerializerSettings SerializerSettings = new JsonSerializerSettings 26 | { 27 | // OpenAPI generated types generally hide default constructors. 28 | ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor, 29 | MissingMemberHandling = MissingMemberHandling.Error, 30 | ContractResolver = new DefaultContractResolver 31 | { 32 | NamingStrategy = new CamelCaseNamingStrategy 33 | { 34 | OverrideSpecifiedNames = false 35 | } 36 | } 37 | }; 38 | 39 | /// 40 | /// Custom JSON serializer for objects with additional properties 41 | /// 42 | static public readonly JsonSerializerSettings AdditionalPropertiesSerializerSettings = new JsonSerializerSettings 43 | { 44 | // OpenAPI generated types generally hide default constructors. 45 | ConstructorHandling = ConstructorHandling.AllowNonPublicDefaultConstructor, 46 | MissingMemberHandling = MissingMemberHandling.Ignore, 47 | ContractResolver = new DefaultContractResolver 48 | { 49 | NamingStrategy = new CamelCaseNamingStrategy 50 | { 51 | OverrideSpecifiedNames = false 52 | } 53 | } 54 | }; 55 | 56 | /// 57 | /// Gets or Sets the actual instance 58 | /// 59 | public abstract Object ActualInstance { get; set; } 60 | 61 | /// 62 | /// Gets or Sets IsNullable to indicate whether the instance is nullable 63 | /// 64 | public bool IsNullable { get; protected set; } 65 | 66 | /// 67 | /// Gets or Sets the schema type, which can be either `oneOf` or `anyOf` 68 | /// 69 | public string SchemaType { get; protected set; } 70 | 71 | /// 72 | /// Converts the instance into JSON string. 73 | /// 74 | public abstract string ToJson(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/SdWebUiApi/Model/CreateResponse.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * FastAPI 3 | * 4 | * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 5 | * 6 | * The version of the OpenAPI document: 0.1.0 7 | * Generated by: https://github.com/openapitools/openapi-generator.git 8 | */ 9 | 10 | 11 | using System; 12 | using System.Collections; 13 | using System.Collections.Generic; 14 | using System.Collections.ObjectModel; 15 | using System.Linq; 16 | using System.IO; 17 | using System.Runtime.Serialization; 18 | using System.Text; 19 | using System.Text.RegularExpressions; 20 | using Newtonsoft.Json; 21 | using Newtonsoft.Json.Converters; 22 | using Newtonsoft.Json.Linq; 23 | using System.ComponentModel.DataAnnotations; 24 | using OpenAPIDateConverter = SdWebUiApi.Client.OpenAPIDateConverter; 25 | 26 | namespace SdWebUiApi.Model 27 | { 28 | /// 29 | /// CreateResponse 30 | /// 31 | [DataContract(Name = "CreateResponse")] 32 | public partial class CreateResponse : IValidatableObject 33 | { 34 | /// 35 | /// Initializes a new instance of the class. 36 | /// 37 | [JsonConstructorAttribute] 38 | protected CreateResponse() { } 39 | /// 40 | /// Initializes a new instance of the class. 41 | /// 42 | /// Response string from create embedding or hypernetwork task. (required). 43 | public CreateResponse(string info = default(string)) 44 | { 45 | // to ensure "info" is required (not null) 46 | if (info == null) 47 | { 48 | throw new ArgumentNullException("info is a required property for CreateResponse and cannot be null"); 49 | } 50 | this.Info = info; 51 | } 52 | 53 | /// 54 | /// Response string from create embedding or hypernetwork task. 55 | /// 56 | /// Response string from create embedding or hypernetwork task. 57 | [DataMember(Name = "info", IsRequired = true, EmitDefaultValue = true)] 58 | public string Info { get; set; } 59 | 60 | /// 61 | /// Returns the string presentation of the object 62 | /// 63 | /// String presentation of the object 64 | public override string ToString() 65 | { 66 | StringBuilder sb = new StringBuilder(); 67 | sb.Append("class CreateResponse {\n"); 68 | sb.Append(" Info: ").Append(Info).Append("\n"); 69 | sb.Append("}\n"); 70 | return sb.ToString(); 71 | } 72 | 73 | /// 74 | /// Returns the JSON string presentation of the object 75 | /// 76 | /// JSON string presentation of the object 77 | public virtual string ToJson() 78 | { 79 | return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); 80 | } 81 | 82 | /// 83 | /// To validate all properties of the instance 84 | /// 85 | /// Validation context 86 | /// Validation Result 87 | IEnumerable IValidatableObject.Validate(ValidationContext validationContext) 88 | { 89 | yield break; 90 | } 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /src/SdWebUiApi/Model/HTTPValidationError.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * FastAPI 3 | * 4 | * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 5 | * 6 | * The version of the OpenAPI document: 0.1.0 7 | * Generated by: https://github.com/openapitools/openapi-generator.git 8 | */ 9 | 10 | 11 | using System; 12 | using System.Collections; 13 | using System.Collections.Generic; 14 | using System.Collections.ObjectModel; 15 | using System.Linq; 16 | using System.IO; 17 | using System.Runtime.Serialization; 18 | using System.Text; 19 | using System.Text.RegularExpressions; 20 | using Newtonsoft.Json; 21 | using Newtonsoft.Json.Converters; 22 | using Newtonsoft.Json.Linq; 23 | using System.ComponentModel.DataAnnotations; 24 | using OpenAPIDateConverter = SdWebUiApi.Client.OpenAPIDateConverter; 25 | 26 | namespace SdWebUiApi.Model 27 | { 28 | /// 29 | /// HTTPValidationError 30 | /// 31 | [DataContract(Name = "HTTPValidationError")] 32 | public partial class HTTPValidationError : IValidatableObject 33 | { 34 | /// 35 | /// Initializes a new instance of the class. 36 | /// 37 | /// detail. 38 | public HTTPValidationError(List detail = default(List)) 39 | { 40 | this.Detail = detail; 41 | } 42 | 43 | /// 44 | /// Gets or Sets Detail 45 | /// 46 | [DataMember(Name = "detail", EmitDefaultValue = false)] 47 | public List Detail { get; set; } 48 | 49 | /// 50 | /// Returns the string presentation of the object 51 | /// 52 | /// String presentation of the object 53 | public override string ToString() 54 | { 55 | StringBuilder sb = new StringBuilder(); 56 | sb.Append("class HTTPValidationError {\n"); 57 | sb.Append(" Detail: ").Append(Detail).Append("\n"); 58 | sb.Append("}\n"); 59 | return sb.ToString(); 60 | } 61 | 62 | /// 63 | /// Returns the JSON string presentation of the object 64 | /// 65 | /// JSON string presentation of the object 66 | public virtual string ToJson() 67 | { 68 | return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); 69 | } 70 | 71 | /// 72 | /// To validate all properties of the instance 73 | /// 74 | /// Validation context 75 | /// Validation Result 76 | IEnumerable IValidatableObject.Validate(ValidationContext validationContext) 77 | { 78 | yield break; 79 | } 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /src/SdWebUiApi/Model/LatentUpscalerModeItem.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * FastAPI 3 | * 4 | * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 5 | * 6 | * The version of the OpenAPI document: 0.1.0 7 | * Generated by: https://github.com/openapitools/openapi-generator.git 8 | */ 9 | 10 | 11 | using System; 12 | using System.Collections; 13 | using System.Collections.Generic; 14 | using System.Collections.ObjectModel; 15 | using System.Linq; 16 | using System.IO; 17 | using System.Runtime.Serialization; 18 | using System.Text; 19 | using System.Text.RegularExpressions; 20 | using Newtonsoft.Json; 21 | using Newtonsoft.Json.Converters; 22 | using Newtonsoft.Json.Linq; 23 | using System.ComponentModel.DataAnnotations; 24 | using OpenAPIDateConverter = SdWebUiApi.Client.OpenAPIDateConverter; 25 | 26 | namespace SdWebUiApi.Model 27 | { 28 | /// 29 | /// LatentUpscalerModeItem 30 | /// 31 | [DataContract(Name = "LatentUpscalerModeItem")] 32 | public partial class LatentUpscalerModeItem : IValidatableObject 33 | { 34 | /// 35 | /// Initializes a new instance of the class. 36 | /// 37 | [JsonConstructorAttribute] 38 | protected LatentUpscalerModeItem() { } 39 | /// 40 | /// Initializes a new instance of the class. 41 | /// 42 | /// name (required). 43 | public LatentUpscalerModeItem(string name = default(string)) 44 | { 45 | // to ensure "name" is required (not null) 46 | if (name == null) 47 | { 48 | throw new ArgumentNullException("name is a required property for LatentUpscalerModeItem and cannot be null"); 49 | } 50 | this.Name = name; 51 | } 52 | 53 | /// 54 | /// Gets or Sets Name 55 | /// 56 | [DataMember(Name = "name", IsRequired = true, EmitDefaultValue = true)] 57 | public string Name { get; set; } 58 | 59 | /// 60 | /// Returns the string presentation of the object 61 | /// 62 | /// String presentation of the object 63 | public override string ToString() 64 | { 65 | StringBuilder sb = new StringBuilder(); 66 | sb.Append("class LatentUpscalerModeItem {\n"); 67 | sb.Append(" Name: ").Append(Name).Append("\n"); 68 | sb.Append("}\n"); 69 | return sb.ToString(); 70 | } 71 | 72 | /// 73 | /// Returns the JSON string presentation of the object 74 | /// 75 | /// JSON string presentation of the object 76 | public virtual string ToJson() 77 | { 78 | return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); 79 | } 80 | 81 | /// 82 | /// To validate all properties of the instance 83 | /// 84 | /// Validation context 85 | /// Validation Result 86 | IEnumerable IValidatableObject.Validate(ValidationContext validationContext) 87 | { 88 | yield break; 89 | } 90 | } 91 | 92 | } 93 | -------------------------------------------------------------------------------- /src/SdWebUiApi/Model/PNGInfoRequest.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * FastAPI 3 | * 4 | * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 5 | * 6 | * The version of the OpenAPI document: 0.1.0 7 | * Generated by: https://github.com/openapitools/openapi-generator.git 8 | */ 9 | 10 | 11 | using System; 12 | using System.Collections; 13 | using System.Collections.Generic; 14 | using System.Collections.ObjectModel; 15 | using System.Linq; 16 | using System.IO; 17 | using System.Runtime.Serialization; 18 | using System.Text; 19 | using System.Text.RegularExpressions; 20 | using Newtonsoft.Json; 21 | using Newtonsoft.Json.Converters; 22 | using Newtonsoft.Json.Linq; 23 | using System.ComponentModel.DataAnnotations; 24 | using OpenAPIDateConverter = SdWebUiApi.Client.OpenAPIDateConverter; 25 | 26 | namespace SdWebUiApi.Model 27 | { 28 | /// 29 | /// PNGInfoRequest 30 | /// 31 | [DataContract(Name = "PNGInfoRequest")] 32 | public partial class PNGInfoRequest : IValidatableObject 33 | { 34 | /// 35 | /// Initializes a new instance of the class. 36 | /// 37 | [JsonConstructorAttribute] 38 | protected PNGInfoRequest() { } 39 | /// 40 | /// Initializes a new instance of the class. 41 | /// 42 | /// The base64 encoded PNG image (required). 43 | public PNGInfoRequest(string image = default(string)) 44 | { 45 | // to ensure "image" is required (not null) 46 | if (image == null) 47 | { 48 | throw new ArgumentNullException("image is a required property for PNGInfoRequest and cannot be null"); 49 | } 50 | this.Image = image; 51 | } 52 | 53 | /// 54 | /// The base64 encoded PNG image 55 | /// 56 | /// The base64 encoded PNG image 57 | [DataMember(Name = "image", IsRequired = true, EmitDefaultValue = true)] 58 | public string Image { get; set; } 59 | 60 | /// 61 | /// Returns the string presentation of the object 62 | /// 63 | /// String presentation of the object 64 | public override string ToString() 65 | { 66 | StringBuilder sb = new StringBuilder(); 67 | sb.Append("class PNGInfoRequest {\n"); 68 | sb.Append(" Image: ").Append(Image).Append("\n"); 69 | sb.Append("}\n"); 70 | return sb.ToString(); 71 | } 72 | 73 | /// 74 | /// Returns the JSON string presentation of the object 75 | /// 76 | /// JSON string presentation of the object 77 | public virtual string ToJson() 78 | { 79 | return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); 80 | } 81 | 82 | /// 83 | /// To validate all properties of the instance 84 | /// 85 | /// Validation context 86 | /// Validation Result 87 | IEnumerable IValidatableObject.Validate(ValidationContext validationContext) 88 | { 89 | yield break; 90 | } 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /src/SdWebUiApi/Model/PreprocessResponse.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * FastAPI 3 | * 4 | * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 5 | * 6 | * The version of the OpenAPI document: 0.1.0 7 | * Generated by: https://github.com/openapitools/openapi-generator.git 8 | */ 9 | 10 | 11 | using System; 12 | using System.Collections; 13 | using System.Collections.Generic; 14 | using System.Collections.ObjectModel; 15 | using System.Linq; 16 | using System.IO; 17 | using System.Runtime.Serialization; 18 | using System.Text; 19 | using System.Text.RegularExpressions; 20 | using Newtonsoft.Json; 21 | using Newtonsoft.Json.Converters; 22 | using Newtonsoft.Json.Linq; 23 | using System.ComponentModel.DataAnnotations; 24 | using OpenAPIDateConverter = SdWebUiApi.Client.OpenAPIDateConverter; 25 | 26 | namespace SdWebUiApi.Model 27 | { 28 | /// 29 | /// PreprocessResponse 30 | /// 31 | [DataContract(Name = "PreprocessResponse")] 32 | public partial class PreprocessResponse : IValidatableObject 33 | { 34 | /// 35 | /// Initializes a new instance of the class. 36 | /// 37 | [JsonConstructorAttribute] 38 | protected PreprocessResponse() { } 39 | /// 40 | /// Initializes a new instance of the class. 41 | /// 42 | /// Response string from preprocessing task. (required). 43 | public PreprocessResponse(string info = default(string)) 44 | { 45 | // to ensure "info" is required (not null) 46 | if (info == null) 47 | { 48 | throw new ArgumentNullException("info is a required property for PreprocessResponse and cannot be null"); 49 | } 50 | this.Info = info; 51 | } 52 | 53 | /// 54 | /// Response string from preprocessing task. 55 | /// 56 | /// Response string from preprocessing task. 57 | [DataMember(Name = "info", IsRequired = true, EmitDefaultValue = true)] 58 | public string Info { get; set; } 59 | 60 | /// 61 | /// Returns the string presentation of the object 62 | /// 63 | /// String presentation of the object 64 | public override string ToString() 65 | { 66 | StringBuilder sb = new StringBuilder(); 67 | sb.Append("class PreprocessResponse {\n"); 68 | sb.Append(" Info: ").Append(Info).Append("\n"); 69 | sb.Append("}\n"); 70 | return sb.ToString(); 71 | } 72 | 73 | /// 74 | /// Returns the JSON string presentation of the object 75 | /// 76 | /// JSON string presentation of the object 77 | public virtual string ToJson() 78 | { 79 | return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); 80 | } 81 | 82 | /// 83 | /// To validate all properties of the instance 84 | /// 85 | /// Validation context 86 | /// Validation Result 87 | IEnumerable IValidatableObject.Validate(ValidationContext validationContext) 88 | { 89 | yield break; 90 | } 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /src/SdWebUiApi/Model/ScriptsList.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * FastAPI 3 | * 4 | * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 5 | * 6 | * The version of the OpenAPI document: 0.1.0 7 | * Generated by: https://github.com/openapitools/openapi-generator.git 8 | */ 9 | 10 | 11 | using System; 12 | using System.Collections; 13 | using System.Collections.Generic; 14 | using System.Collections.ObjectModel; 15 | using System.Linq; 16 | using System.IO; 17 | using System.Runtime.Serialization; 18 | using System.Text; 19 | using System.Text.RegularExpressions; 20 | using Newtonsoft.Json; 21 | using Newtonsoft.Json.Converters; 22 | using Newtonsoft.Json.Linq; 23 | using System.ComponentModel.DataAnnotations; 24 | using OpenAPIDateConverter = SdWebUiApi.Client.OpenAPIDateConverter; 25 | 26 | namespace SdWebUiApi.Model 27 | { 28 | /// 29 | /// ScriptsList 30 | /// 31 | [DataContract(Name = "ScriptsList")] 32 | public partial class ScriptsList : IValidatableObject 33 | { 34 | /// 35 | /// Initializes a new instance of the class. 36 | /// 37 | /// Titles of scripts (txt2img). 38 | /// Titles of scripts (img2img). 39 | public ScriptsList(List txt2img = default(List), List img2img = default(List)) 40 | { 41 | this.Txt2img = txt2img; 42 | this.Img2img = img2img; 43 | } 44 | 45 | /// 46 | /// Titles of scripts (txt2img) 47 | /// 48 | /// Titles of scripts (txt2img) 49 | [DataMember(Name = "txt2img", EmitDefaultValue = false)] 50 | public List Txt2img { get; set; } 51 | 52 | /// 53 | /// Titles of scripts (img2img) 54 | /// 55 | /// Titles of scripts (img2img) 56 | [DataMember(Name = "img2img", EmitDefaultValue = false)] 57 | public List Img2img { get; set; } 58 | 59 | /// 60 | /// Returns the string presentation of the object 61 | /// 62 | /// String presentation of the object 63 | public override string ToString() 64 | { 65 | StringBuilder sb = new StringBuilder(); 66 | sb.Append("class ScriptsList {\n"); 67 | sb.Append(" Txt2img: ").Append(Txt2img).Append("\n"); 68 | sb.Append(" Img2img: ").Append(Img2img).Append("\n"); 69 | sb.Append("}\n"); 70 | return sb.ToString(); 71 | } 72 | 73 | /// 74 | /// Returns the JSON string presentation of the object 75 | /// 76 | /// JSON string presentation of the object 77 | public virtual string ToJson() 78 | { 79 | return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); 80 | } 81 | 82 | /// 83 | /// To validate all properties of the instance 84 | /// 85 | /// Validation context 86 | /// Validation Result 87 | IEnumerable IValidatableObject.Validate(ValidationContext validationContext) 88 | { 89 | yield break; 90 | } 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /src/SdWebUiApi/Model/TrainResponse.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * FastAPI 3 | * 4 | * No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) 5 | * 6 | * The version of the OpenAPI document: 0.1.0 7 | * Generated by: https://github.com/openapitools/openapi-generator.git 8 | */ 9 | 10 | 11 | using System; 12 | using System.Collections; 13 | using System.Collections.Generic; 14 | using System.Collections.ObjectModel; 15 | using System.Linq; 16 | using System.IO; 17 | using System.Runtime.Serialization; 18 | using System.Text; 19 | using System.Text.RegularExpressions; 20 | using Newtonsoft.Json; 21 | using Newtonsoft.Json.Converters; 22 | using Newtonsoft.Json.Linq; 23 | using System.ComponentModel.DataAnnotations; 24 | using OpenAPIDateConverter = SdWebUiApi.Client.OpenAPIDateConverter; 25 | 26 | namespace SdWebUiApi.Model 27 | { 28 | /// 29 | /// TrainResponse 30 | /// 31 | [DataContract(Name = "TrainResponse")] 32 | public partial class TrainResponse : IValidatableObject 33 | { 34 | /// 35 | /// Initializes a new instance of the class. 36 | /// 37 | [JsonConstructorAttribute] 38 | protected TrainResponse() { } 39 | /// 40 | /// Initializes a new instance of the class. 41 | /// 42 | /// Response string from train embedding or hypernetwork task. (required). 43 | public TrainResponse(string info = default(string)) 44 | { 45 | // to ensure "info" is required (not null) 46 | if (info == null) 47 | { 48 | throw new ArgumentNullException("info is a required property for TrainResponse and cannot be null"); 49 | } 50 | this.Info = info; 51 | } 52 | 53 | /// 54 | /// Response string from train embedding or hypernetwork task. 55 | /// 56 | /// Response string from train embedding or hypernetwork task. 57 | [DataMember(Name = "info", IsRequired = true, EmitDefaultValue = true)] 58 | public string Info { get; set; } 59 | 60 | /// 61 | /// Returns the string presentation of the object 62 | /// 63 | /// String presentation of the object 64 | public override string ToString() 65 | { 66 | StringBuilder sb = new StringBuilder(); 67 | sb.Append("class TrainResponse {\n"); 68 | sb.Append(" Info: ").Append(Info).Append("\n"); 69 | sb.Append("}\n"); 70 | return sb.ToString(); 71 | } 72 | 73 | /// 74 | /// Returns the JSON string presentation of the object 75 | /// 76 | /// JSON string presentation of the object 77 | public virtual string ToJson() 78 | { 79 | return Newtonsoft.Json.JsonConvert.SerializeObject(this, Newtonsoft.Json.Formatting.Indented); 80 | } 81 | 82 | /// 83 | /// To validate all properties of the instance 84 | /// 85 | /// Validation context 86 | /// Validation Result 87 | IEnumerable IValidatableObject.Validate(ValidationContext validationContext) 88 | { 89 | yield break; 90 | } 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /src/SdWebUiApi/RemBgModels.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace SdWebUiApi 8 | { 9 | public static class RembgModels 10 | { 11 | public const string U2Net = "u2net"; 12 | public const string U2NetP = "u2netp"; 13 | public const string U2NetHumanSeg = "u2net_human_seg"; 14 | public const string U2NetClothSeg = "u2net_cloth_seg"; 15 | public const string Silueta = "u2net_human_seg"; 16 | public const string IsNetGeneralUse = "isnet-general-use"; 17 | public const string IsNetAnime = "isnet-anime"; 18 | 19 | public static readonly IReadOnlyCollection Models = new List() 20 | { 21 | U2Net, 22 | U2NetP, 23 | U2NetHumanSeg, 24 | U2NetClothSeg, 25 | Silueta, 26 | IsNetGeneralUse, 27 | IsNetAnime 28 | }; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/SdWebUiApi/RemBgResult.cs: -------------------------------------------------------------------------------- 1 | namespace SdWebUiApi 2 | { 3 | public class RemBgResult 4 | { 5 | public string image { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /src/SdWebUiApi/SamplingMethod.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace SdWebUpApi 8 | { 9 | public enum SamplingMethod : int 10 | { 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/SdWebUiApi/SdWebUiApi.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | false 5 | net6.0 6 | SdWebUiApi 7 | SdWebUiApi 8 | Library 9 | OpenAPI 10 | OpenAPI 11 | OpenAPI Library 12 | A library generated from a OpenAPI doc 13 | No Copyright 14 | SdWebUiApi 15 | 1.0.0 16 | bin\$(Configuration)\$(TargetFramework)\SdWebUiApi.xml 17 | https://github.com/GIT_USER_ID/GIT_REPO_ID.git 18 | git 19 | Minor update 20 | annotations 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.5.33502.453 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TagUtil", "TagUtil\TagUtil.csproj", "{38612DB3-63C6-4EB1-8CDE-36EDC4B46E58}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "StableDiffusionTagManager", "StableDiffusionTagManager\StableDiffusionTagManager.csproj", "{B730FAF2-5836-4ECA-A080-8503CC4EEBC3}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ImageUtil", "ImageUtil\ImageUtil.csproj", "{1A082A88-4F2C-4B5A-92AE-37E8ADA187CF}" 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SdWebUiApi", "SdWebUiApi\SdWebUiApi.csproj", "{B45BC3A5-3B4A-4C2F-8811-ABC5102DB2C5}" 13 | EndProject 14 | Global 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 16 | Debug|Any CPU = Debug|Any CPU 17 | Release|Any CPU = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {38612DB3-63C6-4EB1-8CDE-36EDC4B46E58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {38612DB3-63C6-4EB1-8CDE-36EDC4B46E58}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {38612DB3-63C6-4EB1-8CDE-36EDC4B46E58}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {38612DB3-63C6-4EB1-8CDE-36EDC4B46E58}.Release|Any CPU.Build.0 = Release|Any CPU 24 | {B730FAF2-5836-4ECA-A080-8503CC4EEBC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {B730FAF2-5836-4ECA-A080-8503CC4EEBC3}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {B730FAF2-5836-4ECA-A080-8503CC4EEBC3}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {B730FAF2-5836-4ECA-A080-8503CC4EEBC3}.Release|Any CPU.Build.0 = Release|Any CPU 28 | {1A082A88-4F2C-4B5A-92AE-37E8ADA187CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 29 | {1A082A88-4F2C-4B5A-92AE-37E8ADA187CF}.Debug|Any CPU.Build.0 = Debug|Any CPU 30 | {1A082A88-4F2C-4B5A-92AE-37E8ADA187CF}.Release|Any CPU.ActiveCfg = Release|Any CPU 31 | {1A082A88-4F2C-4B5A-92AE-37E8ADA187CF}.Release|Any CPU.Build.0 = Release|Any CPU 32 | {B45BC3A5-3B4A-4C2F-8811-ABC5102DB2C5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 33 | {B45BC3A5-3B4A-4C2F-8811-ABC5102DB2C5}.Debug|Any CPU.Build.0 = Debug|Any CPU 34 | {B45BC3A5-3B4A-4C2F-8811-ABC5102DB2C5}.Release|Any CPU.ActiveCfg = Release|Any CPU 35 | {B45BC3A5-3B4A-4C2F-8811-ABC5102DB2C5}.Release|Any CPU.Build.0 = Release|Any CPU 36 | EndGlobalSection 37 | GlobalSection(SolutionProperties) = preSolution 38 | HideSolutionNode = FALSE 39 | EndGlobalSection 40 | GlobalSection(ExtensibilityGlobals) = postSolution 41 | SolutionGuid = {4213D52E-9374-43F4-8A04-10D18443F889} 42 | EndGlobalSection 43 | EndGlobal 44 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/App.axaml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Assets/logo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PMahern/StableDiffusionTagManager/687d4d433c96565bd5c7ea6089ddb4141da9197c/src/StableDiffusionTagManager/Assets/logo.ico -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Attributes/ServiceAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace StableDiffusionTagManager.Attributes 4 | { 5 | [AttributeUsage(AttributeTargets.Class)] 6 | public class ServiceAttribute : Attribute 7 | { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Attributes/SupportedPlatformsAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace StableDiffusionTagManager.Attributes 4 | { 5 | public class SupportedPlatformsAttribute : Attribute 6 | { 7 | public SupportedPlatformsAttribute(params string[] platforms) 8 | { 9 | Platforms = platforms; 10 | } 11 | 12 | public string[] Platforms { get; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Behaviors/CloseWindowOnEventBehavior.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls; 3 | using Avalonia.Xaml.Interactivity; 4 | using System; 5 | using System.Reflection; 6 | 7 | namespace StableDiffusionTagManager.Behaviors 8 | { 9 | public class CloseWindowOnEventBehavior : Behavior 10 | { 11 | public static readonly StyledProperty EventNameProperty = 12 | AvaloniaProperty.Register(nameof(EventName)); 13 | 14 | public string EventName 15 | { 16 | get => GetValue(EventNameProperty); 17 | set => SetValue(EventNameProperty, value); 18 | } 19 | 20 | private EventInfo? _eventInfo; 21 | private Delegate? _eventHandler; 22 | 23 | protected override void OnAttached() 24 | { 25 | base.OnAttached(); 26 | if (AssociatedObject != null) 27 | { 28 | AssociatedObject.DataContextChanged += OnDataContextChanged; 29 | AttachHandler(AssociatedObject.DataContext); 30 | } 31 | } 32 | 33 | protected override void OnDetaching() 34 | { 35 | if (AssociatedObject != null) 36 | { 37 | AssociatedObject.DataContextChanged -= OnDataContextChanged; 38 | DetachHandler(); 39 | } 40 | base.OnDetaching(); 41 | } 42 | 43 | private void OnDataContextChanged(object? sender, EventArgs e) 44 | { 45 | DetachHandler(); 46 | AttachHandler(AssociatedObject?.DataContext); 47 | } 48 | 49 | private void AttachHandler(object? dataContext) 50 | { 51 | if (dataContext != null && !string.IsNullOrEmpty(EventName)) 52 | { 53 | _eventInfo = dataContext.GetType().GetEvent(EventName); 54 | if (_eventInfo != null) 55 | { 56 | _eventHandler = Delegate.CreateDelegate(_eventInfo.EventHandlerType!, this, nameof(OnEventRaised)); 57 | _eventInfo.AddEventHandler(dataContext, _eventHandler); 58 | } 59 | } 60 | } 61 | 62 | private void DetachHandler() 63 | { 64 | if (_eventInfo != null && _eventHandler != null) 65 | { 66 | _eventInfo.RemoveEventHandler(AssociatedObject?.DataContext, _eventHandler); 67 | _eventInfo = null; 68 | _eventHandler = null; 69 | } 70 | } 71 | 72 | private void OnEventRaised(object? sender, EventArgs e) 73 | { 74 | AssociatedObject?.Close(); 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Collections/OrderedSetObservableCollection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Collections.ObjectModel; 4 | 5 | namespace StableDiffusionTagManager.Collections 6 | { 7 | public class OrderedSetObservableCollection : ObservableCollection 8 | { 9 | private readonly SortedSet set; 10 | 11 | public OrderedSetObservableCollection(Comparison comparison) : base() 12 | { 13 | set = new SortedSet(Comparer.Create(comparison)); 14 | } 15 | 16 | public new void Add(T item) 17 | { 18 | if (set.Add(item)) 19 | { 20 | base.Insert(FindInsertionIndex(item), item); 21 | } 22 | } 23 | 24 | public new bool Remove(T item) 25 | { 26 | if (set.Remove(item)) 27 | { 28 | base.Remove(item); 29 | return true; 30 | } 31 | return false; 32 | } 33 | 34 | public new void Clear() 35 | { 36 | set.Clear(); 37 | base.Clear(); 38 | } 39 | 40 | public new bool Contains(T item) 41 | { 42 | return set.Contains(item); 43 | } 44 | 45 | private int FindInsertionIndex(T item) 46 | { 47 | int index = 0; 48 | foreach (T existingItem in set) 49 | { 50 | if (set.Comparer.Compare(existingItem, item) >= 0) 51 | { 52 | break; 53 | } 54 | index++; 55 | } 56 | return index; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Controls/AdvancedImageBox.axaml: -------------------------------------------------------------------------------- 1 | 7 | 10 | 11 | 14 | 15 | 23 | 24 | 32 | 33 | 34 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Controls/IDialogWithResult.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | using System.Threading.Tasks; 3 | 4 | namespace StableDiffusionTagManager.Controls 5 | { 6 | public interface IDialogWithResult 7 | { 8 | public TResult ShowWithResult(Window parent); 9 | } 10 | 11 | public interface IDialogWithResultAsync 12 | { 13 | public Task ShowWithResult(Window parent); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Controls/TagAutoCompleteBox.axaml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Controls/TagAutoCompleteBox.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using System.Threading; 6 | using Avalonia; 7 | 8 | namespace StableDiffusionTagManager.Controls 9 | { 10 | public partial class TagAutoCompleteBox : UserControl 11 | { 12 | public TagAutoCompleteBox() 13 | { 14 | InitializeComponent(); 15 | } 16 | 17 | public async Task> SearchTags(string text, CancellationToken token) 18 | { 19 | var app = App.Current as App; 20 | if (app != null) 21 | { 22 | return await app.SearchTags(text, token); 23 | } 24 | return Enumerable.Empty(); 25 | } 26 | 27 | public static readonly StyledProperty TextProperty = 28 | AvaloniaProperty.Register(nameof(Text), "", defaultBindingMode: Avalonia.Data.BindingMode.TwoWay); 29 | 30 | public string Text 31 | { 32 | get => GetValue(TextProperty); 33 | set => SetValue(TextProperty, value); 34 | } 35 | 36 | public new void Focus() 37 | { 38 | this.AutoComplete.Focus(); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Converters/BitmapPixelSizeConverter.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Data.Converters; 2 | using Avalonia.Media.Imaging; 3 | using System; 4 | using System.Globalization; 5 | 6 | 7 | namespace StableDiffusionTagManager.Converters 8 | { 9 | public class BitmapPixelSizeConverter : IValueConverter 10 | { 11 | public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 12 | { 13 | var bitmap = value as Bitmap; 14 | var pixelSize = bitmap?.PixelSize; 15 | 16 | if (pixelSize != null) 17 | { 18 | return $"{pixelSize.Value.Width}w x {pixelSize.Value.Height}h"; 19 | } 20 | 21 | return ""; 22 | } 23 | 24 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 25 | { 26 | throw new NotImplementedException(); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Converters/ColorBrushConverter.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Data.Converters; 2 | using Avalonia.Media; 3 | using System; 4 | using System.Globalization; 5 | 6 | namespace StableDiffusionTagManager.Converters 7 | { 8 | public class ColorBrushConverter : IValueConverter 9 | { 10 | public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 11 | { 12 | var color = value as Color?; 13 | 14 | if(color != null) 15 | { 16 | return new SolidColorBrush(color.Value); 17 | } 18 | 19 | return null; 20 | } 21 | 22 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 23 | { 24 | throw new NotImplementedException(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Converters/ImageViewerModeToBoolConverter.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Data.Converters; 2 | using StableDiffusionTagManager.Controls; 3 | using System; 4 | using System.Globalization; 5 | 6 | namespace StableDiffusionTagManager.Converters 7 | { 8 | public class ImageViewerModeToBoolConverter : IValueConverter 9 | { 10 | public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 11 | { 12 | var convertedValue = value as ImageViewerMode?; 13 | var convertedParam = parameter as ImageViewerMode?; 14 | 15 | return convertedValue.HasValue && convertedParam.HasValue && convertedValue.Value == convertedParam.Value; 16 | } 17 | 18 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 19 | { 20 | throw new NotImplementedException(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Converters/InterrogateMethodToBooleanConverter.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Data.Converters; 2 | using SdWebUiApi; 3 | using SdWebUpApi; 4 | using System; 5 | using System.Globalization; 6 | 7 | namespace StableDiffusionTagManager.Converters 8 | { 9 | public class InterrogateMethodToBooleanConverter : IValueConverter 10 | { 11 | public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 12 | { 13 | var convertedValue = value as InterrogateMethod?; 14 | var convertedParam = parameter as InterrogateMethod?; 15 | 16 | return convertedValue.HasValue && convertedParam.HasValue && convertedValue.Value == convertedParam.Value; 17 | } 18 | 19 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 20 | { 21 | var convertedValue = value as bool?; 22 | var convertedParam = parameter as InterrogateMethod?; 23 | 24 | if(convertedValue.HasValue && convertedValue.Value && convertedParam.HasValue) 25 | { 26 | return convertedParam.Value; 27 | } 28 | return null; 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Converters/MaskedContentToStringConverter.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Data.Converters; 2 | using SdWebUiApi; 3 | using SdWebUpApi; 4 | using System; 5 | using System.Globalization; 6 | 7 | namespace StableDiffusionTagManager.Converters 8 | { 9 | internal class MaskedContentToStringConverter : IValueConverter 10 | { 11 | public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 12 | { 13 | var maskedContent = value as MaskedContent?; 14 | 15 | if(maskedContent != null) 16 | { 17 | switch(maskedContent) 18 | { 19 | case MaskedContent.LatentNoise: 20 | return "Latent Noise"; 21 | case MaskedContent.LatentNothing: 22 | return "Latent Nothing"; 23 | case MaskedContent.Original: 24 | return "Original"; 25 | case MaskedContent.Fill: 26 | return "Fill"; 27 | } 28 | } 29 | 30 | return null; 31 | } 32 | 33 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 34 | { 35 | throw new NotImplementedException(); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Converters/ReviewModeToBoolConverter.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Data.Converters; 2 | using StableDiffusionTagManager.Views; 3 | using System; 4 | using System.Globalization; 5 | 6 | namespace StableDiffusionTagManager.Converters 7 | { 8 | public class ReviewModeToBoolConverter : IValueConverter 9 | { 10 | public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 11 | { 12 | var reviewMode = value as ImageReviewDialogMode?; 13 | var reviewModeParam = parameter as ImageReviewDialogMode?; 14 | 15 | if (reviewMode != null && reviewModeParam != null) 16 | { 17 | return reviewMode == reviewModeParam; 18 | } 19 | 20 | return false; 21 | } 22 | 23 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 24 | { 25 | throw new NotImplementedException(); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Converters/TagCollectionBackgroundConverter.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Data.Converters; 2 | using Avalonia.Media; 3 | using StableDiffusionTagManager.ViewModels; 4 | using System; 5 | using System.Globalization; 6 | 7 | namespace StableDiffusionTagManager.Converters 8 | { 9 | public class TagCollectionBackgroundConverter : IValueConverter 10 | { 11 | public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) 12 | { 13 | var isSelected = value as bool?; 14 | if (isSelected.HasValue && isSelected.Value) 15 | { 16 | return new SolidColorBrush(new Color(255, 75, 75, 75)); 17 | } 18 | return null; 19 | } 20 | 21 | public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) 22 | { 23 | throw new NotImplementedException(); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Extensions/ByteArrayExtensions.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Media.Imaging; 2 | using System.IO; 3 | 4 | namespace StableDiffusionTagManager.Extensions 5 | { 6 | internal static class ByteArrayExtensions 7 | { 8 | public static Bitmap ToBitmap(this byte[] byteArray) 9 | { 10 | using (MemoryStream memoryStream = new MemoryStream(byteArray)) 11 | { 12 | return new Bitmap(memoryStream); 13 | } 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Extensions/IEnumerableExtensions.cs: -------------------------------------------------------------------------------- 1 | using StableDiffusionTagManager.Collections; 2 | using StableDiffusionTagManager.ViewModels; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Collections.ObjectModel; 6 | using System.Linq; 7 | 8 | namespace StableDiffusionTagManager.Extensions 9 | { 10 | public static class IEnumerableExtensions 11 | { 12 | public static ObservableCollection ToObservableCollection(this IEnumerable col) 13 | { 14 | return new ObservableCollection(col); 15 | } 16 | 17 | public static OrderedSetObservableCollection ToOrderedSetObservableCollection(this IEnumerable col, System.Comparison pred) 18 | { 19 | var toReturn = new OrderedSetObservableCollection(pred); 20 | foreach(var item in col) 21 | { 22 | toReturn.Add(item); 23 | } 24 | return toReturn; 25 | } 26 | 27 | public static List ToDropdownSelectItems(this IEnumerable items, Func nameSelector) 28 | { 29 | return items.Select(item => (DropdownSelectItem)new DropdownSelectItem(nameSelector(item), item)).ToList(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Extensions/LockedFramebufferExtensions.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Media; 2 | using Avalonia.Platform; 3 | using System; 4 | 5 | namespace StableDiffusionTagManager.Extensions 6 | { 7 | public static class LockedFramebufferExtensions 8 | { 9 | public static Span GetPixels(this ILockedFramebuffer framebuffer) 10 | { 11 | unsafe 12 | { 13 | return new Span((byte*)framebuffer.Address, framebuffer.RowBytes * framebuffer.Size.Height); 14 | } 15 | } 16 | 17 | public static Span GetPixel(this ILockedFramebuffer framebuffer, int x, int y) 18 | { 19 | unsafe 20 | { 21 | var bytesPerPixel = framebuffer.Format.GetBytesPerPixel(); 22 | var zero = (byte*)framebuffer.Address; 23 | var offset = framebuffer.RowBytes * y + bytesPerPixel * x; 24 | return new Span(zero + offset, bytesPerPixel); 25 | } 26 | } 27 | 28 | public static Color GetPixelColor(this ILockedFramebuffer framebuffer, int x, int y) 29 | { 30 | var pixel = framebuffer.GetPixel(x, y); 31 | 32 | var alpha = 0.0; 33 | 34 | if (framebuffer.Format == PixelFormat.Rgb565) 35 | { 36 | var value = pixel[0] << 8 | pixel[1]; 37 | return new Color(255, (byte)((value >> 8) & 0b11111000), (byte)((value >> 3) & 0b11111100), (byte)((value << 3 & 0b11111000))); 38 | } 39 | else if (framebuffer.Format == PixelFormat.Rgba8888) 40 | { 41 | alpha = pixel[3] * 255.0; 42 | return new Color(pixel[3], (byte)(pixel[0] * alpha), (byte)(pixel[1] * alpha), (byte)(pixel[2] * alpha)); 43 | } 44 | else if (framebuffer.Format == PixelFormat.Bgra8888) 45 | { 46 | alpha = pixel[3] * 255.0; 47 | return new Color(pixel[3], (byte)(pixel[2] * alpha), (byte)(pixel[1] * alpha), (byte)(pixel[0] * alpha)); 48 | } 49 | throw new ArgumentOutOfRangeException(); 50 | } 51 | 52 | 53 | public static void SetPixel(this ILockedFramebuffer framebuffer, int x, int y, Color color) 54 | { 55 | var pixel = framebuffer.GetPixel(x, y); 56 | 57 | var alpha = color.A / 255.0; 58 | 59 | if (framebuffer.Format == PixelFormat.Rgb565) 60 | { 61 | var value = (((color.R & 0b11111000) << 8) + ((color.G & 0b11111100) << 3) + (color.B >> 3)); 62 | pixel[0] = (byte)value; 63 | pixel[1] = (byte)(value >> 8); 64 | } 65 | else if (framebuffer.Format == PixelFormat.Rgba8888) 66 | { 67 | pixel[0] = (byte)(color.R * alpha); 68 | pixel[1] = (byte)(color.G * alpha); 69 | pixel[2] = (byte)(color.B * alpha); 70 | pixel[3] = color.A; 71 | } 72 | else if (framebuffer.Format == PixelFormat.Bgra8888) 73 | { 74 | pixel[0] = (byte)(color.B * alpha); 75 | pixel[1] = (byte)(color.G * alpha); 76 | pixel[2] = (byte)(color.R * alpha); 77 | pixel[3] = color.A; 78 | } else 79 | { 80 | throw new ArgumentOutOfRangeException(); 81 | } 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Extensions/MaskResult.cs: -------------------------------------------------------------------------------- 1 | using SixLabors.ImageSharp; 2 | 3 | namespace StableDiffusionTagManager.Extensions 4 | { 5 | public class CropBounds 6 | { 7 | public int X { get; set; } 8 | public int Y { get; set; } 9 | public int Width { get; set; } 10 | public int Height { get; set; } 11 | } 12 | public class MaskResult 13 | { 14 | 15 | public CropBounds Bounds { get; set; } = new CropBounds(); 16 | public Image FullMaskedImage { get; set; } 17 | public Image CroppedMaskedImage { get; set; } 18 | public Image CroppedMask { get; set; } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Extensions/PixelFormatExtensions.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Platform; 2 | 3 | namespace StableDiffusionTagManager.Extensions 4 | { 5 | public static class PixelFormatExtensions 6 | { 7 | public static int GetBytesPerPixel(this PixelFormat pixelFormat) 8 | { 9 | if(pixelFormat == PixelFormat.Rgb565) 10 | { 11 | return 2; 12 | } 13 | 14 | return 4; 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Extensions/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel; 2 | 3 | namespace StableDiffusionTagManager.Extensions 4 | { 5 | public static class StringExtensions 6 | { 7 | public static T? ConvertTo(this string data) 8 | { 9 | TypeConverter conv = TypeDescriptor.GetConverter(typeof(T)); 10 | return (T?)conv.ConvertFromInvariantString(data); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Models/ImageAspectRatioSet.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using CommunityToolkit.Mvvm.ComponentModel; 3 | using StableDiffusionTagManager.ViewModels; 4 | using System; 5 | using System.Collections.ObjectModel; 6 | 7 | namespace StableDiffusionTagManager.Views 8 | { 9 | public partial class ImageAspectRatioSet : ViewModelBase 10 | { 11 | [ObservableProperty] 12 | private string name; 13 | 14 | [ObservableProperty] 15 | private ObservableCollection resolutions = new(); 16 | 17 | private ImageResolution? FindClosest(double aspect) 18 | { 19 | ImageResolution closestResolution = null; 20 | double closestDifference = double.MaxValue; 21 | 22 | foreach (var resolution in Resolutions) 23 | { 24 | double resolutionAspect = resolution.ImageAspectRatio; 25 | double difference = Math.Abs(resolutionAspect - aspect); 26 | 27 | if (difference < closestDifference) 28 | { 29 | closestDifference = difference; 30 | closestResolution = resolution; 31 | } 32 | } 33 | 34 | return closestResolution; 35 | } 36 | public double GetClosestAspectRatio(double aspect) 37 | { 38 | return FindClosest(aspect)?.ImageAspectRatio ?? 0.0; 39 | } 40 | 41 | internal PixelSize? GetClosesResolution(double aspect) 42 | { 43 | var closest = FindClosest(aspect); 44 | 45 | if (closest != null) 46 | { 47 | return new PixelSize(closest.X, closest.Y); 48 | } 49 | 50 | return null; 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Models/ImageFilterMode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace StableDiffusionTagManager.Models 8 | { 9 | public enum ImageFilterMode 10 | { 11 | None = 0, 12 | Completed, 13 | NotCompleted 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Models/ImageResolution.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | using StableDiffusionTagManager.ViewModels; 3 | 4 | namespace StableDiffusionTagManager.Views 5 | { 6 | public partial class ImageResolution : ViewModelBase { 7 | 8 | partial void OnXChanged(int oldValue, int newValue) 9 | { 10 | _imageAspectRatio = null; 11 | } 12 | 13 | partial void OnYChanged(int oldValue, int newValue) 14 | { 15 | _imageAspectRatio = null; 16 | } 17 | 18 | [ObservableProperty] 19 | private int x; 20 | 21 | [ObservableProperty] 22 | private int y; 23 | 24 | private double? _imageAspectRatio = null; 25 | public double ImageAspectRatio 26 | { 27 | get 28 | { 29 | if (_imageAspectRatio == null) 30 | { 31 | _imageAspectRatio = _imageAspectRatio ?? (Y != 0 ? (double?)X / (double)Y : 0.0); 32 | } 33 | return _imageAspectRatio.Value; 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Models/TagCollection.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace StableDiffusionTagManager.Models 4 | { 5 | public class TagCollection 6 | { 7 | public string Name { get; set; } = string.Empty; 8 | public List Tags { get; set; } = new List(); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Models/TagCountModel.cs: -------------------------------------------------------------------------------- 1 | namespace StableDiffusionTagManager.Models 2 | { 3 | public class TagCountModel 4 | { 5 | public string Tag { get; set; } = ""; 6 | public int Count { get; set; } = 0; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Models/XmlSettingsFile.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Xml.Linq; 4 | 5 | namespace StableDiffusionTagManager.Models 6 | { 7 | public abstract class XmlSettingsFile 8 | { 9 | private string filename; 10 | private readonly string rootelementname; 11 | 12 | public XmlSettingsFile(string filename, string rootelementname) 13 | { 14 | this.filename = filename; 15 | this.rootelementname = rootelementname; 16 | Load(); 17 | } 18 | 19 | public void Load() 20 | { 21 | if (File.Exists(filename)) 22 | { 23 | var doc = XDocument.Load(filename); 24 | 25 | LoadSettings(doc); 26 | } 27 | } 28 | 29 | public void Save() 30 | { 31 | XDocument doc = new XDocument(); 32 | 33 | doc.Add(new XElement(rootelementname)); 34 | AddSettings(doc); 35 | doc.Save(filename); 36 | } 37 | 38 | protected abstract void AddSettings(XDocument doc); 39 | protected abstract void LoadSettings(XDocument doc); 40 | 41 | protected string? LoadSetting(XDocument doc, string name, string? def = null) 42 | { 43 | return doc.Root?.Attribute(name)?.Value ?? def; 44 | } 45 | 46 | protected Nullable LoadSetting(XDocument doc, string name, TargetType def = default(TargetType)) 47 | where TargetType : struct 48 | { 49 | var value = doc.Root?.Attribute(name)?.Value; 50 | if (value != null) 51 | { 52 | return (TargetType?)Convert.ChangeType(value, typeof(TargetType)); 53 | } 54 | 55 | return null; 56 | } 57 | 58 | protected void SaveSetting(XDocument doc, string name, string? value) 59 | { 60 | if (value != null) 61 | { 62 | doc.Root?.SetAttributeValue(name, value); 63 | } 64 | } 65 | 66 | protected void SaveSetting(XDocument doc, string name, TargetType value) 67 | { 68 | doc.Root?.SetAttributeValue(name, value?.ToString()); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Program.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using System; 3 | 4 | namespace StableDiffusionTagManager 5 | { 6 | internal class Program 7 | { 8 | // Initialization code. Don't use any Avalonia, third-party APIs or any 9 | // SynchronizationContext-reliant code before AppMain is called: things aren't initialized 10 | // yet and stuff might break. 11 | [STAThread] 12 | public static void Main(string[] args) => BuildAvaloniaApp() 13 | .StartWithClassicDesktopLifetime(args); 14 | 15 | // Avalonia configuration, don't remove; also used by visual designer. 16 | public static AppBuilder BuildAvaloniaApp() 17 | => AppBuilder.Configure() 18 | .UsePlatformDetect() 19 | .LogToTrace(); 20 | } 21 | } -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Roots.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/ServiceCollectionExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | using StableDiffusionTagManager.Attributes; 3 | using StableDiffusionTagManager.Services; 4 | using StableDiffusionTagManager.ViewModels; 5 | using System.Linq; 6 | using System.Runtime.InteropServices; 7 | 8 | namespace StableDiffusionTagManager 9 | { 10 | public static class ServiceCollectionExtensions 11 | { 12 | public static void AddCommonServices(this IServiceCollection collection) 13 | { 14 | collection.Scan(collection => collection 15 | .FromAssemblyOf() 16 | .AddClasses(classes => classes.AssignableTo()) 17 | .AsSelf() 18 | .WithTransientLifetime()); 19 | 20 | collection.Scan(collection => collection 21 | .FromAssemblyOf() 22 | .AddClasses(classes => classes.WithAttribute()) 23 | .AsSelf() 24 | .WithTransientLifetime()); 25 | 26 | collection.Scan(collection => collection 27 | .FromAssemblyOf() 28 | .AddClasses(classes => classes.AssignableTo().WithoutAttribute()) 29 | .AsImplementedInterfaces() 30 | .WithTransientLifetime()); 31 | 32 | collection.Scan(collection => collection 33 | .FromAssemblyOf() 34 | .AddClasses(classes => classes.AssignableTo() 35 | .WithAttribute(attr => attr.Platforms.Any(platform => RuntimeInformation.IsOSPlatform(OSPlatform.Create(platform)))) 36 | ) 37 | .AsImplementedInterfaces() 38 | .WithTransientLifetime()); 39 | 40 | collection.Scan(collection => collection 41 | .FromAssemblyOf() 42 | .AddClasses(classes => classes.AssignableTo().WithoutAttribute()) 43 | .AsImplementedInterfaces() 44 | .WithTransientLifetime()); 45 | 46 | collection.Scan(collection => collection 47 | .FromAssemblyOf() 48 | .AddClasses(classes => classes.AssignableTo() 49 | .WithAttribute(attr => attr.Platforms.Any(platform => RuntimeInformation.IsOSPlatform(OSPlatform.Create(platform)))) 50 | ) 51 | .AsImplementedInterfaces() 52 | .WithTransientLifetime()); 53 | 54 | collection.AddTransient(); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Services/ComicPanelExtractor.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Media.Imaging; 2 | using Avalonia; 3 | using ImageUtil; 4 | using StableDiffusionTagManager.Models; 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | using System.IO; 10 | using StableDiffusionTagManager.Extensions; 11 | using StableDiffusionTagManager.Attributes; 12 | 13 | namespace StableDiffusionTagManager.Services 14 | { 15 | [Service] 16 | public class ComicPanelExtractor 17 | { 18 | private readonly Settings settings; 19 | 20 | public ComicPanelExtractor(Settings settings) 21 | { 22 | this.settings = settings; 23 | } 24 | 25 | public async Task?> ExtractComicPanels(Bitmap bitmap, RenderTargetBitmap? paint = null) 26 | { 27 | string tmpImage = Path.Combine(App.GetTempFileDirectory(), $"{Guid.NewGuid()}.png"); 28 | bitmap.Save(tmpImage); 29 | 30 | var appDir = App.GetAppDirectory(); 31 | 32 | KumikoWrapper kwrapper = new KumikoWrapper(settings.PythonPath, Path.Combine(new string[] { appDir, "Assets", "kumiko" })); 33 | var results = await kwrapper.GetImagePanels(tmpImage, App.GetTempFileDirectory()); 34 | 35 | return results.Select(r => bitmap.CreateNewImageFromRegion(new Rect(r.TopLeftX, r.TopLeftY, r.Width, r.Height), null, paint)).ToList(); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Services/DialogHandler.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | using MsBox.Avalonia.Base; 3 | using StableDiffusionTagManager.Controls; 4 | using StableDiffusionTagManager.Views; 5 | using System.Threading.Tasks; 6 | 7 | namespace StableDiffusionTagManager.Services 8 | { 9 | public class DialogHandler 10 | { 11 | private MainWindow window; 12 | 13 | public DialogHandler(MainWindow window) 14 | { 15 | this.window = window; 16 | } 17 | 18 | public Task ShowDialog(IMsBox msgBox) 19 | { 20 | return msgBox.ShowWindowDialogAsync(window); 21 | } 22 | 23 | public TResultType ShowDialog(IDialogWithResult dialogWithResult) 24 | { 25 | return dialogWithResult.ShowWithResult(window); 26 | } 27 | 28 | public Task ShowDialog(IDialogWithResultAsync dialogWithResult) 29 | { 30 | return dialogWithResult.ShowWithResult(window); 31 | } 32 | 33 | public Task ShowWindowAsDialog(Window dialog) 34 | { 35 | return dialog.ShowDialog(window); 36 | } 37 | 38 | public Task ShowWindowAsDialog(Window dialog) 39 | { 40 | return dialog.ShowDialog(window); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Services/ViewModelFactory.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.DependencyInjection; 2 | using StableDiffusionTagManager.Attributes; 3 | using StableDiffusionTagManager.ViewModels; 4 | using System; 5 | 6 | namespace StableDiffusionTagManager.Services 7 | { 8 | [Service] 9 | public class ViewModelFactory 10 | { 11 | private readonly IServiceProvider _serviceProvider; 12 | 13 | public ViewModelFactory(IServiceProvider serviceProvider) 14 | { 15 | _serviceProvider = serviceProvider; 16 | } 17 | 18 | public T CreateViewModel() where T : ViewModelBase 19 | { 20 | return _serviceProvider.GetRequiredService(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Services/WebApiFactory.cs: -------------------------------------------------------------------------------- 1 | using MsBox.Avalonia.Enums; 2 | using MsBox.Avalonia; 3 | using SdWebUiApi.Api; 4 | using StableDiffusionTagManager.Models; 5 | using StableDiffusionTagManager.Attributes; 6 | 7 | namespace StableDiffusionTagManager.Services 8 | { 9 | [Service] 10 | public class WebApiFactory 11 | { 12 | private readonly Settings settings; 13 | private readonly DialogHandler dialogHandler; 14 | 15 | public WebApiFactory(Settings settings, DialogHandler dialogHandler) 16 | { 17 | this.settings = settings; 18 | this.dialogHandler = dialogHandler; 19 | } 20 | 21 | public DefaultApi? GetWebApi() 22 | { 23 | if (string.IsNullOrEmpty(settings.WebUiAddress)) 24 | { 25 | var messageBoxStandardWindow = MessageBoxManager 26 | .GetMessageBoxStandard("Web UI Address not set", 27 | "The Web UI Address is not set, please set it in the settings dialog.", 28 | ButtonEnum.Ok, 29 | Icon.Warning); 30 | dialogHandler.ShowDialog(messageBoxStandardWindow); 31 | return null; 32 | } 33 | return new DefaultApi(settings.WebUiAddress); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Styles/Controls/Checkbox.axaml: -------------------------------------------------------------------------------- 1 |  3 | 4 | 5 | Test checkbox 6 | 7 | 8 | 56 | 57 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Styles/Controls/Dialog.axaml: -------------------------------------------------------------------------------- 1 |  4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 23 | 26 | 27 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Styles/Controls/HeaderControl.axaml: -------------------------------------------------------------------------------- 1 |  4 | 5 | 6 | 7 | 11 | 12 | 13 | 14 | 15 | 16 | 45 | 46 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Styles/Controls/InputForm.axaml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | Test Item 14 | 15 | 16 | 17 | 18 | 19 | Test Item 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 34 | 35 | 38 | 42 | 46 | 49 | 50 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Styles/Controls/Overlay.axaml: -------------------------------------------------------------------------------- 1 |  6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 33 | 34 | 38 | 39 | 47 | 48 | 56 | 57 | 62 | 63 | 70 | 71 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Styles/Controls/Tag.axaml: -------------------------------------------------------------------------------- 1 |  3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 26 | 29 | 32 | 36 | 42 | 43 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Styles/Controls/Toolbar.axaml: -------------------------------------------------------------------------------- 1 |  4 | 5 | 6 | 7 | 10 | 13 | 16 | 17 | 18 | 19 | 23 | 29 | 33 | 39 | 42 | 49 | 52 | 58 | 59 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/ViewLocator.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | using Avalonia.Controls.Templates; 3 | using StableDiffusionTagManager.ViewModels; 4 | using System; 5 | 6 | namespace StableDiffusionTagManager 7 | { 8 | public class ViewLocator : IDataTemplate 9 | { 10 | public bool Match(object data) 11 | { 12 | return data is ViewModelBase; 13 | } 14 | 15 | Control? ITemplate.Build(object? param) 16 | { 17 | if(param != null) 18 | { 19 | var name = param.GetType().FullName!.Replace("ViewModel", "View"); 20 | if (name != param.GetType().FullName) 21 | { 22 | var type = Type.GetType(name); 23 | 24 | if (type != null) 25 | { 26 | return (Control)Activator.CreateInstance(type)!; 27 | } 28 | } 29 | } 30 | 31 | return new TextBlock { Text = "Param is null." }; 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/ViewModels/CheckBoxViewModel.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | 3 | namespace StableDiffusionTagManager.ViewModels 4 | { 5 | public partial class CheckBoxViewModel : ViewModelBase 6 | { 7 | [ObservableProperty] 8 | private bool isChecked = false; 9 | 10 | [ObservableProperty] 11 | private string text = string.Empty; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/ViewModels/DefaultNaturalLanguageInterrogationViewModel.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | using ImageUtil; 3 | using ImageUtil.Interrogation; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Threading.Tasks; 7 | 8 | namespace StableDiffusionTagManager.ViewModels 9 | { 10 | public partial class DefaultNaturalLanguageInterrogationViewModel : InterrogatorViewModel 11 | { 12 | private readonly Func> factory; 13 | [ObservableProperty] 14 | public string prompt = "Describe the image."; 15 | 16 | public override bool IsValid => throw new NotImplementedException(); 17 | 18 | public DefaultNaturalLanguageInterrogationViewModel(Func> factory, string? defaultPrompt = null) 19 | { 20 | this.factory = factory; 21 | this.prompt = defaultPrompt ?? "Describe the image."; 22 | } 23 | 24 | public override ConfiguredInterrogationContext CreateInterrogationContext() 25 | { 26 | var interrogator = factory.Invoke(); 27 | 28 | return new ConfiguredInterrogationContext(interrogator, interrogator.Initialize, (imageData, updateCallback, consoleCallback) => interrogator.CaptionImage(Prompt, imageData, consoleCallback)); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/ViewModels/DefaultTagInterrogationViewModel.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | using ImageUtil; 3 | using ImageUtil.Interrogation; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Threading.Tasks; 7 | 8 | namespace StableDiffusionTagManager.ViewModels 9 | { 10 | public partial class DefaultTagInterrogationViewModel : InterrogatorViewModel> 11 | { 12 | private readonly Func> interrogatorFactory; 13 | 14 | public DefaultTagInterrogationViewModel(Func> interrogatorFactory) 15 | { 16 | this.interrogatorFactory = interrogatorFactory; 17 | } 18 | 19 | public override ConfiguredInterrogationContext> CreateInterrogationContext() 20 | { 21 | var interrogator = interrogatorFactory.Invoke(); 22 | 23 | return new ConfiguredInterrogationContext>(interrogator, interrogator.Initialize, (imageData, updateCallback, consoleCallback) => interrogator.TagImage(Threshold, imageData, consoleCallback)); 24 | } 25 | 26 | [ObservableProperty] 27 | public float threshold = 0.5f; 28 | 29 | 30 | public override bool IsValid => Threshold >= 0 && Threshold <= 1; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/ViewModels/DropdownSelectItem.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | 3 | namespace StableDiffusionTagManager.ViewModels 4 | { 5 | public partial class DropdownSelectItem : ViewModelBase 6 | { 7 | public DropdownSelectItem(string name) 8 | { 9 | this.name = name; 10 | } 11 | 12 | [ObservableProperty] 13 | private string name; 14 | } 15 | 16 | public class DropdownSelectItem : DropdownSelectItem 17 | { 18 | public DropdownSelectItem(string name, T value) : base(name) 19 | { 20 | Value = value; 21 | } 22 | 23 | public T Value { get; } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/ViewModels/INaturalLanguageInterrogatorViewModelFactory.cs: -------------------------------------------------------------------------------- 1 | using ImageUtil; 2 | using ImageUtil.Interrogation; 3 | using StableDiffusionTagManager.Attributes; 4 | using System.Collections.Generic; 5 | using System.Runtime.InteropServices; 6 | 7 | namespace StableDiffusionTagManager.ViewModels 8 | { 9 | public interface INaturalLanguageInterrogatorViewModelFactory 10 | { 11 | string Name { get; } 12 | 13 | public InterrogatorViewModel CreateViewModel(); 14 | 15 | public List SupportedPlatforms => new List { OSPlatform.Windows, OSPlatform.Linux, OSPlatform.OSX }; 16 | } 17 | 18 | [SupportedPlatforms("Linux")] 19 | public class CogVLM2InterrogatorViewModelFactory : INaturalLanguageInterrogatorViewModelFactory 20 | { 21 | public string Name => "CogVLM2"; 22 | 23 | public InterrogatorViewModel CreateViewModel() 24 | { 25 | return new DefaultNaturalLanguageInterrogationViewModel(() => new CogVLM2Interrogator(), "Describe the image with as much detail as possible."); 26 | } 27 | 28 | public List SupportedPlatforms => new List { OSPlatform.Linux }; 29 | } 30 | 31 | 32 | public class JoyCaptionPreAlphaViewModelFactory : INaturalLanguageInterrogatorViewModelFactory 33 | { 34 | public string Name => "Joy Caption Pre-Alpha"; 35 | 36 | public InterrogatorViewModel CreateViewModel() 37 | { 38 | return new DefaultNaturalLanguageInterrogationViewModel(() => new JoyCaptionPreAlpha(), "A descriptive caption for this image:"); 39 | } 40 | } 41 | 42 | public class JoyCaptionAlphaOneViewModelFactory : INaturalLanguageInterrogatorViewModelFactory 43 | { 44 | public string Name => "Joy Caption Alpha One"; 45 | 46 | public InterrogatorViewModel CreateViewModel() 47 | { 48 | return new DefaultNaturalLanguageInterrogationViewModel(() => new JoyCaptionAlphaOne(), "Write a descriptive caption for this image in a formal tone."); 49 | } 50 | } 51 | 52 | public class JoyCaptionAlphaTwoViewModelFactory : INaturalLanguageInterrogatorViewModelFactory 53 | { 54 | public string Name => "Joy Caption Alpha Two"; 55 | 56 | public InterrogatorViewModel CreateViewModel() 57 | { 58 | return new JoyCaptionAlphaTwoNaturalLanguageInterrogationViewModel(); 59 | } 60 | } 61 | 62 | public class JoyCaptionBetaOneNaturalLanguageViewModelFactory : INaturalLanguageInterrogatorViewModelFactory 63 | { 64 | public string Name => "Joy Caption Beta One"; 65 | 66 | public InterrogatorViewModel CreateViewModel() 67 | { 68 | return new JoyCaptionBetaOneNaturalLanguageInterrogationViewModel(); 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/ViewModels/ImageReviewViewModel.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Media.Imaging; 2 | using CommunityToolkit.Mvvm.Input; 3 | using StableDiffusionTagManager.Views; 4 | using System; 5 | using System.Threading.Tasks; 6 | 7 | namespace StableDiffusionTagManager.ViewModels 8 | { 9 | public partial class ImageReviewActionViewModel : ViewModelBase 10 | { 11 | private ImageReviewDialog _parent; 12 | 13 | public ImageReviewActionViewModel(ImageReviewDialog parent) 14 | { 15 | _parent = parent; 16 | } 17 | 18 | public Func? Action { get; set; } 19 | 20 | public bool CanClick => _parent.SelectedImage != null; 21 | 22 | [RelayCommand(CanExecute = nameof(CanClick))] 23 | public async Task ActionClick(Bitmap selectedImage) 24 | { 25 | if(Action != null) 26 | { 27 | await Action.Invoke(selectedImage); 28 | } 29 | } 30 | 31 | public string Name { get; set; } = ""; 32 | } 33 | 34 | public class ImageReviewViewModel : ViewModelBase 35 | { 36 | private bool isSelected = false; 37 | private Bitmap image; 38 | 39 | public ImageReviewViewModel(Bitmap image) 40 | { 41 | this.image = image; 42 | } 43 | 44 | public Bitmap Image 45 | { 46 | get => image; 47 | set 48 | { 49 | SetProperty(ref image, value); 50 | } 51 | } 52 | 53 | public bool IsSelected 54 | { 55 | get => isSelected; 56 | set 57 | { 58 | SetProperty(ref isSelected, value); 59 | } 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/ViewModels/InterrogationDialogViewModel.cs: -------------------------------------------------------------------------------- 1 | using ImageUtil; 2 | using System.Collections.Generic; 3 | using System; 4 | using System.Linq; 5 | using CommunityToolkit.Mvvm.ComponentModel; 6 | using System.ComponentModel; 7 | using CommunityToolkit.Mvvm.Input; 8 | 9 | namespace StableDiffusionTagManager.ViewModels 10 | { 11 | public partial class InterrogationDialogViewModel : ViewModelBase 12 | { 13 | public event EventHandler? RequestClose; 14 | 15 | public InterrogationDialogViewModel(IEnumerable taggers, IEnumerable naturalLanguageInterrogators) 16 | { 17 | Taggers = taggers.Prepend(null); 18 | NaturalLanguageInterrogators = naturalLanguageInterrogators.Prepend(null); 19 | } 20 | 21 | protected override void OnPropertyChanged(PropertyChangedEventArgs change) 22 | { 23 | base.OnPropertyChanged(change); 24 | 25 | if (change.PropertyName == nameof(SelectedTagInterrogator)) 26 | { 27 | if (SelectedTagInterrogator != null) 28 | { 29 | SelectedTagSettingsViewModel = SelectedTagInterrogator.CreateViewModel(); 30 | } 31 | else 32 | { 33 | SelectedTagSettingsViewModel = null; 34 | } 35 | } 36 | 37 | if (change.PropertyName == nameof(SelectedNaturalLanguageInterrogator)) 38 | { 39 | if (SelectedNaturalLanguageInterrogator != null) 40 | { 41 | SelectedNaturalLanguageSettingsViewModel = SelectedNaturalLanguageInterrogator.CreateViewModel(); 42 | } 43 | else 44 | { 45 | SelectedNaturalLanguageSettingsViewModel = null; 46 | } 47 | } 48 | } 49 | 50 | 51 | [ObservableProperty] 52 | public IEnumerable taggers; 53 | 54 | [ObservableProperty] 55 | private ITaggerViewModelFactory? selectedTagInterrogator; 56 | [ObservableProperty] 57 | private InterrogatorViewModel>? selectedTagSettingsViewModel; 58 | 59 | 60 | [ObservableProperty] 61 | public IEnumerable naturalLanguageInterrogators; 62 | [ObservableProperty] 63 | private INaturalLanguageInterrogatorViewModelFactory? selectedNaturalLanguageInterrogator; 64 | [ObservableProperty] 65 | private InterrogatorViewModel? selectedNaturalLanguageSettingsViewModel; 66 | 67 | 68 | public bool Success { get; set; } = false; 69 | 70 | [RelayCommand] 71 | public void Interrogate() 72 | { 73 | if (SelectedNaturalLanguageInterrogator != null || SelectedTagInterrogator != null) 74 | { 75 | Success = true; 76 | RequestClose?.Invoke(this, EventArgs.Empty); 77 | } 78 | } 79 | 80 | [RelayCommand] 81 | public void Cancel() 82 | { 83 | RequestClose?.Invoke(this, EventArgs.Empty); 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/ViewModels/InterrogatorViewModel.cs: -------------------------------------------------------------------------------- 1 | using ImageUtil.Interrogation; 2 | using System; 3 | using System.Threading.Tasks; 4 | 5 | namespace StableDiffusionTagManager.ViewModels 6 | { 7 | public abstract class InterrogatorViewModel : ValidatedViewModel 8 | { 9 | public abstract ConfiguredInterrogationContext CreateInterrogationContext(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/ViewModels/JoyCaptionAlphaTwoNaturalLanguageInterrogationViewModel.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | using ImageUtil.Interrogation; 3 | using StableDiffusionTagManager.Extensions; 4 | using System.Collections.ObjectModel; 5 | using System.Linq; 6 | 7 | namespace StableDiffusionTagManager.ViewModels 8 | { 9 | public partial class JoyCaptionAlphaTwoNaturalLanguageInterrogationViewModel : InterrogatorViewModel 10 | { 11 | public JoyCaptionAlphaTwoNaturalLanguageInterrogationViewModel() 12 | { 13 | extraOptions = JoyCaptionAlphaTwo.ExtraOptionText.Select(text => new CheckBoxViewModel { Text = text }).ToObservableCollection(); 14 | } 15 | 16 | [ObservableProperty] 17 | private ObservableCollection extraOptions; 18 | 19 | [ObservableProperty] 20 | private string selectedPrompt; 21 | 22 | [ObservableProperty] 23 | private string selectedLength; 24 | 25 | [ObservableProperty] 26 | private string characterName; 27 | 28 | [ObservableProperty] 29 | private string customPrompt; 30 | 31 | public override ConfiguredInterrogationContext CreateInterrogationContext() 32 | { 33 | var interrogator = new JoyCaptionAlphaTwo(); 34 | 35 | var args = new JoyCaptionAlphaTwoArgs 36 | { 37 | CaptionType = SelectedPrompt, 38 | Length = SelectedLength, 39 | ExtraOptions = ExtraOptions.Where(x => x.IsChecked).Any() ? ExtraOptions.Where(x => x.IsChecked).Select(x => x.Text).Aggregate((l, r) => $"{l},{r}") : "", 40 | NameInput = CharacterName 41 | }; 42 | 43 | return new ConfiguredInterrogationContext(interrogator, interrogator.Initialize, (imageData, updateCallback, consoleCallback) => interrogator.CaptionImage(args, imageData, consoleCallback)); 44 | } 45 | 46 | public override bool IsValid => true; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/ViewModels/JoyCaptionAlphaTwoTagInterrogationViewModel.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | using ImageUtil.Interrogation; 3 | using StableDiffusionTagManager.Extensions; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Collections.ObjectModel; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | using TagUtil; 10 | 11 | namespace StableDiffusionTagManager.ViewModels 12 | { 13 | public partial class JoyCaptionAlphaTwoTagInterrogationViewModel : InterrogatorViewModel> 14 | { 15 | public JoyCaptionAlphaTwoTagInterrogationViewModel() 16 | { 17 | extraOptions = JoyCaptionAlphaTwo.ExtraOptionText.Select(text => new CheckBoxViewModel { Text = text }).ToObservableCollection(); 18 | } 19 | 20 | [ObservableProperty] 21 | private ObservableCollection extraOptions; 22 | 23 | [ObservableProperty] 24 | private string selectedPrompt; 25 | 26 | [ObservableProperty] 27 | private string selectedLength; 28 | 29 | [ObservableProperty] 30 | private string characterName; 31 | 32 | [ObservableProperty] 33 | private string customPrompt; 34 | 35 | public override bool IsValid => true; 36 | 37 | public override ConfiguredInterrogationContext> CreateInterrogationContext() 38 | { 39 | var interrogator = new JoyCaptionAlphaTwo(); 40 | 41 | var args = new JoyCaptionAlphaTwoArgs 42 | { 43 | CaptionType = SelectedPrompt, 44 | Length = SelectedLength, 45 | ExtraOptions = ExtraOptions.Where(x => x.IsChecked).Any() ? ExtraOptions.Where(x => x.IsChecked).Select(x => x.Text).Aggregate((l, r) => $"{l},{r}") : "", 46 | NameInput = CharacterName 47 | }; 48 | 49 | return new ConfiguredInterrogationContext>(interrogator, interrogator.Initialize, (imageData, updateCallback, consoleCallback) => interrogator.TagImage(args, imageData, consoleCallback)); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/ViewModels/JoyCaptionBetaOneNaturalLanguageInterrogationViewModel.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | using ImageUtil.Interrogation; 3 | using StableDiffusionTagManager.Extensions; 4 | using System.Collections.ObjectModel; 5 | using System.Linq; 6 | 7 | namespace StableDiffusionTagManager.ViewModels 8 | { 9 | public partial class JoyCaptionBetaOneNaturalLanguageInterrogationViewModel : InterrogatorViewModel 10 | { 11 | public JoyCaptionBetaOneNaturalLanguageInterrogationViewModel() 12 | { 13 | extraOptions = JoyCaptionBetaOne.ExtraOptionText.Select(text => new CheckBoxViewModel { Text = text }).ToObservableCollection(); 14 | } 15 | 16 | [ObservableProperty] 17 | private ObservableCollection extraOptions; 18 | 19 | [ObservableProperty] 20 | private string selectedPrompt; 21 | 22 | [ObservableProperty] 23 | private string selectedLength; 24 | 25 | [ObservableProperty] 26 | private string characterName; 27 | 28 | [ObservableProperty] 29 | private string customPrompt; 30 | 31 | public override ConfiguredInterrogationContext CreateInterrogationContext() 32 | { 33 | var interrogator = new JoyCaptionBetaOne(); 34 | 35 | var args = new JoyCaptionBetaOneArgs 36 | { 37 | CaptionType = SelectedPrompt, 38 | Length = SelectedLength, 39 | ExtraOptions = ExtraOptions.Where(x => x.IsChecked).Any() ? ExtraOptions.Where(x => x.IsChecked).Select(x => x.Text).Aggregate((l, r) => $"{l},{r}") : "", 40 | NameInput = CharacterName 41 | }; 42 | 43 | return new ConfiguredInterrogationContext(interrogator, interrogator.Initialize, (imageData, updateCallback, consoleCallback) => interrogator.CaptionImage(args, imageData, consoleCallback)); 44 | } 45 | 46 | public override bool IsValid => true; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/ViewModels/JoyCaptionBetaOneTagInterrogationViewModel.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | using ImageUtil.Interrogation; 3 | using StableDiffusionTagManager.Extensions; 4 | using System; 5 | using System.Collections.Generic; 6 | using System.Collections.ObjectModel; 7 | using System.Linq; 8 | using System.Threading.Tasks; 9 | using TagUtil; 10 | 11 | namespace StableDiffusionTagManager.ViewModels 12 | { 13 | public partial class JoyCaptionBetaOneTagInterrogationViewModel : InterrogatorViewModel> 14 | { 15 | public JoyCaptionBetaOneTagInterrogationViewModel() 16 | { 17 | extraOptions = JoyCaptionBetaOne.ExtraOptionText.Select(text => new CheckBoxViewModel { Text = text }).ToObservableCollection(); 18 | } 19 | 20 | [ObservableProperty] 21 | private ObservableCollection extraOptions; 22 | 23 | [ObservableProperty] 24 | private string selectedPrompt; 25 | 26 | [ObservableProperty] 27 | private string selectedLength; 28 | 29 | [ObservableProperty] 30 | private string characterName; 31 | 32 | [ObservableProperty] 33 | private string customPrompt; 34 | 35 | public override bool IsValid => true; 36 | 37 | public override ConfiguredInterrogationContext> CreateInterrogationContext() 38 | { 39 | var interrogator = new JoyCaptionBetaOne(); 40 | 41 | var args = new JoyCaptionBetaOneArgs 42 | { 43 | CaptionType = SelectedPrompt, 44 | Length = SelectedLength, 45 | ExtraOptions = ExtraOptions.Where(x => x.IsChecked).Any() ? ExtraOptions.Where(x => x.IsChecked).Select(x => x.Text).Aggregate((l, r) => $"{l},{r}") : "", 46 | NameInput = CharacterName 47 | }; 48 | 49 | return new ConfiguredInterrogationContext>(interrogator, interrogator.Initialize, (imageData, updateCallback, consoleCallback) => interrogator.TagImage(args, imageData, consoleCallback)); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/ViewModels/TagCollectionViewModel.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | using CommunityToolkit.Mvvm.Input; 3 | using StableDiffusionTagManager.Extensions; 4 | using System.Collections.Generic; 5 | using System.Collections.ObjectModel; 6 | using System.Linq; 7 | 8 | namespace StableDiffusionTagManager.ViewModels 9 | { 10 | 11 | public partial class TagCollectionViewModel : ViewModelBase 12 | { 13 | private readonly MainWindowViewModel parent; 14 | 15 | public TagCollectionViewModel( 16 | MainWindowViewModel parent, 17 | string name, 18 | IEnumerable tags) 19 | { 20 | this.parent = parent; 21 | Name = name; 22 | Tags = tags.Select(t => new TagCollectionTagViewModel(this, t)).ToObservableCollection(); 23 | } 24 | 25 | public TagCollectionViewModel( 26 | MainWindowViewModel parent, 27 | string name) 28 | { 29 | this.parent = parent; 30 | Name = name; 31 | Tags = new ObservableCollection(); 32 | } 33 | 34 | [ObservableProperty] 35 | public bool isSelected; 36 | 37 | [ObservableProperty] 38 | private string name; 39 | 40 | [ObservableProperty] 41 | private ObservableCollection tags; 42 | 43 | [RelayCommand] 44 | public void AddTags() 45 | { 46 | parent.AddMissingTagsToEnd(Tags.Select(t => t.Tag).ToList()); 47 | } 48 | 49 | [RelayCommand] 50 | public void EditTags() 51 | { 52 | parent.EditTagCollectionTarget = this; 53 | } 54 | 55 | [RelayCommand] 56 | public void RemoveTagCollection() 57 | { 58 | parent.RemoveTagCollection(this); 59 | } 60 | 61 | public void RemoveTag(TagCollectionTagViewModel toRemove) 62 | { 63 | this.Tags.Remove(toRemove); 64 | } 65 | 66 | public void AddEmptyTag() 67 | { 68 | this.Tags.Add(new TagCollectionTagViewModel(this, "")); 69 | } 70 | } 71 | 72 | public partial class TagCollectionTagViewModel : ViewModelBase 73 | { 74 | TagCollectionViewModel parent; 75 | 76 | [ObservableProperty] 77 | private string tag; 78 | 79 | public TagCollectionTagViewModel(TagCollectionViewModel parent, string tag) 80 | { 81 | this.parent = parent; 82 | this.Tag = tag; 83 | } 84 | 85 | [RelayCommand] 86 | public void RemoveTagFromCollection() 87 | { 88 | parent.RemoveTag(this); 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/ViewModels/TagCountLetterGroupViewModel.cs: -------------------------------------------------------------------------------- 1 | using StableDiffusionTagManager.Collections; 2 | 3 | namespace StableDiffusionTagManager.ViewModels 4 | { 5 | public class TagCountLetterGroupViewModel 6 | { 7 | public TagCountLetterGroupViewModel(char letter) 8 | { 9 | Letter = letter; 10 | } 11 | 12 | public char Letter { get; } 13 | public OrderedSetObservableCollection TagCounts { get; set; } = new OrderedSetObservableCollection((l, r) => l.Tag.CompareTo(r.Tag)); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/ViewModels/TagCountViewModel.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.Input; 2 | 3 | namespace StableDiffusionTagManager.ViewModels 4 | { 5 | public partial class TagWithCountViewModel : ViewModelBase 6 | { 7 | private readonly MainWindowViewModel parent; 8 | private string tag = ""; 9 | private int count; 10 | 11 | public TagWithCountViewModel(MainWindowViewModel parent) 12 | { 13 | this.parent = parent; 14 | } 15 | 16 | [RelayCommand] 17 | public void AddTag() 18 | { 19 | parent.AddTagToEnd(Tag); 20 | } 21 | 22 | [RelayCommand] 23 | public void RemoveTagFromAllImages() 24 | { 25 | parent.RemoveTagFromAllImages(Tag); 26 | } 27 | 28 | [RelayCommand] 29 | public void ReplaceTagInAllImages() 30 | { 31 | parent.ReplaceTagInAllImages(Tag); 32 | } 33 | 34 | public string Tag { get => tag; set => SetProperty(ref tag, value); } 35 | public int Count { get => count; set => SetProperty(ref count, value); } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/ViewModels/TagPrioritySetButtonViewModel.cs: -------------------------------------------------------------------------------- 1 | using StableDiffusionTagManager.Models; 2 | 3 | namespace StableDiffusionTagManager.ViewModels 4 | { 5 | public class TagPrioritySetButtonViewModel : ViewModelBase 6 | { 7 | public TagPrioritySetButtonViewModel(string name, TagCategorySet prioritySet) 8 | { 9 | this.name = name; 10 | PrioritySet = prioritySet; 11 | } 12 | 13 | private string name; 14 | 15 | public string Name 16 | { 17 | get { return name; } 18 | set 19 | { 20 | name = value; 21 | OnPropertyChanged(); 22 | } 23 | } 24 | 25 | public TagCategorySet PrioritySet { get; } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/ViewModels/TagPrioritySetViewModel.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | using CommunityToolkit.Mvvm.Input; 3 | using StableDiffusionTagManager.Extensions; 4 | using StableDiffusionTagManager.Models; 5 | using System.Collections.ObjectModel; 6 | using System.Linq; 7 | using System.Xml.Linq; 8 | 9 | namespace StableDiffusionTagManager.ViewModels 10 | { 11 | public partial class TagCategoryViewModel : ViewModelBase 12 | { 13 | [ObservableProperty] 14 | private string name; 15 | 16 | [ObservableProperty] 17 | private bool isSelected; 18 | 19 | [ObservableProperty] 20 | private ObservableCollection tags = new ObservableCollection(); 21 | 22 | public void RemoveTag(string tag) 23 | { 24 | tags.Remove(tag); 25 | } 26 | } 27 | 28 | public partial class TagPrioritySetViewModel : ViewModelBase 29 | { 30 | public static TagPrioritySetViewModel CreateFromFile(string filename) 31 | { 32 | var doc = XDocument.Load(filename); 33 | 34 | var categories = TagCategorySet.ReadCategories(doc); 35 | 36 | var viewModels = categories.Select(category => 37 | new TagCategoryViewModel 38 | { 39 | Name = category.CategoryName, 40 | Tags = category.Tags.ToObservableCollection() 41 | }).ToObservableCollection(); 42 | 43 | return new TagPrioritySetViewModel() 44 | { 45 | categories = viewModels 46 | }; 47 | } 48 | 49 | public TagPrioritySetViewModel() 50 | { 51 | } 52 | 53 | 54 | [ObservableProperty] 55 | private ObservableCollection categories = new ObservableCollection(); 56 | 57 | [RelayCommand] 58 | public void AddCategory(string name) 59 | { 60 | categories.Add(new TagCategoryViewModel() { Name = name }); 61 | } 62 | 63 | [RelayCommand] 64 | public void RemoveCategory(TagCategoryViewModel target) 65 | { 66 | categories.Remove(target); 67 | } 68 | 69 | public void Save(string filename) 70 | { 71 | var doc = new XDocument( 72 | categories.Select(entry => 73 | new XElement("TagCategory", 74 | new XAttribute("Name", entry.Name), 75 | entry.Tags.Select(tag => new XElement("Tag", tag)) 76 | ) 77 | ) 78 | ); 79 | doc.Save(filename); 80 | } 81 | 82 | internal void MoveTagCategory(TagCategoryViewModel vm, TagCategoryViewModel destvm) 83 | { 84 | if (vm == destvm) return; 85 | 86 | var index = categories.IndexOf(destvm); 87 | categories.Remove(vm); 88 | categories.Insert(index, vm); 89 | } 90 | } 91 | } -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/ViewModels/TagViewModel.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | using System; 3 | 4 | namespace StableDiffusionTagManager.ViewModels 5 | { 6 | public class TagViewModel : ObservableObject 7 | { 8 | private string _tagWhenGainedFocus = null; 9 | 10 | public TagViewModel(string tag) 11 | { 12 | Tag = tag; 13 | } 14 | 15 | private string tag; 16 | public string Tag 17 | { 18 | get => tag; 19 | set { 20 | var temp = tag; 21 | tag = value; 22 | if(!isFocused) 23 | { 24 | TagChanged?.Invoke(temp, value); 25 | } 26 | OnPropertyChanged(); 27 | } 28 | } 29 | 30 | public Action? TagChanged; 31 | 32 | private bool isBeingDragged; 33 | public bool IsBeingDragged 34 | { 35 | get { return isBeingDragged; } 36 | set 37 | { 38 | isBeingDragged = value; 39 | OnPropertyChanged(); 40 | } 41 | } 42 | 43 | private bool isFocused = false; 44 | public bool IsFocused 45 | { 46 | get { return isFocused; } 47 | set 48 | { 49 | if(value != isFocused) 50 | { 51 | if (value) 52 | { 53 | _tagWhenGainedFocus = tag; 54 | } 55 | else if (_tagWhenGainedFocus != tag) 56 | { 57 | TagChanged?.Invoke(_tagWhenGainedFocus, tag); 58 | } 59 | 60 | isFocused = value; 61 | OnPropertyChanged(); 62 | } 63 | 64 | } 65 | } 66 | 67 | //private TagViewModel draggeOverSource; 68 | //public TagViewModel DraggeOverSource 69 | //{ 70 | // get { return draggeOverSource; } 71 | // set 72 | // { 73 | // draggeOverSource = value; 74 | // OnPropertyChanged(); 75 | // } 76 | //} 77 | 78 | //private bool isPlaceHolder; 79 | 80 | //public bool IsPlaceHolder 81 | //{ 82 | // get { return isPlaceHolder; } 83 | // set { isPlaceHolder = value; OnPropertyChanged(); } 84 | //} 85 | 86 | //private bool isFocused; 87 | 88 | //public bool IsFocused 89 | //{ 90 | // get { return isFocused; } 91 | // set { isFocused = value; OnPropertyChanged(); } 92 | //} 93 | 94 | 95 | //public Visibility DropPreviewVisibility => DraggeOverSource != null ? Visibility.Visible : Visibility.Collapsed; 96 | //public Color BackgroundColor => isPlaceHolder ? Color.Parse("Orange") : 97 | // isBeingDragged ? Color.Parse("Grey") : Color.Parse("LightBlue"); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/ViewModels/ViewModelBase.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | 3 | namespace StableDiffusionTagManager.ViewModels 4 | { 5 | public class ViewModelBase : ObservableObject 6 | { 7 | } 8 | 9 | public abstract class ValidatedViewModel : ViewModelBase 10 | { 11 | public abstract bool IsValid { get; } 12 | } 13 | } -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/ViewModels/YOLOModelSelectorDialogViewModel.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | using StableDiffusionTagManager.Services; 3 | namespace StableDiffusionTagManager.ViewModels 4 | { 5 | public partial class YOLOModelSelectorDialogViewModel : ViewModelBase 6 | { 7 | public YOLOModelSelectorDialogViewModel(ViewModelFactory viewModelFactory) 8 | { 9 | selectorViewModel = viewModelFactory.CreateViewModel(); 10 | } 11 | 12 | [ObservableProperty] 13 | private YOLOModelSelectorViewModel selectorViewModel; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/ViewModels/YOLOModelSelectorViewModel.cs: -------------------------------------------------------------------------------- 1 | using CommunityToolkit.Mvvm.ComponentModel; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using System.Linq; 6 | 7 | namespace StableDiffusionTagManager.ViewModels 8 | { 9 | public class YOLOModelSelectorItem 10 | { 11 | public YOLOModelSelectorItem(string filename) 12 | { 13 | Filename = filename; 14 | Name = Path.GetFileName(filename); 15 | } 16 | 17 | public string Filename { get; set; } 18 | public string Name { get; set; } 19 | } 20 | 21 | public partial class YOLOModelSelectorViewModel : ViewModelBase 22 | { 23 | [ObservableProperty] 24 | List models; 25 | [ObservableProperty] 26 | private YOLOModelSelectorItem? selectedModel; 27 | [ObservableProperty] 28 | private float threshold = 0.5f; 29 | [ObservableProperty] 30 | public int expandMask = 0; 31 | 32 | public YOLOModelSelectorViewModel() 33 | { 34 | string yoloModelDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "yolomodels"); 35 | 36 | if(Directory.Exists(yoloModelDirectory)) 37 | { 38 | models = Directory.GetFiles(yoloModelDirectory, "*.pt").Select(file => new YOLOModelSelectorItem(file)).ToList(); 39 | SelectedModel = models.FirstOrDefault(); 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Views/ColorPickerDialog.axaml: -------------------------------------------------------------------------------- 1 | 22 | 23 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Views/ColorPickerDialog.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls; 3 | using Avalonia.Input; 4 | using Avalonia.Media; 5 | using CommunityToolkit.Mvvm.Input; 6 | using StableDiffusionTagManager.Controls; 7 | using System.Threading.Tasks; 8 | 9 | namespace StableDiffusionTagManager.Views 10 | { 11 | public partial class ColorPickerDialog : Window, IDialogWithResultAsync 12 | { 13 | public ColorPickerDialog() 14 | { 15 | InitializeComponent(); 16 | } 17 | 18 | public bool Success { get; set; } = false; 19 | 20 | [RelayCommand] 21 | public void Save() 22 | { 23 | this.Success = true; 24 | Close(); 25 | } 26 | 27 | [RelayCommand] 28 | public void Cancel() 29 | { 30 | Close(); 31 | } 32 | 33 | public async Task ShowWithResult(Window parent) 34 | { 35 | await ShowDialog(parent); 36 | 37 | if (this.Success) 38 | { 39 | return SelectedColor; 40 | } 41 | else 42 | { 43 | return null; 44 | } 45 | } 46 | 47 | public static readonly StyledProperty SelectedColorProperty = 48 | AvaloniaProperty.Register(nameof(SelectedColor), new Color(255, 255, 255, 255)); 49 | 50 | /// 51 | /// Gets or sets if control can render the image 52 | /// 53 | public Color SelectedColor 54 | { 55 | get => GetValue(SelectedColorProperty); 56 | set => SetValue(SelectedColorProperty, value); 57 | } 58 | 59 | public void WindowKeyDown(object sender, KeyEventArgs e) 60 | { 61 | if(e.Key == Key.Escape) 62 | { 63 | Close(); 64 | } 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Views/DefaultNaturalLanguageInterrogationView.axaml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Views/DefaultNaturalLanguageInterrogationView.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | 3 | namespace StableDiffusionTagManager.Views; 4 | 5 | public partial class DefaultNaturalLanguageInterrogationView : UserControl 6 | { 7 | public DefaultNaturalLanguageInterrogationView() 8 | { 9 | InitializeComponent(); 10 | } 11 | } -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Views/DefaultTagInterrogationView.axaml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Views/DefaultTagInterrogationView.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | 3 | namespace StableDiffusionTagManager.Views; 4 | 5 | public partial class DefaultTagInterrogationView : UserControl 6 | { 7 | public DefaultTagInterrogationView() 8 | { 9 | InitializeComponent(); 10 | } 11 | } -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Views/DropdownSelectDialog.axaml: -------------------------------------------------------------------------------- 1 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Views/DropdownSelectDialog.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls; 3 | using Avalonia.Input; 4 | using CommunityToolkit.Mvvm.Input; 5 | using StableDiffusionTagManager.Controls; 6 | using StableDiffusionTagManager.ViewModels; 7 | using System; 8 | using System.Collections.Generic; 9 | using System.Threading.Tasks; 10 | 11 | namespace StableDiffusionTagManager.Views 12 | { 13 | public partial class DropdownSelectDialog : Window, IDialogWithResultAsync 14 | { 15 | public DropdownSelectDialog() 16 | { 17 | InitializeComponent(); 18 | } 19 | 20 | public static readonly StyledProperty> DropdownItemsProperty = 21 | AvaloniaProperty.Register>(nameof(DropdownItems), new List()); 22 | 23 | /// 24 | /// Gets or sets the image to be displayed 25 | /// 26 | public List DropdownItems 27 | { 28 | get => GetValue(DropdownItemsProperty); 29 | set => SetValue(DropdownItemsProperty, value); 30 | } 31 | 32 | public static readonly StyledProperty SelectedItemProperty = 33 | AvaloniaProperty.Register(nameof(SelectedItem)); 34 | 35 | /// 36 | /// Gets or sets the image to be displayed 37 | /// 38 | public DropdownSelectItem? SelectedItem 39 | { 40 | get => GetValue(SelectedItemProperty); 41 | set => SetValue(SelectedItemProperty, value); 42 | } 43 | 44 | public bool Success { get; set; } = false; 45 | 46 | [RelayCommand] 47 | public void Save() 48 | { 49 | this.Success = true; 50 | Close(); 51 | } 52 | 53 | [RelayCommand] 54 | public void Cancel() 55 | { 56 | Close(); 57 | } 58 | 59 | public async Task ShowWithResult(Window parent) 60 | { 61 | await ShowDialog(parent); 62 | 63 | if (this.Success) 64 | { 65 | return SelectedItem; 66 | } 67 | else 68 | { 69 | return null; 70 | } 71 | } 72 | 73 | public void WindowKeyDown(object sender, KeyEventArgs e) 74 | { 75 | if (e.Key == Key.Escape) 76 | { 77 | Close(); 78 | } 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Views/ExpandImageDialog.axaml: -------------------------------------------------------------------------------- 1 | 20 | 21 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Views/ImageViewerWindow.axaml: -------------------------------------------------------------------------------- 1 | 13 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Views/ImageViewerWindow.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls; 3 | using Avalonia.Media.Imaging; 4 | using UVtools.AvaloniaControls; 5 | 6 | namespace StableDiffusionTagManager.Views 7 | { 8 | public partial class ImageViewerWindow : Window 9 | { 10 | public ImageViewerWindow() 11 | { 12 | InitializeComponent(); 13 | 14 | this.DataContext = this; 15 | 16 | Opened += ImageViewerWindow_Opened; 17 | } 18 | 19 | private void ImageViewerWindow_Opened(object? sender, System.EventArgs e) 20 | { 21 | if(Image != null) 22 | { 23 | ImageBox.ZoomToFit(); 24 | } 25 | } 26 | 27 | public static readonly StyledProperty ImageProperty = 28 | AvaloniaProperty.Register(nameof(Image)); 29 | 30 | /// 31 | /// Gets or sets the image to be displayed 32 | /// 33 | public Bitmap? Image 34 | { 35 | get => GetValue(ImageProperty); 36 | set => SetValue(ImageProperty, value); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Views/InterrogationDialog.axaml: -------------------------------------------------------------------------------- 1 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | Natural Language 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | Tags 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Views/InterrogationDialog.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls; 3 | namespace StableDiffusionTagManager.Views; 4 | 5 | public partial class InterrogationDialog : Window 6 | { 7 | public InterrogationDialog() 8 | { 9 | InitializeComponent(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Views/JoyCaptionAlphaTwoNaturalLanguageInterrogationView.axaml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 15 | 16 | 19 | 20 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Views/JoyCaptionAlphaTwoNaturalLanguageInterrogationView.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | 3 | namespace StableDiffusionTagManager.Views; 4 | 5 | public partial class JoyCaptionAlphaTwoNaturalLanguageInterrogationView : UserControl 6 | { 7 | public JoyCaptionAlphaTwoNaturalLanguageInterrogationView() 8 | { 9 | InitializeComponent(); 10 | } 11 | } -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Views/JoyCaptionAlphaTwoTagInterrogationView.axaml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 15 | 16 | 19 | 20 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Views/JoyCaptionAlphaTwoTagInterrogationView.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | 3 | namespace StableDiffusionTagManager.Views; 4 | 5 | public partial class JoyCaptionAlphaTwoTagInterrogationView : UserControl 6 | { 7 | public JoyCaptionAlphaTwoTagInterrogationView() 8 | { 9 | InitializeComponent(); 10 | } 11 | } -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Views/JoyCaptionBetaOneNaturalLanguageInterrogationView.axaml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 15 | 16 | 19 | 20 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Views/JoyCaptionBetaOneNaturalLanguageInterrogationView.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | 3 | namespace StableDiffusionTagManager.Views; 4 | 5 | public partial class JoyCaptionBetaOneNaturalLanguageInterrogationView : UserControl 6 | { 7 | public JoyCaptionBetaOneNaturalLanguageInterrogationView() 8 | { 9 | InitializeComponent(); 10 | } 11 | } -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Views/JoyCaptionBetaOneTagInterrogationView.axaml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 15 | 16 | 19 | 20 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Views/JoyCaptionBetaOneTagInterrogationView.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | 3 | namespace StableDiffusionTagManager.Views; 4 | 5 | public partial class JoyCaptionBetaOneTagInterrogationView : UserControl 6 | { 7 | public JoyCaptionBetaOneTagInterrogationView() 8 | { 9 | InitializeComponent(); 10 | } 11 | } -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Views/NewItemNameDialog.axaml: -------------------------------------------------------------------------------- 1 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Views/NewItemNameDialog.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls; 3 | using CommunityToolkit.Mvvm.Input; 4 | 5 | namespace StableDiffusionTagManager.Views 6 | { 7 | public partial class NewItemNameDialog : Window 8 | { 9 | public NewItemNameDialog() 10 | { 11 | InitializeComponent(); 12 | this.DataContext = this; 13 | } 14 | 15 | public static readonly StyledProperty NewItemNameProperty = 16 | AvaloniaProperty.Register(nameof(NewItemName)); 17 | 18 | /// 19 | /// Gets or sets if control can render the image 20 | /// 21 | public string NewItemName 22 | { 23 | get => GetValue(NewItemNameProperty); 24 | set => SetValue(NewItemNameProperty, value); 25 | } 26 | 27 | public bool Success { get; set; } = false; 28 | 29 | [RelayCommand] 30 | public void Create() 31 | { 32 | Success = true; 33 | Close(); 34 | } 35 | 36 | [RelayCommand] 37 | public void Cancel() 38 | { 39 | Close(); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Views/ProjectSettingsDialog.axaml: -------------------------------------------------------------------------------- 1 | 20 | 21 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Views/TagSearchDialog.axaml: -------------------------------------------------------------------------------- 1 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Views/TagSearchDialog.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | using System.Threading; 5 | using System; 6 | using System.Linq; 7 | using Avalonia.Interactivity; 8 | using Avalonia.Threading; 9 | using Avalonia; 10 | using UVtools.AvaloniaControls; 11 | using CommunityToolkit.Mvvm.Input; 12 | using StableDiffusionTagManager.Controls; 13 | using Avalonia.Input; 14 | 15 | namespace StableDiffusionTagManager.Views 16 | { 17 | public partial class TagSearchDialog : Window, IDialogWithResultAsync 18 | { 19 | public TagSearchDialog() 20 | { 21 | InitializeComponent(); 22 | 23 | Title = "SearchTags"; 24 | this.DataContext = this; 25 | Opened += TagSearchDialog_Opened; 26 | } 27 | 28 | private void TagSearchDialog_Opened(object? sender, EventArgs e) 29 | { 30 | TagAutoComplete.Focus(); 31 | } 32 | 33 | private bool success = false; 34 | 35 | public async Task ShowWithResult(Window parent) 36 | { 37 | await ShowDialog(parent); 38 | 39 | if (this.success && !string.IsNullOrEmpty(TagAutoComplete.Text)) 40 | { 41 | return TagAutoComplete.Text; 42 | } 43 | else 44 | { 45 | return null; 46 | } 47 | } 48 | 49 | public void Cancel_Clicked(object sender, RoutedEventArgs e) 50 | { 51 | this.success = false; 52 | Close(); 53 | } 54 | 55 | public void Ok_Clicked(object sender, RoutedEventArgs e) 56 | { 57 | this.success = true; 58 | Close(); 59 | } 60 | 61 | public static readonly StyledProperty DialogTitleProperty = 62 | AvaloniaProperty.Register(nameof(DialogTitle), "Lookup Tag"); 63 | 64 | public string DialogTitle 65 | { 66 | get => GetValue(DialogTitleProperty); 67 | set => SetValue(DialogTitleProperty, value); 68 | } 69 | 70 | [RelayCommand] 71 | public void HeaderClose() 72 | { 73 | this.success = false; 74 | Close(); 75 | } 76 | 77 | private void KeyDownHandler(KeyEventArgs e) 78 | { 79 | if (e.Key == Key.Enter) 80 | { 81 | this.success = true; 82 | Close(); 83 | } 84 | if(e.Key == Key.Escape) { 85 | this.success = false; 86 | Close(); 87 | } 88 | } 89 | 90 | public void AutoCompleteKeyDown(object sender, KeyEventArgs e) 91 | { 92 | KeyDownHandler(e); 93 | } 94 | 95 | public void DialogKeyDown(object sender, KeyEventArgs e) 96 | { 97 | KeyDownHandler(e); 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Views/TextInputDialog.axaml: -------------------------------------------------------------------------------- 1 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Views/TextInputDialog.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls; 3 | using Avalonia.Input; 4 | using Avalonia.Interactivity; 5 | using Avalonia.Markup.Xaml; 6 | using CommunityToolkit.Mvvm.Input; 7 | using StableDiffusionTagManager.Controls; 8 | using StableDiffusionTagManager.Views; 9 | using System.Threading.Tasks; 10 | 11 | namespace StableDiffusionTagManager; 12 | 13 | public partial class TextInputDialog : Window, IDialogWithResultAsync 14 | { 15 | public TextInputDialog() 16 | { 17 | InitializeComponent(); 18 | 19 | this.DataContext = this; 20 | Opened += TextInputDialog_Opened; 21 | } 22 | 23 | private bool success = false; 24 | 25 | private void TextInputDialog_Opened(object? sender, System.EventArgs e) 26 | { 27 | UserInputField.Focus(); 28 | } 29 | 30 | public async Task ShowWithResult(Window parent) 31 | { 32 | await ShowDialog(parent); 33 | 34 | if (this.success && !string.IsNullOrEmpty(UserInputField.Text)) 35 | { 36 | return UserInputField.Text; 37 | } 38 | else 39 | { 40 | return null; 41 | } 42 | } 43 | 44 | public void Cancel_Clicked(object sender, RoutedEventArgs e) 45 | { 46 | this.success = false; 47 | Close(); 48 | } 49 | 50 | public void Ok_Clicked(object sender, RoutedEventArgs e) 51 | { 52 | this.success = true; 53 | Close(); 54 | } 55 | 56 | public static readonly StyledProperty DialogTitleProperty = 57 | AvaloniaProperty.Register(nameof(DialogTitle), "Enter Text"); 58 | 59 | public string DialogTitle 60 | { 61 | get => GetValue(DialogTitleProperty); 62 | set => SetValue(DialogTitleProperty, value); 63 | } 64 | 65 | [RelayCommand] 66 | public void HeaderClose() 67 | { 68 | this.success = false; 69 | Close(); 70 | } 71 | 72 | private void KeyDownHandler(KeyEventArgs e) 73 | { 74 | if (e.Key == Key.Enter) 75 | { 76 | this.success = true; 77 | Close(); 78 | } 79 | if (e.Key == Key.Escape) 80 | { 81 | this.success = false; 82 | Close(); 83 | } 84 | } 85 | 86 | public void TextInputKeyDown(object sender, KeyEventArgs e) 87 | { 88 | KeyDownHandler(e); 89 | } 90 | 91 | public void DialogKeyDown(object sender, KeyEventArgs e) 92 | { 93 | KeyDownHandler(e); 94 | } 95 | } -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Views/YOLOModelSelectorDialog.axaml: -------------------------------------------------------------------------------- 1 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Views/YOLOModelSelectorDialog.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia.Controls; 2 | using CommunityToolkit.Mvvm.Input; 3 | using StableDiffusionTagManager.Controls; 4 | using StableDiffusionTagManager.ViewModels; 5 | using System.Threading.Tasks; 6 | 7 | namespace StableDiffusionTagManager; 8 | 9 | public partial class YOLOModelSelectorDialog : Window, IDialogWithResultAsync<(string modelPath, float threshold, int expandMask)?> 10 | { 11 | public bool Success { get; set; } = false; 12 | public (string modelPath, float threshold, int expandMask)? Result { get; set; } 13 | public async Task<(string modelPath, float threshold, int expandMask)?> ShowWithResult(Window parent) 14 | { 15 | await ShowDialog(parent); 16 | var viewModel = DataContext as YOLOModelSelectorDialogViewModel; 17 | if(viewModel != null && viewModel.SelectorViewModel.SelectedModel != null) 18 | { 19 | return Success ? (viewModel.SelectorViewModel.SelectedModel.Filename, viewModel.SelectorViewModel.Threshold, viewModel.SelectorViewModel.ExpandMask) : null; 20 | } 21 | return null; 22 | } 23 | 24 | public YOLOModelSelectorDialog() 25 | { 26 | InitializeComponent(); 27 | } 28 | 29 | private void GenerateClicked(object? sender, Avalonia.Interactivity.RoutedEventArgs e) 30 | { 31 | var viewModel = DataContext as YOLOModelSelectorDialogViewModel; 32 | if (viewModel != null && viewModel.SelectorViewModel?.SelectedModel != null) 33 | { 34 | Success = true; 35 | Close(); 36 | } 37 | } 38 | 39 | private void CancelClicked(object? sender, Avalonia.Interactivity.RoutedEventArgs e) 40 | { 41 | Close(); 42 | } 43 | } -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Views/YOLOModelSelectorView.axaml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/Views/YOLOModelSelectorView.axaml.cs: -------------------------------------------------------------------------------- 1 | using Avalonia; 2 | using Avalonia.Controls; 3 | using Avalonia.Markup.Xaml; 4 | 5 | namespace StableDiffusionTagManager; 6 | 7 | public partial class YOLOModelSelectorView : UserControl 8 | { 9 | public YOLOModelSelectorView() 10 | { 11 | InitializeComponent(); 12 | } 13 | } -------------------------------------------------------------------------------- /src/StableDiffusionTagManager/app.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 6 | 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/TagUtil/FolderTagSets.cs: -------------------------------------------------------------------------------- 1 | using System.Linq; 2 | 3 | namespace TagUtil 4 | { 5 | public class FolderTagSets 6 | { 7 | public FolderTagSets(string path) 8 | { 9 | //Ensure there's no jpgs or pngs with the same names 10 | var jpegs = Directory.EnumerateFiles(path, "*.jpg").ToList(); 11 | var pngs = Directory.EnumerateFiles(path, "*.png").ToList(); 12 | var jpegFilenames = jpegs.Select(f => Path.GetFileNameWithoutExtension(f)).ToHashSet(); 13 | var pngFilenames = pngs.Select(f => Path.GetFileNameWithoutExtension(f)).ToList(); 14 | 15 | //Check for the existence of a project folder 16 | var pairs = pngFilenames.Where(png => jpegFilenames.Contains(png)).ToList(); 17 | if(pairs.Any()) { 18 | var aggregated = pairs.Aggregate((l, r) => $"{l}, {r}"); 19 | throw new Exception($"There exists both a jpg and a png with the following filenames: {aggregated}."); 20 | } 21 | 22 | var jpegTagSets = jpegs.Select(jpeg => (ImageFile: jpeg, TagSet: new TagSet($"{path}/{Path.GetFileNameWithoutExtension(jpeg)}.txt"))); 23 | var pngTagSets = pngs.Select(png => (ImageFile: png, TagSet: new TagSet($"{path}/{Path.GetFileNameWithoutExtension(png)}.txt"))); 24 | 25 | //Load the tags 26 | TagsSets = jpegTagSets.Union(pngTagSets).ToList(); 27 | } 28 | 29 | public List<(string ImageFile, TagSet TagSet)> TagsSets { get; set; } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/TagUtil/ImageData.cs: -------------------------------------------------------------------------------- 1 | namespace TagUtil 2 | { 3 | public class ImageData 4 | { 5 | public string File { get; } 6 | 7 | public ImageData(string file) 8 | { 9 | File = file; 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/TagUtil/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace TagUtil 2 | { 3 | internal static class StringExtensions 4 | { 5 | public static List ExtractTags(this string _this) 6 | { 7 | return _this.Split(',').Select(s => s.Trim()).Distinct().Where(s => !string.IsNullOrWhiteSpace(s)).ToList(); 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/TagUtil/TagSet.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using System.Text.RegularExpressions; 3 | 4 | namespace TagUtil 5 | { 6 | public class TagSet 7 | { 8 | public List Tags { get; set; } 9 | public string? Description { get; set; } 10 | public string File { get; } 11 | 12 | public TagSet(string targetFile, string? description, IEnumerable tags) 13 | { 14 | File = targetFile; 15 | Tags = tags.ToList(); 16 | Description = description; 17 | } 18 | 19 | public TagSet(string file) 20 | { 21 | File = file; 22 | if (System.IO.File.Exists(file)) 23 | { 24 | var content = System.IO.File.ReadAllText(file); 25 | 26 | if (content != null) 27 | { 28 | content = content.Trim(); 29 | 30 | var chunks = Regex.Split(content, @"\r\n|\n"); 31 | 32 | var descriptionBuilder = new StringBuilder(); 33 | 34 | foreach (var chunk in chunks.Take(chunks.Length - 1)) 35 | { 36 | descriptionBuilder.AppendLine(chunk); 37 | } 38 | 39 | var lastChunk = chunks.Last(); 40 | var extractedTags = lastChunk.ExtractTags(); 41 | // If there's more than one comma per 25 characters and no upper case letters assume that the last chunk is tags. 42 | if (extractedTags.Count > (lastChunk.Length / 25) && !lastChunk.Any(c => char.IsUpper(c))) 43 | { 44 | Tags = extractedTags; 45 | } 46 | else 47 | { 48 | //Assume that the last chunk is more description. 49 | descriptionBuilder.AppendLine(lastChunk); 50 | Tags = new List(); 51 | } 52 | 53 | Description = descriptionBuilder.ToString().Trim(); 54 | } 55 | } 56 | else 57 | { 58 | Tags = new List(); 59 | } 60 | } 61 | 62 | public void WriteFile() 63 | { 64 | var output = new StringBuilder(); 65 | if (!string.IsNullOrWhiteSpace(Description) && (Tags?.Any() ?? false)) 66 | { 67 | output.AppendLine(Description); 68 | output.AppendLine(); 69 | output.AppendLine(Tags.Aggregate((l, r) => $"{l}, {r}")); 70 | } 71 | else if (!string.IsNullOrWhiteSpace(Description)) 72 | { 73 | output.AppendLine(Description); 74 | } 75 | else if (Tags?.Any() ?? false) 76 | { 77 | output.AppendLine(Tags.Aggregate((l, r) => $"{l}, {r}")); 78 | } 79 | if (output.Length > 0) 80 | System.IO.File.WriteAllText(File, output.ToString()); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/TagUtil/TagUtil.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | --------------------------------------------------------------------------------