mirror of https://github.com/SixLabors/ImageSharp
Browse Source
Implementation of image.h and image.c; AC strategy implementation was slightly adjusted to reduce errors.pull/3153/head
17 changed files with 476 additions and 47 deletions
@ -1,12 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Buffers; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jxl.Memory; |
|||
|
|||
internal interface IJxlMemoryManager |
|||
{ |
|||
IMemoryOwner<T> Allocate<T>(int size); |
|||
IMemoryOwner<byte> Allocate(int size); |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jxl.Memory.ImageTypes; |
|||
|
|||
/// <summary>
|
|||
/// Represents a three-plane, 2D raster image of type <see cref="byte"/>.
|
|||
/// </summary>
|
|||
internal sealed class JxlImage3B : JxlImage3<byte> |
|||
{ |
|||
public JxlImage3B() |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jxl.Memory.ImageTypes; |
|||
|
|||
/// <summary>
|
|||
/// Represents a three-plane, 2D raster image of type <see cref="float"/>.
|
|||
/// </summary>
|
|||
internal sealed class JxlImage3F : JxlImage3<float> |
|||
{ |
|||
public JxlImage3F() |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jxl.Memory.ImageTypes; |
|||
|
|||
/// <summary>
|
|||
/// Represents a three-plane, 2D raster image of type <see cref="int"/>.
|
|||
/// </summary>
|
|||
internal sealed class JxlImage3I : JxlImage3<int> |
|||
{ |
|||
public JxlImage3I() |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jxl.Memory.ImageTypes; |
|||
|
|||
/// <summary>
|
|||
/// Represents a three-plane, 2D raster image of type <see cref="short"/>.
|
|||
/// </summary>
|
|||
internal sealed class JxlImage3S : JxlImage3<short> |
|||
{ |
|||
public JxlImage3S() |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jxl.Memory.ImageTypes; |
|||
|
|||
/// <summary>
|
|||
/// Represents a three-plane, 2D raster image of type <see cref="ushort"/>.
|
|||
/// </summary>
|
|||
internal sealed class JxlImage3U : JxlImage3<ushort> |
|||
{ |
|||
public JxlImage3U() |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,34 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Diagnostics; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jxl.Memory.ImageTypes; |
|||
|
|||
/// <summary>
|
|||
/// Represents a single-plane, 2D raster image of type <see cref="byte"/>.
|
|||
/// </summary>
|
|||
internal sealed class JxlImageB : JxlPlane<byte> |
|||
{ |
|||
public JxlImageB() |
|||
{ |
|||
} |
|||
|
|||
public JxlImageB(int width, int height) |
|||
: base(width, height) |
|||
{ |
|||
} |
|||
|
|||
public JxlImageB(Configuration configuration, int xSize, int ySize, int prePadding = 0) |
|||
: base(xSize, ySize) |
|||
=> this.Allocate(configuration, prePadding); |
|||
|
|||
public Memory<byte> GetRowBytesMemory(int y) |
|||
{ |
|||
Debug.Assert(y < this.YSize, "Attempted to access out-of-bounds Y coordinate"); |
|||
|
|||
Memory<byte> row = this.Bytes[(y * this.BytesPerRow)..]; |
|||
|
|||
return row; |
|||
} |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jxl.Memory.ImageTypes; |
|||
|
|||
/// <summary>
|
|||
/// Represents a single-plane, 2D raster image of type <see cref="float"/>.
|
|||
/// </summary>
|
|||
internal sealed class JxlImageF : JxlPlane<float> |
|||
{ |
|||
public JxlImageF() |
|||
{ |
|||
} |
|||
|
|||
public JxlImageF(int width, int height) |
|||
: base(width, height) |
|||
{ |
|||
} |
|||
|
|||
public JxlImageF(Configuration configuration, int xSize, int ySize, int prePadding = 0) |
|||
: base(xSize, ySize) |
|||
=> this.Allocate(configuration, prePadding); |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jxl.Memory.ImageTypes; |
|||
|
|||
/// <summary>
|
|||
/// Represents a single-plane, 2D raster image of type <see cref="int"/>.
|
|||
/// </summary>
|
|||
internal sealed class JxlImageI : JxlPlane<int> |
|||
{ |
|||
public JxlImageI() |
|||
{ |
|||
} |
|||
|
|||
public JxlImageI(int width, int height) |
|||
: base(width, height) |
|||
{ |
|||
} |
|||
|
|||
public JxlImageI(Configuration configuration, int xSize, int ySize, int prePadding = 0) |
|||
: base(xSize, ySize) |
|||
=> this.Allocate(configuration, prePadding); |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jxl.Memory.ImageTypes; |
|||
|
|||
/// <summary>
|
|||
/// Represents a single-plane, 2D raster image of type <see cref="short"/>.
|
|||
/// </summary>
|
|||
internal sealed class JxlImageS : JxlPlane<short> |
|||
{ |
|||
public JxlImageS() |
|||
{ |
|||
} |
|||
|
|||
public JxlImageS(int width, int height) |
|||
: base(width, height) |
|||
{ |
|||
} |
|||
|
|||
public JxlImageS(Configuration configuration, int xSize, int ySize, int prePadding = 0) |
|||
: base(xSize, ySize) |
|||
=> this.Allocate(configuration, prePadding); |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jxl.Memory.ImageTypes; |
|||
|
|||
/// <summary>
|
|||
/// Represents a single-plane, 2D raster image of type <see cref="sbyte"/>.
|
|||
/// </summary>
|
|||
internal sealed class JxlImageSB : JxlPlane<sbyte> |
|||
{ |
|||
public JxlImageSB() |
|||
{ |
|||
} |
|||
|
|||
public JxlImageSB(int width, int height) |
|||
: base(width, height) |
|||
{ |
|||
} |
|||
|
|||
public JxlImageSB(Configuration configuration, int xSize, int ySize, int prePadding = 0) |
|||
: base(xSize, ySize) |
|||
=> this.Allocate(configuration, prePadding); |
|||
} |
|||
@ -0,0 +1,23 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jxl.Memory.ImageTypes; |
|||
|
|||
/// <summary>
|
|||
/// Represents a single-plane, 2D raster image of type <see cref="ushort"/>.
|
|||
/// </summary>
|
|||
internal sealed class JxlImageU : JxlPlane<ushort> |
|||
{ |
|||
public JxlImageU() |
|||
{ |
|||
} |
|||
|
|||
public JxlImageU(int width, int height) |
|||
: base(width, height) |
|||
{ |
|||
} |
|||
|
|||
public JxlImageU(Configuration configuration, int xSize, int ySize, int prePadding = 0) |
|||
: base(xSize, ySize) |
|||
=> this.Allocate(configuration, prePadding); |
|||
} |
|||
@ -0,0 +1,85 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Diagnostics; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jxl.Memory; |
|||
|
|||
// NOTE: Do not seal this class.
|
|||
internal class JxlImage3<T> |
|||
where T : unmanaged |
|||
{ |
|||
private const int PlaneCount = 3; |
|||
|
|||
private JxlPlane<T>[] planes = new JxlPlane<T>[3]; |
|||
|
|||
public JxlImage3() |
|||
{ |
|||
} |
|||
|
|||
public JxlImage3(JxlImage3<T> other) |
|||
{ |
|||
for (int i = 0; i < PlaneCount; i++) |
|||
{ |
|||
this.planes[i] = other.planes[i]; |
|||
} |
|||
} |
|||
|
|||
public int XSize => this.planes[0].XSize; |
|||
|
|||
public int YSize => this.planes[0].YSize; |
|||
|
|||
public int BytesPerRow => this.planes[0].BytesPerRow; |
|||
|
|||
public int PixelsPerRow => this.planes[0].PixelsPerRow; |
|||
|
|||
public Span<T> PlaneRow(int plane, int row) |
|||
{ |
|||
this.PlaneRowBoundsCheck(plane, row); |
|||
|
|||
int rowOffset = row * this.planes[0].BytesPerRow; |
|||
Span<T> rowSpan = MemoryMarshal.Cast<byte, T>(this.planes[plane].BytesSpan[rowOffset..]); |
|||
|
|||
return rowSpan; |
|||
} |
|||
|
|||
public JxlPlane<T> Plane(int index) => this.planes[index]; |
|||
|
|||
public void Swap(JxlImage3<T> other) |
|||
{ |
|||
for (int i = 0; i < PlaneCount; i++) |
|||
{ |
|||
other.planes[i].Swap(this.planes[i]); |
|||
} |
|||
} |
|||
|
|||
public static JxlImage3<T> Create(Configuration configuration, int xSize, int ySize) |
|||
{ |
|||
JxlPlane<T> plane0 = JxlPlane<T>.Create(configuration, xSize, ySize); |
|||
JxlPlane<T> plane1 = JxlPlane<T>.Create(configuration, xSize, ySize); |
|||
JxlPlane<T> plane2 = JxlPlane<T>.Create(configuration, xSize, ySize); |
|||
|
|||
return new JxlImage3<T>() |
|||
{ |
|||
planes = [plane0, plane1, plane2] |
|||
}; |
|||
} |
|||
|
|||
public bool ShrinkTo(int x, int y) |
|||
{ |
|||
for (int i = 0; i < PlaneCount; i++) |
|||
{ |
|||
if (!this.planes[i].ShrinkTo(x, y)) |
|||
{ |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
[Conditional("DEBUG")] |
|||
private void PlaneRowBoundsCheck(int c, int y) => |
|||
Debug.Assert(c < PlaneCount && y < this.YSize, "The bounds check has failed"); |
|||
} |
|||
@ -1,18 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Buffers; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jxl.Memory; |
|||
|
|||
/// <summary>
|
|||
/// Allows allocation and deallocation of managed memory.
|
|||
/// </summary>
|
|||
internal sealed class JxlMemoryManager : IJxlMemoryManager |
|||
{ |
|||
public static readonly JxlMemoryManager Instance = new(); |
|||
|
|||
public IMemoryOwner<T> Allocate<T>(int size) => MemoryPool<T>.Shared.Rent(size); |
|||
|
|||
public IMemoryOwner<byte> Allocate(int size) => this.Allocate<byte>(size); |
|||
} |
|||
@ -0,0 +1,115 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using System.Buffers; |
|||
using System.Diagnostics; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jxl.Memory; |
|||
|
|||
// NOTE: Do not seal this type.
|
|||
internal class JxlPlaneBase : IDisposable |
|||
{ |
|||
private IMemoryOwner<byte>? bytes; |
|||
|
|||
public JxlPlaneBase(int xSize, int ySize, int sizeOfT) |
|||
{ |
|||
this.XSize = xSize; |
|||
this.YSize = ySize; |
|||
this.OriginalXSize = xSize; |
|||
this.OriginalYSize = ySize; |
|||
this.BytesPerRow = 0; |
|||
this.Size = sizeOfT; |
|||
} |
|||
|
|||
public JxlPlaneBase() |
|||
: this(0, 0, 0) |
|||
{ |
|||
} |
|||
|
|||
public int BytesPerRow { get; private set; } |
|||
|
|||
public int XSize { get; private set; } |
|||
|
|||
public int YSize { get; private set; } |
|||
|
|||
public Memory<byte> Bytes => |
|||
#if DEBUG
|
|||
this.bytes?.Memory ?? throw new InvalidOperationException("Bytes are missing"); |
|||
#else
|
|||
return this.bytes!.Memory; |
|||
#endif
|
|||
|
|||
public Span<byte> BytesSpan => this.Bytes.Span; |
|||
|
|||
protected int Size { get; set; } |
|||
|
|||
protected int OriginalXSize { get; set; } |
|||
|
|||
protected int OriginalYSize { get; set; } |
|||
|
|||
public bool Allocate(Configuration configuration, int prePadding) |
|||
{ |
|||
if (this.bytes != null || this.BytesPerRow != 0) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
if (this.XSize == 0 || this.YSize == 0) |
|||
{ |
|||
return true; |
|||
} |
|||
|
|||
int totalBytes = unchecked(this.YSize * this.BytesPerRow); |
|||
|
|||
this.bytes = configuration.MemoryAllocator.Allocate<byte>(totalBytes + (prePadding * this.Size)); |
|||
|
|||
return true; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool ShrinkTo(int x, int y) |
|||
{ |
|||
if (x <= this.OriginalXSize || y <= this.OriginalYSize) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
Debug.Assert(x <= this.OriginalXSize, "ShrinkTo cannot expand memory"); |
|||
Debug.Assert(y <= this.OriginalYSize, "ShrinkTo cannot expand memory"); |
|||
|
|||
this.XSize = x; |
|||
this.YSize = y; |
|||
|
|||
return true; |
|||
} |
|||
|
|||
protected Span<T> GetRowBase<T>(int y) |
|||
where T : unmanaged |
|||
{ |
|||
Debug.Assert(y < this.YSize, "Attempted to access out-of-bounds Y coordinate"); |
|||
|
|||
Span<byte> row = this.Bytes.Span[(y * this.BytesPerRow)..]; |
|||
|
|||
return MemoryMarshal.Cast<byte, T>(row); |
|||
} |
|||
|
|||
protected void SetBytes(IMemoryOwner<byte> bytes) => this.bytes = bytes; |
|||
|
|||
public void Swap(JxlPlaneBase other) |
|||
{ |
|||
(this.XSize, other.XSize) = (other.XSize, this.XSize); |
|||
(this.YSize, other.YSize) = (other.YSize, this.YSize); |
|||
(this.OriginalXSize, other.OriginalXSize) = (other.OriginalXSize, this.OriginalXSize); |
|||
(this.OriginalYSize, other.OriginalYSize) = (other.OriginalYSize, this.OriginalYSize); |
|||
(this.BytesPerRow, other.BytesPerRow) = (other.BytesPerRow, this.BytesPerRow); |
|||
(this.bytes, other.bytes) = (other.bytes, this.bytes); |
|||
} |
|||
|
|||
public void Dispose() |
|||
{ |
|||
this.bytes?.Dispose(); |
|||
GC.SuppressFinalize(this); |
|||
} |
|||
} |
|||
@ -0,0 +1,36 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
namespace SixLabors.ImageSharp.Formats.Jxl.Memory; |
|||
|
|||
// NOTE: Do not seal this class.
|
|||
internal class JxlPlane<T> : JxlPlaneBase |
|||
where T : unmanaged |
|||
{ |
|||
public JxlPlane() |
|||
{ |
|||
} |
|||
|
|||
public unsafe JxlPlane(int width, int height) |
|||
: base(width, height, sizeof(T)) |
|||
{ |
|||
} |
|||
|
|||
public unsafe int PixelsPerRow => this.BytesPerRow / sizeof(T); |
|||
|
|||
public static JxlPlane<T> Create(Configuration configuration, int xSize, int ySize, int prePadding = 0) |
|||
{ |
|||
JxlPlane<T> plane = new(xSize, ySize); |
|||
|
|||
bool allocated = plane.Allocate(configuration, prePadding); |
|||
|
|||
if (!allocated) |
|||
{ |
|||
throw new InvalidOperationException("Failed to allocate a JPEG XL plane"); |
|||
} |
|||
|
|||
return plane; |
|||
} |
|||
|
|||
public Span<T> GetRow(int y) => this.GetRowBase<T>(y); |
|||
} |
|||
Loading…
Reference in new issue