From 66c5eecc260b67c433933d273f60102ee4f7e846 Mon Sep 17 00:00:00 2001 From: "H. Utku Maden" Date: Fri, 14 Nov 2025 22:31:54 +0300 Subject: [PATCH] Move StbImage to its own assembly. --- Dashboard.Common/Drawing/IImageLoader.cs | 61 ++++++++++++++++++++ Dashboard.StbImage/Dashboard.StbImage.csproj | 18 ++++++ Dashboard.StbImage/StbImageLoader.cs | 47 +++++++++++++++ Dashboard.sln | 8 +++ Dashboard/Controls/Form.cs | 1 - Dashboard/Dashboard.csproj | 4 -- tests/Dashboard.TestApplication/Program.cs | 23 +++----- 7 files changed, 143 insertions(+), 19 deletions(-) create mode 100644 Dashboard.Common/Drawing/IImageLoader.cs create mode 100644 Dashboard.StbImage/Dashboard.StbImage.csproj create mode 100644 Dashboard.StbImage/StbImageLoader.cs diff --git a/Dashboard.Common/Drawing/IImageLoader.cs b/Dashboard.Common/Drawing/IImageLoader.cs new file mode 100644 index 0000000..d769594 --- /dev/null +++ b/Dashboard.Common/Drawing/IImageLoader.cs @@ -0,0 +1,61 @@ +using Dashboard.Pal; + +namespace Dashboard.Drawing +{ + public record ImageData( + TextureType Type, + PixelFormat Format, + int Width, + int Height, + byte[] Bitmap) + { + public int Depth { get; init; } = 1; + public int Levels { get; init; } = 1; + public bool Premultiplied { get; init; } = false; + public int Alignment { get; init; } = 4; + + public long GetLevelOffset(int level) + { + ArgumentOutOfRangeException.ThrowIfLessThan(level, 0, nameof(level)); + ArgumentOutOfRangeException.ThrowIfGreaterThan(level, Levels, nameof(level)); + ArgumentOutOfRangeException.ThrowIfGreaterThan(level, Math.ILogB(Math.Max(Width, Height))); + + long offset = 0; + + long row = Width * Format switch + { + PixelFormat.R8I => 1, + PixelFormat.R16F => 2, + PixelFormat.Rg8I => 2, + PixelFormat.Rg16F => 4, + PixelFormat.Rgb8I => 3, + PixelFormat.Rgb16F => 6, + PixelFormat.Rgba8I => 4, + PixelFormat.Rgba16F => 8, + }; + + row += Alignment - (row % Alignment); + long plane = row * Height; + long volume = plane * Depth; + + for (int i = 0; i < level; i++) + { + if (Depth == 1) + { + offset += plane / (1 << i) / (1 << i); + } + else + { + offset += volume / (1 << i) / (1 << i) / (1 << i); + } + } + + return offset; + } + } + + public interface IImageLoader : IApplicationExtension + { + public ImageData LoadImageData(Stream stream); + } +} diff --git a/Dashboard.StbImage/Dashboard.StbImage.csproj b/Dashboard.StbImage/Dashboard.StbImage.csproj new file mode 100644 index 0000000..76eec2e --- /dev/null +++ b/Dashboard.StbImage/Dashboard.StbImage.csproj @@ -0,0 +1,18 @@ + + + + net8.0 + latest + enable + enable + + + + + + + + + + + diff --git a/Dashboard.StbImage/StbImageLoader.cs b/Dashboard.StbImage/StbImageLoader.cs new file mode 100644 index 0000000..fd573f6 --- /dev/null +++ b/Dashboard.StbImage/StbImageLoader.cs @@ -0,0 +1,47 @@ +using Dashboard.Drawing; +using Dashboard.Pal; +using ReFuel.Stb; + +namespace Dashboard.StbImage +{ + public class StbImageLoader : IImageLoader + { + public string DriverName { get; } = "Dashboard Stb Image Loader"; + public string DriverVendor { get; } = "Dashboard"; + public Version DriverVersion { get; } = new Version(1, 0); + + public void Dispose() + { + } + + IContextBase IContextExtensionBase.Context => Context; + + public void Require(Application context) + { + Context = context; + } + + public ImageData LoadImageData(Stream stream) + { + using ReFuel.Stb.StbImage image = ReFuel.Stb.StbImage.Load(stream, StbiImageFormat.Rgba); + ReadOnlySpan data = image.AsSpan(); + return new ImageData(TextureType.Texture2D, image.Format switch + { + StbiImageFormat.GreyAlpha => PixelFormat.Rg8I, + StbiImageFormat.Rgb => PixelFormat.Rgb8I, + StbiImageFormat.Rgba => PixelFormat.Rgba8I, + _ => PixelFormat.R8I, + }, + image.Width, + image.Height, + data.ToArray()); + } + + public Application Context { get; private set; } = null!; + + void IContextExtensionBase.Require(IContextBase context) + { + Require((Application)context); + } + } +} diff --git a/Dashboard.sln b/Dashboard.sln index 83febe3..ba0aedf 100644 --- a/Dashboard.sln +++ b/Dashboard.sln @@ -27,6 +27,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dashboard.OpenTK", "Dashboa EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dashboard.OpenGL", "Dashboard.OpenGL\Dashboard.OpenGL.csproj", "{33EB657C-B53A-41B4-BC3C-F38C09ABA577}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dashboard.StbImage", "Dashboard.StbImage\Dashboard.StbImage.csproj", "{85BCEB9E-DEC2-4A53-B2DA-6BFC6F3EE4E7}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -65,6 +67,11 @@ Global {33EB657C-B53A-41B4-BC3C-F38C09ABA577}.Debug|Any CPU.Build.0 = Debug|Any CPU {33EB657C-B53A-41B4-BC3C-F38C09ABA577}.Release|Any CPU.ActiveCfg = Release|Any CPU {33EB657C-B53A-41B4-BC3C-F38C09ABA577}.Release|Any CPU.Build.0 = Release|Any CPU + {85BCEB9E-DEC2-4A53-B2DA-6BFC6F3EE4E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {85BCEB9E-DEC2-4A53-B2DA-6BFC6F3EE4E7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {85BCEB9E-DEC2-4A53-B2DA-6BFC6F3EE4E7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {85BCEB9E-DEC2-4A53-B2DA-6BFC6F3EE4E7}.Release|Any CPU.Build.0 = Release|Any CPU + {14616F42-663B-4673-8561-5637FAD1B22F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -72,5 +79,6 @@ Global GlobalSection(NestedProjects) = preSolution {7C90B90B-DF31-439B-9080-CD805383B014} = {9D6CCC74-4DF3-47CB-B9B2-6BB75DF2BC40} {7B064228-2629-486E-95C6-BDDD4B4602C4} = {9B62A92D-ABF5-4704-B831-FD075515A82F} + {85BCEB9E-DEC2-4A53-B2DA-6BFC6F3EE4E7} = {9B62A92D-ABF5-4704-B831-FD075515A82F} EndGlobalSection EndGlobal diff --git a/Dashboard/Controls/Form.cs b/Dashboard/Controls/Form.cs index ff0e725..06c80ee 100644 --- a/Dashboard/Controls/Form.cs +++ b/Dashboard/Controls/Form.cs @@ -1,6 +1,5 @@ using System; using Dashboard.Drawing; -using Dashboard.Resources; using Dashboard.Windowing; namespace Dashboard.Controls diff --git a/Dashboard/Dashboard.csproj b/Dashboard/Dashboard.csproj index 66cde79..95aa9e2 100644 --- a/Dashboard/Dashboard.csproj +++ b/Dashboard/Dashboard.csproj @@ -12,8 +12,4 @@ - - - - diff --git a/tests/Dashboard.TestApplication/Program.cs b/tests/Dashboard.TestApplication/Program.cs index 630285b..2dba001 100644 --- a/tests/Dashboard.TestApplication/Program.cs +++ b/tests/Dashboard.TestApplication/Program.cs @@ -1,22 +1,16 @@ -using Dashboard.Drawing; -using System.Drawing; +using System.Drawing; using System.Text; -using Dashboard.Drawing.OpenGL; -using Dashboard.ImmediateUI; +using Dashboard.Controls; +using Dashboard.Drawing; +using Dashboard.Drawing.OpenGL.Pal; using Dashboard.OpenTK.PAL2; -using OpenTK.Platform; +using Dashboard.Pal; +using Dashboard.StbImage; using OpenTK.Graphics.OpenGL; using OpenTK.Mathematics; -using Box2d = Dashboard.Box2d; +using OpenTK.Platform; +using Image = Dashboard.Drawing.Image; using TK = OpenTK.Platform.Toolkit; -using Dashboard; -using Dashboard.Controls; -using Dashboard.Drawing.OpenGL.Pal; -using Dashboard.Pal; -using Dashboard.Windowing; -using OpenTK.Windowing.GraphicsLibraryFramework; -using ReFuel.Stb; -using Image = Dashboard.Resources.Image; using Vector4 = System.Numerics.Vector4; TK.Init(new ToolkitOptions() @@ -66,6 +60,7 @@ List points = new List(); StringBuilder builder = new StringBuilder(); app.Initialize(); +app.ExtensionRequire(); window = (PhysicalWindow)app.CreatePhysicalWindow();