From 80dc5c0635b4a4c9f874feca0c5ca7946476ba50 Mon Sep 17 00:00:00 2001 From: Ben Olden-Cooligan Date: Tue, 6 Feb 2024 20:22:36 -0800 Subject: [PATCH] Match thumbnail placeholders to background --- NAPS2.Images/Bitwise/FillColorImageOp.cs | 54 ++++++++++++++++++++++++ NAPS2.Lib/EtoForms/EtoExtensions.cs | 6 +++ NAPS2.Lib/Images/UiThumbnailProvider.cs | 5 ++- 3 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 NAPS2.Images/Bitwise/FillColorImageOp.cs diff --git a/NAPS2.Images/Bitwise/FillColorImageOp.cs b/NAPS2.Images/Bitwise/FillColorImageOp.cs new file mode 100644 index 000000000..04ae67c41 --- /dev/null +++ b/NAPS2.Images/Bitwise/FillColorImageOp.cs @@ -0,0 +1,54 @@ +namespace NAPS2.Images.Bitwise; + +public class FillColorImageOp : UnaryBitwiseImageOp +{ + private readonly byte _r, _g, _b, _a; + + public FillColorImageOp(byte r, byte g, byte b, byte a) + { + _r = r; + _g = g; + _b = b; + _a = a; + } + + protected override void PerformCore(BitwiseImageData data, int partStart, int partEnd) + { + if (data.bytesPerPixel is 1 or 3 or 4) + { + PerformRgba(data, partStart, partEnd); + } + else + { + throw new InvalidOperationException("Unsupported pixel format"); + } + } + + private unsafe void PerformRgba(BitwiseImageData data, int partStart, int partEnd) + { + bool gray = data.bytesPerPixel == 1; + byte luma = (byte) ((_r * R_MULT + _g * G_MULT + _b * B_MULT) / 1000); + for (int i = partStart; i < partEnd; i++) + { + var row = data.ptr + data.stride * i; + for (int j = 0; j < data.w; j++) + { + var pixel = row + j * data.bytesPerPixel; + if (gray) + { + *pixel = luma; + } + else + { + *(pixel + data.rOff) = _r; + *(pixel + data.gOff) = _g; + *(pixel + data.bOff) = _b; + } + if (data.hasAlpha) + { + *(pixel + data.aOff) = _a; + } + } + } + } +} \ No newline at end of file diff --git a/NAPS2.Lib/EtoForms/EtoExtensions.cs b/NAPS2.Lib/EtoForms/EtoExtensions.cs index 70537777e..7b5cbb90b 100644 --- a/NAPS2.Lib/EtoForms/EtoExtensions.cs +++ b/NAPS2.Lib/EtoForms/EtoExtensions.cs @@ -1,5 +1,6 @@ using Eto.Drawing; using Eto.Forms; +using NAPS2.Images.Bitwise; namespace NAPS2.EtoForms; @@ -40,4 +41,9 @@ public static class EtoExtensions { return checkBox.Checked == true; } + + public static void Fill(this IMemoryImage image, Color color) + { + new FillColorImageOp((byte) color.Rb, (byte) color.Gb, (byte) color.Bb, (byte) color.Ab).Perform(image); + } } \ No newline at end of file diff --git a/NAPS2.Lib/Images/UiThumbnailProvider.cs b/NAPS2.Lib/Images/UiThumbnailProvider.cs index 73726747f..bbdb7d3be 100644 --- a/NAPS2.Lib/Images/UiThumbnailProvider.cs +++ b/NAPS2.Lib/Images/UiThumbnailProvider.cs @@ -9,11 +9,13 @@ namespace NAPS2.Images; public class UiThumbnailProvider { private readonly ImageContext _imageContext; + private readonly ColorScheme _colorScheme; private IMemoryImage? _placeholder; - public UiThumbnailProvider(ImageContext imageContext) + public UiThumbnailProvider(ImageContext imageContext, ColorScheme colorScheme) { _imageContext = imageContext; + _colorScheme = colorScheme; } public IMemoryImage GetThumbnail(UiImage img, int thumbnailSize) @@ -43,6 +45,7 @@ public class UiThumbnailProvider } _placeholder?.Dispose(); _placeholder = _imageContext.Create(thumbnailSize, thumbnailSize, ImagePixelFormat.RGB24); + _placeholder.Fill(_colorScheme.BackgroundColor); _placeholder = EtoPlatform.Current.DrawHourglass(_imageContext, _placeholder); return _placeholder; }