diff --git a/DataAccess/Data/BildInfoData.cs b/DataAccess/Data/BildInfoData.cs
index e2def08..643e28a 100644
--- a/DataAccess/Data/BildInfoData.cs
+++ b/DataAccess/Data/BildInfoData.cs
@@ -19,7 +19,7 @@ public class BildInfoData
/// Fügt die gegebene BildInfo zur Datenbank hinzu und aktualisiert das -Feld mit dem entsprechenden Wert.
///
/// Die BildInfo, die zur Datenbank hinzugefügt werden soll.
- public async Task AddBildInfoAsync(BildInfoModel bildInfo)
+ public async Task InsertBildInfoAsync(BildInfoModel bildInfo)
{
var id = await _db.LoadData("dbo.spBildInfo_Insert", bildInfo);
bildInfo.Id = id.Single();
diff --git a/KIKunstKirstenKlöckner/Data/ImageGenerator.cs b/KIKunstKirstenKlöckner/Data/ImageGenerator.cs
index f9e08c0..66ead66 100644
--- a/KIKunstKirstenKlöckner/Data/ImageGenerator.cs
+++ b/KIKunstKirstenKlöckner/Data/ImageGenerator.cs
@@ -10,8 +10,13 @@ public class ImageGenerator
private readonly HttpClient _client = new();
private readonly BildInfoData _bildInfoData;
+ private readonly IConfiguration _config;
+
+ private string ModelName => _config.GetValue("StableDiffusionModel") ?? "No Model Defined";
+
public ImageGenerator(IConfiguration config, BildInfoData bildInfoData)
{
+ _config = config;
_bildInfoData = bildInfoData;
string? inferenceApiKey = config.GetValue("API:HF_Inference");
@@ -21,13 +26,18 @@ public class ImageGenerator
}
///
- /// Geneiert das Bild für den aktuellen
+ /// Geneiert ein Bild für den gegebenen Wunsch.
///
- public async Task GenerateImageAsync(string prompt, string negativePromt, int? width, int? height, WunschInfoModel wunschInfo, bool isRetry = false)
+ /// Der Wunsch zu dem ein Bild generiert werden soll.
+ /// Die breite des zu generierenden Bildes. für Standardbreite des Modells
+ /// Die höhe des zu generierenden Bildes. für Standardhöhe des Modells
+ /// Begriffe, die explizit nicht generiert werden sollen.
+ /// Die BildInfo des generierten Bildes; oder null, wenn ein Fehler auftrat.
+ public async Task GenerateImageAsync(WunschInfoModel wunschInfo, int? width = null, int? height = null, string negativePromt = "")
{
var postData = new
{
- inputs = prompt,
+ inputs = wunschInfo.BildPrompt,
parameters = new
{
negative_prompt = negativePromt, //"photorealistic, highly detailed, 8K, portrait",
@@ -36,9 +46,11 @@ public class ImageGenerator
},
options = new
{
+ // https://huggingface.co/docs/api-inference/detailed_parameters
// Cache deaktivieren, damit Huggingface für den selben Prompt unterschiedliche Ergebnisse liefert
use_cache = false,
- // Erst wenn wir bereits in einem retry sind warten wir implizit auf das Model. (ignoriert quasi 503-Fehler)
+ // Ignoriert 503-Fehler. Diese treten auf wenn Hugging Face das Model noch nicht geladen hat.
+ // Mit true ignorieren wir den Fehler und schlagen erst fehl, wenn wir einen timeout haben.
wait_for_model = true
}
};
@@ -47,10 +59,7 @@ public class ImageGenerator
try
{
- //const string modelName = "Nacken/kkkk-sdxl-5000";
- const string modelName = "Nacken/kkk-sdxl-18000";
-
- var inferenceModelUrl = $"https://api-inference.huggingface.co/models/{modelName}";
+ var inferenceModelUrl = $"https://api-inference.huggingface.co/models/{ModelName}";
var response = await _client.PostAsync(inferenceModelUrl, content);
@@ -58,29 +67,20 @@ public class ImageGenerator
{
await using Stream imageStream = await response.Content.ReadAsStreamAsync();
- using Image image = await Image.LoadAsync(imageStream);
-
DateTime imageDate = DateTime.Now;
BildInfoModel bildInfo = new()
{
+ // Die tatsächliche Url wird in SaveImageStreamAsync gesetzt.
Dateiname = "PlaceHolder",
Datum = imageDate,
- ImageModel = modelName,
+ ImageModel = ModelName,
WunschId = wunschInfo.Id
};
-
- await _bildInfoData.AddBildInfoAsync(bildInfo);
- string imgUrl = $"generated_images/Image_{bildInfo.Id}.jpg";
+ await SaveImageStreamAsync(imageStream, bildInfo);
- string mapPath = $"./wwwroot/{imgUrl}";
- await image.SaveAsJpegAsync(mapPath);
-
- bildInfo.Dateiname = imgUrl;
- await _bildInfoData.UpdateBildInfoDateinameAsync(bildInfo);
-
- return imgUrl;
+ return bildInfo;
}
else
{
@@ -102,4 +102,26 @@ public class ImageGenerator
return null;
}
}
+
+ ///
+ /// Speichert den Inhalt des gegebenen Datenstroms als Bild ab.
+ ///
+ /// Der Datenstrom, der das Bild enthält.
+ /// Die BildInfo des Bildes. Der Dateiname wird nach dem Speichern aktualisiert.
+ private async Task SaveImageStreamAsync(Stream dataStream, BildInfoModel bildInfo)
+ {
+ using Image image = await Image.LoadAsync(dataStream);
+
+ // Speichert BildInfo in der Datenbank, aktualisiert Id der bildInfo
+ await _bildInfoData.InsertBildInfoAsync(bildInfo);
+
+ string imageUrl = $"generated_images/Image_{bildInfo.Id}.jpg";
+
+ string imageFilePath = $"./wwwroot/{imageUrl}";
+ await image.SaveAsJpegAsync(imageFilePath);
+
+ // Speichert den geänderten Dateinamen in der Datenbank
+ bildInfo.Dateiname = imageUrl;
+ await _bildInfoData.UpdateBildInfoDateinameAsync(bildInfo);
+ }
}
diff --git a/KIKunstKirstenKlöckner/Pages/AiArt.razor b/KIKunstKirstenKlöckner/Pages/AiArt.razor
index f066303..a29a320 100644
--- a/KIKunstKirstenKlöckner/Pages/AiArt.razor
+++ b/KIKunstKirstenKlöckner/Pages/AiArt.razor
@@ -305,7 +305,7 @@
// Vier Bilder generieren
for (int i = 0; i < 4; i++)
{
- _imageUrls[i] = await ImageGenerator.GenerateImageAsync(_imagePrompt, "", width, height, wunschInfo);
+ _imageUrls[i] = (await ImageGenerator.GenerateImageAsync(wunschInfo, width, height))?.Dateiname;
// Kein Bild -> Fehler
if (_imageUrls[i] == null)
@@ -317,12 +317,14 @@
if (retry == true)
{
- await ImageGenerator.GenerateImageAsync(_imagePrompt, "", width, height, wunschInfo);
+ _imageUrls[i] = (await ImageGenerator.GenerateImageAsync(wunschInfo, width, height))?.Dateiname;
}
}
- generatedImages++;
+ if (_imageUrls[i] != null)
+ generatedImages++;
+ // TODO: Fehler anzeigen
_imageStates[i] = ImageState.FadeIn;
await InvokeAsync(StateHasChanged);
}
diff --git a/KIKunstKirstenKlöckner/appsettings.json b/KIKunstKirstenKlöckner/appsettings.json
index 0d8c4f9..4935601 100644
--- a/KIKunstKirstenKlöckner/appsettings.json
+++ b/KIKunstKirstenKlöckner/appsettings.json
@@ -1,15 +1,16 @@
{
- "Logging": {
- "LogLevel": {
- "Default": "Information",
- "Microsoft.AspNetCore": "Warning"
- }
- },
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ },
"AllowedHosts": "*",
"API": {
"OpenAI": "",
"HF_Inference": ""
},
+ "StableDiffusionModel": "Nacken/kkk-sdxl-18000",
"ConnectionStrings": {
"Default": ""
}