diff --git a/KIKunstKirstenKlöckner/Pages/AiArt.razor b/KIKunstKirstenKlöckner/Pages/AiArt.razor
index 7cff2e6..1bbb3b5 100644
--- a/KIKunstKirstenKlöckner/Pages/AiArt.razor
+++ b/KIKunstKirstenKlöckner/Pages/AiArt.razor
@@ -11,18 +11,6 @@
Wunschbilder von KI nur für dich
-@*
-
-
-
-*@
-
-
-@*
-*@
-
-@**@
-
Nenne uns deinen Wunsch:
@@ -72,6 +60,31 @@
await DoStuff(false))>Generate
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@code {
@@ -85,6 +98,17 @@
public string BusyMessage { get; set; } = "Initial Message";
+ private string?[] _imageUrls = new string?[4];
+ private ImageState[] _imageStates = new ImageState[4];
+
+ enum ImageState
+ {
+ //Hide = 0,
+ FadeOut,
+ FadeIn,
+ //Show,
+ }
+
// Busy dialog from markup
async Task ShowBusyDialog()
{
@@ -95,6 +119,14 @@
, new DialogOptions() { ShowTitle = false, Style = "min-height:auto;min-width:auto;width:auto", CloseDialogOnEsc = false });
}
+ async Task ShowImageDialog(string imageUrl)
+ {
+ var result = await DialogService.OpenAsync("", ds =>
+ @
+
+
, new DialogOptions() { CloseDialogOnOverlayClick = true });
+ }
+
// Busy dialog from string
async Task BusyDialog(string message)
{
@@ -258,9 +290,85 @@
}
}
+ ///
+ /// Geneiert das Bild für den aktuellen
+ ///
+ public async Task GenerateImageAsync(string prompt, bool isRetry = false)
+ {
+ var postData = new
+ {
+ inputs = prompt,
+ options = new
+ {
+ // 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)
+ wait_for_model = isRetry
+ }
+ };
+
+ JsonContent content = JsonContent.Create(postData);
+
+ async Task FailedToDrawImage()
+ {
+ bool? retry = await DialogService.Confirm("Leider konnte das Bild nicht gemalt werden. Möchtest du es noch eimal versuchen?", "Ups, ein Fehler ist aufgetreten...",
+ new ConfirmOptions { OkButtonText = "Ja", CancelButtonText = "Nein" });
+
+ if (retry == true)
+ {
+ return await GenerateImageAsync(prompt, true);
+ }
+
+ return null;
+ }
+
+ try
+ {
+ var inferenceModelUrl = "https://api-inference.huggingface.co/models/Nacken/ki-kunst-kirsten-kloeckner-colab";
+
+ var response = await _client.PostAsync(inferenceModelUrl, content);
+
+ if (response?.IsSuccessStatusCode == true)
+ {
+ await using Stream imageStream = await response.Content.ReadAsStreamAsync();
+
+ using Image image = await Image.LoadAsync(imageStream);
+
+ string imgUrl = $"generated_images/{DateTime.Now:dd_MM_yyyy_hh_mm_s_fffffff}.jpg";
+
+ string mapPath = $"./wwwroot/{imgUrl}";
+ await image.SaveAsJpegAsync(mapPath);
+
+ return imgUrl;
+ }
+ else
+ {
+ Console.WriteLine($"Image conversion failed: {response}");
+
+ if (Debugger.IsAttached)
+ Debugger.Break();
+
+ return await FailedToDrawImage();
+ }
+ }
+ catch (Exception exception)
+ {
+ Console.WriteLine($"Image request failed: {exception}");
+
+ if (Debugger.IsAttached)
+ Debugger.Break();
+
+ return await FailedToDrawImage();
+ }
+
+ return null;
+ }
private async Task DoStuff(bool newPic)
{
+ for (int i = 0; i < 4; i++)
+ _imageStates[i] = ImageState.FadeOut;
+
// Der Dialog blokiert so lange, wie der er offen ist, deshalb dürfen wir hier nicht warten, da wir sonst nie mit der Arbeit anfangen...
//Task busyDialog = ShowBusyDialog();
_progressVisible = true;
@@ -304,19 +412,14 @@
await UpdateBusyMessage("Kirstens Assistent hat eine Idee! Er wird sie nun malen...");
- Task makeImagesTask = GenerateImageAsync();
-
- //CancellationTokenSource cancelFunnyMessages = new CancellationTokenSource();
-
- //Task funnyMessagesTask = FunnyMessageSwitcher_ImageGen(cancelFunnyMessages.Token);
-
- // Wichtig, erst Bilder awaiten, dann die lustingen Sprüche, sonst warten wir ewig...
- await makeImagesTask;
-
- //cancelFunnyMessages.Cancel();
-
- //await funnyMessagesTask;
-
+ // Vier Bilder generieren
+ for (int i = 0; i < 4; i++)
+ {
+ _imageUrls[i] = await GenerateImageAsync(_imagePrompt);
+ _imageStates[i] = ImageState.FadeIn;
+ await InvokeAsync(StateHasChanged);
+ }
+
_progressVisible = false;
_buttonVisible = true;
if (amountOfAddons > 0)
@@ -333,3 +436,4 @@
}
}
+
diff --git a/KIKunstKirstenKlöckner/Pages/FlippingImage.razor b/KIKunstKirstenKlöckner/Pages/FlippingImage.razor
new file mode 100644
index 0000000..60c85c8
--- /dev/null
+++ b/KIKunstKirstenKlöckner/Pages/FlippingImage.razor
@@ -0,0 +1,162 @@
+
+
+
+
+@code {
+ [Parameter]
+ public bool Show { get; set; }
+
+ [Parameter]
+ public bool HideImage { get; set; }
+
+ [Parameter]
+ public string ImageUrl { get; set; } = "images/robot_painting.jpg";
+
+ public enum FlipDirection
+ {
+ Up,
+ Down,
+ Left,
+ Right
+ }
+
+ private string _flipperClassName;
+ private string _backClassName;
+ private FlipDirection _flipTo;
+
+ [Parameter]
+ public FlipDirection FlipTo
+ {
+ get => _flipTo;
+ set
+ {
+ _flipTo = value;
+ _flipperClassName = _flipTo switch
+ {
+ FlipDirection.Up => "flip-card_up",
+ FlipDirection.Down => "flip-card_down",
+ FlipDirection.Left => "flip-card_left",
+ FlipDirection.Right => "flip-card_right",
+ _ => throw new ArgumentOutOfRangeException()};
+ _backClassName = _flipTo switch
+ {
+ FlipDirection.Up => "flip-card-back_up",
+ FlipDirection.Down => "flip-card-back_down",
+ FlipDirection.Left => "flip-card-back_left",
+ FlipDirection.Right => "flip-card-back_right",
+ _ => throw new ArgumentOutOfRangeException()};
+ }
+ }
+
+ [Parameter]
+ public double FlipDelay { get; set; } = 0.0;
+
+ /// Gets or sets the click callback.
+ /// The click callback.
+ [Parameter]
+ public EventCallback Click { get; set; }
+}
diff --git a/KIKunstKirstenKlöckner/wwwroot/css/site.css b/KIKunstKirstenKlöckner/wwwroot/css/site.css
index 96b0583..7404feb 100644
--- a/KIKunstKirstenKlöckner/wwwroot/css/site.css
+++ b/KIKunstKirstenKlöckner/wwwroot/css/site.css
@@ -63,6 +63,56 @@ a, .btn-link {
color: white;
}
- .blazor-error-boundary::after {
- content: "An error has occurred."
+.blazor-error-boundary::after {
+ content: "An error has occurred."
+}
+
+.fade-in-5 {
+ animation: fadeIn 5s;
+ animation-fill-mode: forwards;
+}
+.fade-out-5 {
+ animation: fadeOut 5s;
+ animation-fill-mode: forwards;
+}
+
+
+@keyframes fadeIn {
+ 0% {
+ opacity: 0;
}
+
+ 100% {
+ opacity: 1;
+ }
+}
+
+@keyframes fadeOut {
+ 0% {
+ opacity: 1;
+ }
+
+ 100% {
+ opacity: 0;
+ }
+}
+
+.flip-image {
+ animation: flip 0.6s;
+ animation-fill-mode: forwards;
+ -webkit-backface-visibility: hidden;
+ transition: transform 0.6s;
+ transform-style: preserve-3d;
+ box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2);
+ backface-visibility: hidden;
+}
+
+@keyframes flip {
+ 0% {
+ transform: rotateY(0deg);
+ }
+
+ 100% {
+ transform: rotateY(180deg);
+ }
+}
diff --git a/KIKunstKirstenKlöckner/wwwroot/images/robot_painting.jpg b/KIKunstKirstenKlöckner/wwwroot/images/robot_painting.jpg
new file mode 100644
index 0000000..74a347e
Binary files /dev/null and b/KIKunstKirstenKlöckner/wwwroot/images/robot_painting.jpg differ