|
|
|
@ -38,7 +38,9 @@ using InferenceTextToImageView = StabilityMatrix.Avalonia.Views.Inference.Infere
|
|
|
|
|
namespace StabilityMatrix.Avalonia.ViewModels.Inference; |
|
|
|
|
|
|
|
|
|
[View(typeof(InferenceTextToImageView), persistent: true)] |
|
|
|
|
public partial class InferenceTextToImageViewModel : InferenceTabViewModelBase |
|
|
|
|
public partial class InferenceTextToImageViewModel |
|
|
|
|
: InferenceTabViewModelBase, |
|
|
|
|
IImageGalleryComponent |
|
|
|
|
{ |
|
|
|
|
private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); |
|
|
|
|
|
|
|
|
@ -421,103 +423,100 @@ public partial class InferenceTextToImageViewModel : InferenceTabViewModelBase
|
|
|
|
|
notificationService.Show("No output", "Did not receive any output images"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
finally |
|
|
|
|
{ |
|
|
|
|
// Disconnect progress handler |
|
|
|
|
OutputProgress.Value = 0; |
|
|
|
|
OutputProgress.Text = ""; |
|
|
|
|
ImageGalleryCardViewModel.PreviewImage?.Dispose(); |
|
|
|
|
ImageGalleryCardViewModel.PreviewImage = null; |
|
|
|
|
ImageGalleryCardViewModel.IsPreviewOverlayEnabled = false; |
|
|
|
|
|
|
|
|
|
promptTask?.Dispose(); |
|
|
|
|
client.PreviewImageReceived -= OnPreviewImageReceived; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
List<ImageSource> outputImages; |
|
|
|
|
// Use local file path if available, otherwise use remote URL |
|
|
|
|
if (client.OutputImagesDir is { } outputPath) |
|
|
|
|
{ |
|
|
|
|
outputImages = new List<ImageSource>(); |
|
|
|
|
foreach (var image in images) |
|
|
|
|
{ |
|
|
|
|
var filePath = image.ToFilePath(outputPath); |
|
|
|
|
|
|
|
|
|
private async Task ProcessOutputs(IReadOnlyList<ComfyImage> images) |
|
|
|
|
{ |
|
|
|
|
List<ImageSource> outputImages; |
|
|
|
|
// Use local file path if available, otherwise use remote URL |
|
|
|
|
if (client.OutputImagesDir is { } outputPath) |
|
|
|
|
{ |
|
|
|
|
outputImages = new List<ImageSource>(); |
|
|
|
|
foreach (var image in images) |
|
|
|
|
var bytesWithMetadata = PngDataHelper.AddMetadata( |
|
|
|
|
await filePath.ReadAllBytesAsync(), |
|
|
|
|
generationInfo, |
|
|
|
|
smproj |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
/*await using (var readStream = filePath.Info.OpenWrite()) |
|
|
|
|
{ |
|
|
|
|
using (var reader = new BinaryReader(readStream)) |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
}*/ |
|
|
|
|
|
|
|
|
|
await using (var outputStream = filePath.Info.OpenWrite()) |
|
|
|
|
{ |
|
|
|
|
await outputStream.WriteAsync(bytesWithMetadata); |
|
|
|
|
await outputStream.FlushAsync(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
outputImages.Add(new ImageSource(filePath)); |
|
|
|
|
|
|
|
|
|
imageIndexService.OnImageAdded(filePath); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
var filePath = image.ToFilePath(outputPath); |
|
|
|
|
outputImages = images! |
|
|
|
|
.Select(i => new ImageSource(i.ToUri(client.BaseAddress))) |
|
|
|
|
.ToList(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var bytesWithMetadata = PngDataHelper.AddMetadata( |
|
|
|
|
await filePath.ReadAllBytesAsync(), |
|
|
|
|
// Download all images to make grid, if multiple |
|
|
|
|
if (outputImages.Count > 1) |
|
|
|
|
{ |
|
|
|
|
var loadedImages = outputImages |
|
|
|
|
.Select(i => SKImage.FromEncodedData(i.LocalFile?.Info.OpenRead())) |
|
|
|
|
.ToImmutableArray(); |
|
|
|
|
|
|
|
|
|
var grid = ImageProcessor.CreateImageGrid(loadedImages); |
|
|
|
|
var gridBytes = grid.Encode().ToArray(); |
|
|
|
|
var gridBytesWithMetadata = PngDataHelper.AddMetadata( |
|
|
|
|
gridBytes, |
|
|
|
|
generationInfo, |
|
|
|
|
smproj |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
/*await using (var readStream = filePath.Info.OpenWrite()) |
|
|
|
|
{ |
|
|
|
|
using (var reader = new BinaryReader(readStream)) |
|
|
|
|
{ |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
}*/ |
|
|
|
|
// Save to disk |
|
|
|
|
var lastName = outputImages.Last().LocalFile?.Info.Name; |
|
|
|
|
var gridPath = client.OutputImagesDir!.JoinFile($"grid-{lastName}"); |
|
|
|
|
|
|
|
|
|
await using (var outputStream = filePath.Info.OpenWrite()) |
|
|
|
|
await using (var fileStream = gridPath.Info.OpenWrite()) |
|
|
|
|
{ |
|
|
|
|
await outputStream.WriteAsync(bytesWithMetadata); |
|
|
|
|
await outputStream.FlushAsync(); |
|
|
|
|
await fileStream.WriteAsync(gridBytesWithMetadata, cancellationToken); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
outputImages.Add(new ImageSource(filePath)); |
|
|
|
|
// Insert to start of images |
|
|
|
|
var gridImage = new ImageSource(gridPath); |
|
|
|
|
// Preload |
|
|
|
|
await gridImage.GetBitmapAsync(); |
|
|
|
|
ImageGalleryCardViewModel.ImageSources.Add(gridImage); |
|
|
|
|
|
|
|
|
|
imageIndexService.OnImageAdded(filePath); |
|
|
|
|
imageIndexService.OnImageAdded(gridPath); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
outputImages = images! |
|
|
|
|
.Select(i => new ImageSource(i.ToUri(client.BaseAddress))) |
|
|
|
|
.ToList(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Download all images to make grid, if multiple |
|
|
|
|
if (outputImages.Count > 1) |
|
|
|
|
{ |
|
|
|
|
var loadedImages = outputImages |
|
|
|
|
.Select(i => SKImage.FromEncodedData(i.LocalFile?.Info.OpenRead())) |
|
|
|
|
.ToImmutableArray(); |
|
|
|
|
|
|
|
|
|
var grid = ImageProcessor.CreateImageGrid(loadedImages); |
|
|
|
|
var gridBytes = grid.Encode().ToArray(); |
|
|
|
|
var gridBytesWithMetadata = PngDataHelper.AddMetadata( |
|
|
|
|
gridBytes, |
|
|
|
|
generationInfo, |
|
|
|
|
smproj |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
// Save to disk |
|
|
|
|
var lastName = outputImages.Last().LocalFile?.Info.Name; |
|
|
|
|
var gridPath = client.OutputImagesDir!.JoinFile($"grid-{lastName}"); |
|
|
|
|
|
|
|
|
|
await using (var fileStream = gridPath.Info.OpenWrite()) |
|
|
|
|
// Add rest of images |
|
|
|
|
foreach (var img in outputImages) |
|
|
|
|
{ |
|
|
|
|
await fileStream.WriteAsync(gridBytesWithMetadata, cancellationToken); |
|
|
|
|
// Preload |
|
|
|
|
await img.GetBitmapAsync(); |
|
|
|
|
ImageGalleryCardViewModel.ImageSources.Add(img); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Insert to start of images |
|
|
|
|
var gridImage = new ImageSource(gridPath); |
|
|
|
|
// Preload |
|
|
|
|
await gridImage.GetBitmapAsync(); |
|
|
|
|
ImageGalleryCardViewModel.ImageSources.Add(gridImage); |
|
|
|
|
|
|
|
|
|
imageIndexService.OnImageAdded(gridPath); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Add rest of images |
|
|
|
|
foreach (var img in outputImages) |
|
|
|
|
finally |
|
|
|
|
{ |
|
|
|
|
// Preload |
|
|
|
|
await img.GetBitmapAsync(); |
|
|
|
|
ImageGalleryCardViewModel.ImageSources.Add(img); |
|
|
|
|
// Disconnect progress handler |
|
|
|
|
OutputProgress.Value = 0; |
|
|
|
|
OutputProgress.Text = ""; |
|
|
|
|
ImageGalleryCardViewModel.PreviewImage?.Dispose(); |
|
|
|
|
ImageGalleryCardViewModel.PreviewImage = null; |
|
|
|
|
ImageGalleryCardViewModel.IsPreviewOverlayEnabled = false; |
|
|
|
|
|
|
|
|
|
promptTask?.Dispose(); |
|
|
|
|
client.PreviewImageReceived -= OnPreviewImageReceived; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|