-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: Using SkiaSharp instead of SixLabors.ImageSharp
- Loading branch information
1 parent
5132654
commit 11f4aaa
Showing
11 changed files
with
207 additions
and
106 deletions.
There are no files selected for viewing
149 changes: 115 additions & 34 deletions
149
Luxoria.App/Luxoria.App/EventHandlers/CollectionUpdatedHandler.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,46 +1,127 @@ | ||
using Luxoria.Modules.Models.Events; | ||
using Luxoria.App.EventHandlers; | ||
using Luxoria.Modules.Models; | ||
using Luxoria.Modules.Models.Events; | ||
using Luxoria.Modules.Utils; | ||
using Luxoria.SDK.Interfaces; | ||
using Microsoft.UI.Xaml.Controls; | ||
using Microsoft.UI.Xaml.Media.Imaging; | ||
using System; | ||
using System.Diagnostics; | ||
using System.IO; | ||
using System.Linq; | ||
using Windows.UI.Notifications; | ||
using System.Threading.Tasks; | ||
using Windows.Graphics.Imaging; | ||
using Windows.Storage.Streams; | ||
|
||
namespace Luxoria.App.EventHandlers; | ||
|
||
/// <summary> | ||
/// Handles the CollectionUpdatedEvent. | ||
/// </summary> | ||
public class CollectionUpdatedHandler | ||
namespace Luxoria.App.EventHandlers | ||
{ | ||
/// <summary> | ||
/// The logger service. | ||
/// </summary> | ||
private readonly ILoggerService _loggerService; | ||
|
||
/// <summary> | ||
/// Constructor for the CollectionUpdatedHandler. | ||
/// </summary> | ||
/// <param name="loggerService"></param> | ||
public CollectionUpdatedHandler(ILoggerService loggerService) | ||
public class CollectionUpdatedHandler | ||
{ | ||
_loggerService = loggerService; | ||
} | ||
private readonly ILoggerService _loggerService; | ||
|
||
/// <summary> | ||
/// Handles the CollectionUpdatedEvent. | ||
/// </summary> | ||
public void OnCollectionUpdated(CollectionUpdatedEvent body) | ||
{ | ||
_loggerService.Log($"Collection updated: {body.CollectionName}"); | ||
_loggerService.Log($"Collection path: {body.CollectionPath}"); | ||
public CollectionUpdatedHandler(ILoggerService loggerService) | ||
{ | ||
_loggerService = loggerService; | ||
} | ||
|
||
// Handles the CollectionUpdatedEvent | ||
public async Task OnCollectionUpdated(CollectionUpdatedEvent body, Image imageControl) | ||
{ | ||
_loggerService.Log($"Collection updated: {body.CollectionName}"); | ||
_loggerService.Log($"Collection path: {body.CollectionPath}"); | ||
|
||
var toastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastText01); | ||
var textNodes = toastXml.GetElementsByTagName("text"); | ||
textNodes[0].AppendChild(toastXml.CreateTextNode($"Updated Collection: {body.CollectionName}")); | ||
var toast = new ToastNotification(toastXml); | ||
ToastNotificationManager.CreateToastNotifier("Luxoria").Show(toast); | ||
// Iterate over the assets and process each image | ||
for (int i = 0; i < body.Assets.Count; i++) | ||
{ | ||
var asset = body.Assets.ElementAt(i); | ||
_loggerService.Log($"Asset {i}: {asset.MetaData.Id}"); | ||
|
||
// Get the pixel data from the asset | ||
ReadOnlyMemory<byte> bitmap = asset.Data.PixelData; | ||
|
||
// Show basic info about the bitmap for debugging | ||
Debug.WriteLine($"Bitmap data length: {bitmap.Length} bytes"); | ||
Debug.WriteLine($"Bitmap width: {asset.Data.Width}"); | ||
Debug.WriteLine($"Bitmap height: {asset.Data.Height}"); | ||
|
||
try | ||
{ | ||
// Convert the byte array to SoftwareBitmap | ||
var softwareBitmap = ConvertToSoftwareBitmap(bitmap, asset.Data.Width, asset.Data.Height); | ||
|
||
// Convert SoftwareBitmap to BitmapImage (ImageSource compatible) | ||
BitmapImage bitmapImage = await ConvertToBitmapImage(softwareBitmap); | ||
|
||
// Set the BitmapImage as the source of the Image control | ||
imageControl.Source = bitmapImage; | ||
} | ||
catch (Exception ex) | ||
{ | ||
// Log the exception details for debugging | ||
_loggerService.Log($"Error processing asset {asset.MetaData.Id}: {ex.Message}"); | ||
Debug.WriteLine($"Error processing asset {asset.MetaData.Id}: {ex.StackTrace}"); | ||
} | ||
} | ||
} | ||
|
||
for (int i = 0; i < body.Assets.Count; i++) | ||
// Convert byte array (ReadOnlyMemory<byte>) to SoftwareBitmap | ||
private SoftwareBitmap ConvertToSoftwareBitmap(ReadOnlyMemory<byte> bitmap, int width, int height) | ||
{ | ||
_loggerService.Log($"Asset {i}: {body.Assets.ElementAt(i).MetaData.Id}"); | ||
try | ||
{ | ||
// Log first few bytes of the bitmap to verify if it contains valid image data (e.g., PNG or JPEG header) | ||
string bytePreview = BitConverter.ToString(bitmap.Span.Slice(0, 10).ToArray()); | ||
Debug.WriteLine($"First 10 bytes of image data: {bytePreview}"); | ||
|
||
// Create a stream to hold the pixel data | ||
var stream = new InMemoryRandomAccessStream(); | ||
var writer = new DataWriter(stream.GetOutputStreamAt(0)); | ||
|
||
// Write the byte data to the stream | ||
writer.WriteBytes(bitmap.Span.ToArray()); | ||
writer.StoreAsync().AsTask().Wait(); | ||
|
||
// Seek back to the beginning of the stream | ||
stream.Seek(0); | ||
|
||
// Create a BitmapDecoder to decode the byte data | ||
var decoder = BitmapDecoder.CreateAsync(stream).AsTask().Result; | ||
|
||
// Retrieve the SoftwareBitmap from the decoder | ||
return decoder.GetSoftwareBitmapAsync().AsTask().Result; | ||
} | ||
catch (Exception ex) | ||
{ | ||
Debug.WriteLine($"Error in ConvertToSoftwareBitmap: {ex.Message}"); | ||
throw new InvalidOperationException("Failed to convert byte array to SoftwareBitmap.", ex); | ||
} | ||
} | ||
|
||
|
||
// Convert SoftwareBitmap to BitmapImage (which is an ImageSource) | ||
private async Task<BitmapImage> ConvertToBitmapImage(SoftwareBitmap softwareBitmap) | ||
{ | ||
try | ||
{ | ||
var bitmapImage = new BitmapImage(); | ||
var stream = new InMemoryRandomAccessStream(); | ||
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream); | ||
|
||
// Encode the SoftwareBitmap into the stream | ||
encoder.SetSoftwareBitmap(softwareBitmap); | ||
await encoder.FlushAsync(); | ||
|
||
// Set the stream as the source for the BitmapImage | ||
stream.Seek(0); | ||
await bitmapImage.SetSourceAsync(stream); | ||
|
||
return bitmapImage; | ||
} | ||
catch (Exception ex) | ||
{ | ||
Debug.WriteLine($"Error in ConvertToBitmapImage: {ex.Message}"); | ||
throw new InvalidOperationException("Failed to convert SoftwareBitmap to BitmapImage.", ex); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,89 +1,79 @@ | ||
using Luxoria.Modules.Models; | ||
using Luxoria.Modules.Utils; | ||
using SixLabors.ImageSharp; | ||
using SixLabors.ImageSharp.PixelFormats; | ||
using SkiaSharp; | ||
using System; | ||
using System.IO; | ||
using System.Diagnostics; | ||
using Luxoria.Modules.Models; | ||
|
||
namespace LuxImport.Utils; | ||
|
||
public static class ImageDataHelper | ||
namespace LuxImport.Utils | ||
{ | ||
/// <summary> | ||
/// Load image data from a specified path | ||
/// </summary> | ||
/// <param name="path">The path to the image file</param> | ||
/// <returns>An ImageData object containing the loaded image's data</returns> | ||
public static ImageData LoadFromPath(string path) | ||
public static class ImageDataHelper | ||
{ | ||
// Check if the path is valid | ||
if (string.IsNullOrWhiteSpace(path)) | ||
{ | ||
throw new ArgumentException("Path cannot be null or empty.", nameof(path)); | ||
} | ||
|
||
if (!File.Exists(path)) | ||
{ | ||
throw new FileNotFoundException("The specified file does not exist.", path); | ||
} | ||
|
||
// Extract the file extension and validate it | ||
string extension = Path.GetExtension(path); | ||
FileExtension ext = FileExtensionHelper.ConvertToEnum(extension); | ||
if (ext == FileExtension.UNKNOWN) | ||
{ | ||
throw new NotSupportedException($"File format '{extension}' is not supported."); | ||
} | ||
|
||
try | ||
/// <summary> | ||
/// Load image data from a specified path and convert it into a byte array. | ||
/// </summary> | ||
/// <param name="path">The path to the image file.</param> | ||
/// <returns>An ImageData object containing the loaded image's data.</returns> | ||
public static ImageData LoadFromPath(string path) | ||
{ | ||
// Log the start of the image loading process | ||
Debug.WriteLine($"Attempting to load image from path: {path}"); | ||
|
||
// Read the file bytes | ||
byte[] fileBytes = File.ReadAllBytes(path); | ||
|
||
// Log file size for debugging purposes | ||
Debug.WriteLine($"Loaded {fileBytes.Length} bytes from {path}"); | ||
// Check if the path is valid | ||
if (string.IsNullOrWhiteSpace(path)) | ||
{ | ||
throw new ArgumentException("Path cannot be null or empty.", nameof(path)); | ||
} | ||
|
||
if (fileBytes.Length == 0) | ||
if (!File.Exists(path)) | ||
{ | ||
throw new InvalidOperationException($"The file at '{path}' is empty."); | ||
throw new FileNotFoundException("The specified file does not exist.", path); | ||
} | ||
|
||
// Load the image using ImageSharp | ||
using (MemoryStream memoryStream = new MemoryStream(fileBytes)) | ||
try | ||
{ | ||
using (Image<Rgba32> image = Image.Load<Rgba32>(memoryStream)) | ||
// Log the start of the image loading process | ||
Debug.WriteLine($"Attempting to load image from path: {path}"); | ||
|
||
// Load the image using SkiaSharp | ||
using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read)) | ||
{ | ||
// Check if the image is valid | ||
if (image == null) | ||
// Decode the image from the stream | ||
Debug.WriteLine("1/ Decoding the image using SkiaSharp..."); | ||
var skData = SKData.Create(stream); | ||
Debug.WriteLine("1.1/ SKData created successfully."); | ||
var skiaImage = SKBitmap.Decode(skData); // This will automatically detect the format | ||
Debug.WriteLine("2/ Image decoded successfully."); | ||
if (skiaImage == null) | ||
{ | ||
throw new InvalidOperationException($"Failed to decode image at path: {path}"); | ||
throw new InvalidOperationException($"Failed to decode the image at '{path}'."); | ||
} | ||
Debug.WriteLine($"Image dimensions: {skiaImage.Width}x{skiaImage.Height}"); | ||
// Convert the image to a byte array (PNG format) | ||
using (var memoryStream = new MemoryStream()) | ||
{ | ||
Debug.WriteLine("3/ Encoding the image as PNG..."); | ||
skiaImage.Encode(SKEncodedImageFormat.Png, 100).SaveTo(memoryStream); | ||
Debug.WriteLine("4/ Image encoded successfully."); | ||
Debug.WriteLine($"Image size: {memoryStream.Length} bytes"); | ||
byte[] imageBytes = memoryStream.ToArray(); | ||
Debug.WriteLine("5/ Image converted to byte array successfully."); | ||
|
||
// Log successful decoding for debugging purposes | ||
Debug.WriteLine($"Image decoded successfully. Width: {image.Width}, Height: {image.Height}"); | ||
|
||
// Directly access pixel data (in RGBA format) without extra encoding | ||
byte[] imageBytes = new byte[image.Width * image.Height * 4]; // RGBA32 = 4 bytes per pixel | ||
image.CopyPixelDataTo(imageBytes); // Copy the pixel data directly to the byte array | ||
|
||
// Create and return an ImageData object | ||
return new ImageData( | ||
imageBytes, | ||
image.Width, | ||
image.Height, | ||
ext | ||
); | ||
// Return an ImageData object with the necessary data | ||
return new ImageData( | ||
imageBytes, | ||
skiaImage.Width, | ||
skiaImage.Height, | ||
FileExtension.PNG//, | ||
//skiaImage // You can use SKBitmap for further manipulation or display | ||
); | ||
} | ||
} | ||
} | ||
} | ||
catch (Exception ex) | ||
{ | ||
// Log detailed error message and stack trace for troubleshooting | ||
Debug.WriteLine($"An error occurred while loading the image at '{path}': {ex.Message}"); | ||
Debug.WriteLine($"Stack Trace: {ex.StackTrace}"); | ||
throw new InvalidOperationException($"An error occurred while loading the image at '{path}': {ex.Message}", ex); | ||
catch (Exception ex) | ||
{ | ||
// Log detailed error message and stack trace for troubleshooting | ||
Debug.WriteLine($"An error occurred while loading the image at '{path}': {ex.Message}"); | ||
Debug.WriteLine($"Stack Trace: {ex.StackTrace}"); | ||
throw new InvalidOperationException($"An error occurred while loading the image at '{path}': {ex.Message}", ex); | ||
} | ||
} | ||
} | ||
} | ||
|
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes
File renamed without changes