From 7223d98e66be7830b7fae570a28e71c60087eacd Mon Sep 17 00:00:00 2001 From: winscripter <142818255+winscripter@users.noreply.github.com> Date: Fri, 17 Jul 2026 23:02:35 +0400 Subject: [PATCH] Add DCT memory, make JxlImage3 implement IDisposable --- .../Formats/Jxl/Memory/JxlImage3{T}.cs | 12 +++- .../Formats/Jxl/Processing/IJxlDctAcImage.cs | 68 +++++++++++++++++++ .../Jxl/Processing/JxlDctAcImage{T}.cs | 63 +++++++++++++++++ .../Formats/Jxl/Processing/JxlDctAcPointer.cs | 20 ++++++ .../Formats/Jxl/Processing/JxlDctAcType.cs | 20 ++++++ .../Jxl/Processing/JxlDctReadOnlyAcPointer.cs | 24 +++++++ 6 files changed, 206 insertions(+), 1 deletion(-) create mode 100644 src/ImageSharp/Formats/Jxl/Processing/IJxlDctAcImage.cs create mode 100644 src/ImageSharp/Formats/Jxl/Processing/JxlDctAcImage{T}.cs create mode 100644 src/ImageSharp/Formats/Jxl/Processing/JxlDctAcPointer.cs create mode 100644 src/ImageSharp/Formats/Jxl/Processing/JxlDctAcType.cs create mode 100644 src/ImageSharp/Formats/Jxl/Processing/JxlDctReadOnlyAcPointer.cs diff --git a/src/ImageSharp/Formats/Jxl/Memory/JxlImage3{T}.cs b/src/ImageSharp/Formats/Jxl/Memory/JxlImage3{T}.cs index f46f6767b..37707b7ba 100644 --- a/src/ImageSharp/Formats/Jxl/Memory/JxlImage3{T}.cs +++ b/src/ImageSharp/Formats/Jxl/Memory/JxlImage3{T}.cs @@ -7,7 +7,7 @@ using System.Runtime.InteropServices; namespace SixLabors.ImageSharp.Formats.Jxl.Memory; // NOTE: Do not seal this class. -internal class JxlImage3 +internal class JxlImage3 : IDisposable where T : unmanaged { private const int PlaneCount = 3; @@ -82,4 +82,14 @@ internal class JxlImage3 [Conditional("DEBUG")] private void PlaneRowBoundsCheck(int c, int y) => Debug.Assert(c < PlaneCount && y < this.YSize, "The bounds check has failed"); + + public void Dispose() + { + foreach (JxlPlane plane in this.planes) + { + plane.Dispose(); + } + + GC.SuppressFinalize(this); + } } diff --git a/src/ImageSharp/Formats/Jxl/Processing/IJxlDctAcImage.cs b/src/ImageSharp/Formats/Jxl/Processing/IJxlDctAcImage.cs new file mode 100644 index 000000000..30969824c --- /dev/null +++ b/src/ImageSharp/Formats/Jxl/Processing/IJxlDctAcImage.cs @@ -0,0 +1,68 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +namespace SixLabors.ImageSharp.Formats.Jxl.Processing; + +/// +/// Base DCT AC coefficient image +/// +internal interface IJxlDctAcImage +{ + /// + /// Gets the bit width of AC coefficients + /// + public JxlDctAcType Type { get; } + + /// + /// Gets the number of pixels per row. + /// + public int PixelsPerRow { get; } + + /// + /// Gets a value indicating whether the image is empty and doesn't + /// have anything within. + /// + public bool IsEmpty { get; } + + /// + /// Returns a reference to the coefficients at the specified row. + /// + /// The plane index (which channel). + /// The row index within plane specified by . + /// The X offset at the specified row. + /// + /// A reference to the coefficients inside the channel + /// specified by index , at index of + /// the row specified by , with X offset + /// specified by . + /// + public JxlDctAcPointer GetPlaneRow(int channel, int y, int xBase = 0); + + /// + /// Returns a reference to the coefficients at the specified row. + /// + /// The plane index (which channel). + /// The row index within plane specified by . + /// The X offset at the specified row. + /// + /// A reference to the coefficients inside the channel + /// specified by index , at index of + /// the row specified by , with X offset + /// specified by . + /// + /// + /// This is a read-only kind of . + /// + public JxlDctReadOnlyAcPointer GetReadOnlyPlaneRow(int channel, int y, int xBase = 0); + + /// + /// Fills all planes with zero. + /// + public void Clear(); + + /// + /// Fills everything within the specified plane with zero. + /// + /// Desired index of the plane. + public void Clear(int plane = 0); +} diff --git a/src/ImageSharp/Formats/Jxl/Processing/JxlDctAcImage{T}.cs b/src/ImageSharp/Formats/Jxl/Processing/JxlDctAcImage{T}.cs new file mode 100644 index 000000000..2052daee6 --- /dev/null +++ b/src/ImageSharp/Formats/Jxl/Processing/JxlDctAcImage{T}.cs @@ -0,0 +1,63 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +using SixLabors.ImageSharp.Formats.Jxl.Memory; + +namespace SixLabors.ImageSharp.Formats.Jxl.Processing; + +internal sealed class JxlDctAcImage : IJxlDctAcImage, IDisposable + where T : unmanaged +{ + private readonly JxlImage3 image; + + public unsafe JxlDctAcImage(Configuration configuration, int width, int height) + { + DebugGuard.IsTrue(sizeof(T) is 2 or 4, "The type must be 2 or 4 bytes"); + + this.image = JxlImage3.Create(configuration, width, height); + } + + public unsafe JxlDctAcType Type => sizeof(T) == 4 ? JxlDctAcType.Ac32 : JxlDctAcType.Ac16; + + public int PixelsPerRow => this.image.PixelsPerRow; + + public bool IsEmpty => this.image.XSize == 0 || this.image.YSize == 0; + + public void Clear() => JxlImageOperations.ClearImage(this.image); + + public void Clear(int plane = 0) => JxlImageOperations.ClearImage(this.image); + + public unsafe JxlDctAcPointer GetPlaneRow(int channel, int y, int xBase = 0) + { + if (sizeof(T) == 4) + { + Span span = (this.image as JxlImage3)!.PlaneRow(channel, y)[xBase..]; + return new JxlDctAcPointer() { Pointer32 = span }; + } + else + { + Span span = (this.image as JxlImage3)!.PlaneRow(channel, y)[xBase..]; + return new JxlDctAcPointer() { Pointer16 = span }; + } + } + + public unsafe JxlDctReadOnlyAcPointer GetReadOnlyPlaneRow(int channel, int y, int xBase = 0) + { + if (sizeof(T) == 4) + { + ReadOnlySpan span = (this.image as JxlImage3)!.PlaneRow(channel, y)[xBase..]; + return new JxlDctReadOnlyAcPointer(span); + } + else + { + ReadOnlySpan span = (this.image as JxlImage3)!.PlaneRow(channel, y)[xBase..]; + return new JxlDctReadOnlyAcPointer(span); + } + } + + public void Dispose() + { + this.image.Dispose(); + GC.SuppressFinalize(this); + } +} diff --git a/src/ImageSharp/Formats/Jxl/Processing/JxlDctAcPointer.cs b/src/ImageSharp/Formats/Jxl/Processing/JxlDctAcPointer.cs new file mode 100644 index 000000000..9710712d7 --- /dev/null +++ b/src/ImageSharp/Formats/Jxl/Processing/JxlDctAcPointer.cs @@ -0,0 +1,20 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +namespace SixLabors.ImageSharp.Formats.Jxl.Processing; + +/// +/// Pointer to DCT AC coefficients +/// +internal ref struct JxlDctAcPointer() +{ + /// + /// 16-bit pointer (if any) + /// + public Span Pointer16 = []; + + /// + /// 32-bit pointer (if any) + /// + public Span Pointer32 = []; +} diff --git a/src/ImageSharp/Formats/Jxl/Processing/JxlDctAcType.cs b/src/ImageSharp/Formats/Jxl/Processing/JxlDctAcType.cs new file mode 100644 index 000000000..a7e4ede67 --- /dev/null +++ b/src/ImageSharp/Formats/Jxl/Processing/JxlDctAcType.cs @@ -0,0 +1,20 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +namespace SixLabors.ImageSharp.Formats.Jxl.Processing; + +/// +/// Bit size for DCT AC coefficient +/// +internal enum JxlDctAcType : byte +{ + /// + /// 16-bit coefficient + /// + Ac16, + + /// + /// 32-bit coefficient + /// + Ac32 +} diff --git a/src/ImageSharp/Formats/Jxl/Processing/JxlDctReadOnlyAcPointer.cs b/src/ImageSharp/Formats/Jxl/Processing/JxlDctReadOnlyAcPointer.cs new file mode 100644 index 000000000..c80d8eaa6 --- /dev/null +++ b/src/ImageSharp/Formats/Jxl/Processing/JxlDctReadOnlyAcPointer.cs @@ -0,0 +1,24 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +namespace SixLabors.ImageSharp.Formats.Jxl.Processing; + +/// +/// Pointer to DCT AC coefficients. (Read-only) +/// +internal readonly ref struct JxlDctReadOnlyAcPointer +{ + /// + /// 16-bit pointer (if any) + /// + public readonly ReadOnlySpan Pointer16; + + /// + /// 32-bit pointer (if any) + /// + public readonly ReadOnlySpan Pointer32; + + internal JxlDctReadOnlyAcPointer(ReadOnlySpan pointer16) => this.Pointer16 = pointer16; + + internal JxlDctReadOnlyAcPointer(ReadOnlySpan pointer32) => this.Pointer32 = pointer32; +}