mirror of https://github.com/SixLabors/ImageSharp
21 changed files with 285 additions and 277 deletions
@ -0,0 +1,115 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Buffers; |
|||
using System.Runtime.CompilerServices; |
|||
using SixLabors.ImageSharp.Memory; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
|
|||
namespace SixLabors.ImageSharp.Processing.Processors.Quantization |
|||
{ |
|||
/// <summary>
|
|||
/// A pixel-specific image frame where each pixel buffer value represents an index in a color palette.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
public sealed class IndexedImageFrame<TPixel> : IDisposable |
|||
where TPixel : unmanaged, IPixel<TPixel> |
|||
{ |
|||
private IMemoryOwner<byte> pixelsOwner; |
|||
private IMemoryOwner<TPixel> paletteOwner; |
|||
private bool isDisposed; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="IndexedImageFrame{TPixel}"/> class.
|
|||
/// </summary>
|
|||
/// <param name="configuration">
|
|||
/// The configuration which allows altering default behaviour or extending the library.
|
|||
/// </param>
|
|||
/// <param name="width">The frame width.</param>
|
|||
/// <param name="height">The frame height.</param>
|
|||
/// <param name="palette">The color palette.</param>
|
|||
internal IndexedImageFrame(Configuration configuration, int width, int height, ReadOnlyMemory<TPixel> palette) |
|||
{ |
|||
Guard.NotNull(configuration, nameof(configuration)); |
|||
Guard.MustBeGreaterThan(width, 0, nameof(width)); |
|||
Guard.MustBeGreaterThan(height, 0, nameof(height)); |
|||
|
|||
this.Configuration = configuration; |
|||
this.Width = width; |
|||
this.Height = height; |
|||
this.pixelsOwner = configuration.MemoryAllocator.AllocateManagedByteBuffer(width * height); |
|||
|
|||
// Copy the palette over. We want the lifetime of this frame to be independant of any palette source.
|
|||
this.paletteOwner = configuration.MemoryAllocator.Allocate<TPixel>(palette.Length); |
|||
palette.Span.CopyTo(this.paletteOwner.GetSpan()); |
|||
this.Palette = this.paletteOwner.Memory.Slice(0, palette.Length); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the configuration which allows altering default behaviour or extending the library.
|
|||
/// </summary>
|
|||
public Configuration Configuration { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the width of this <see cref="IndexedImageFrame{TPixel}"/>.
|
|||
/// </summary>
|
|||
public int Width { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the height of this <see cref="IndexedImageFrame{TPixel}"/>.
|
|||
/// </summary>
|
|||
public int Height { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the color palette of this <see cref="IndexedImageFrame{TPixel}"/>.
|
|||
/// </summary>
|
|||
public ReadOnlyMemory<TPixel> Palette { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the pixels of this <see cref="IndexedImageFrame{TPixel}"/>.
|
|||
/// </summary>
|
|||
/// <returns>The <see cref="ReadOnlySpan{T}"/></returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public ReadOnlySpan<byte> GetPixelBufferSpan() => this.pixelsOwner.GetSpan(); // TODO: Buffer2D<byte>
|
|||
|
|||
/// <summary>
|
|||
/// Gets the representation of the pixels as a <see cref="ReadOnlySpan{T}"/> of contiguous memory
|
|||
/// at row <paramref name="rowIndex"/> beginning from the the first pixel on that row.
|
|||
/// </summary>
|
|||
/// <param name="rowIndex">The row index in the pixel buffer.</param>
|
|||
/// <returns>The pixel row as a <see cref="ReadOnlySpan{T}"/>.</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public ReadOnlySpan<byte> GetPixelRowSpan(int rowIndex) |
|||
=> this.GetWritablePixelRowSpanUnsafe(rowIndex); |
|||
|
|||
/// <summary>
|
|||
/// <para>
|
|||
/// Gets the representation of the pixels as a <see cref="Span{T}"/> of contiguous memory
|
|||
/// at row <paramref name="rowIndex"/> beginning from the the first pixel on that row.
|
|||
/// </para>
|
|||
/// <para>
|
|||
/// Note: Values written to this span are not sanitized against the palette length.
|
|||
/// Care should be taken during assignment to prevent out-of-bounds errors.
|
|||
/// </para>
|
|||
/// </summary>
|
|||
/// <param name="rowIndex">The row index in the pixel buffer.</param>
|
|||
/// <returns>The pixel row as a <see cref="Span{T}"/>.</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public Span<byte> GetWritablePixelRowSpanUnsafe(int rowIndex) |
|||
=> this.pixelsOwner.GetSpan().Slice(rowIndex * this.Width, this.Width); |
|||
|
|||
/// <inheritdoc/>
|
|||
public void Dispose() |
|||
{ |
|||
if (!this.isDisposed) |
|||
{ |
|||
this.isDisposed = true; |
|||
this.pixelsOwner.Dispose(); |
|||
this.paletteOwner.Dispose(); |
|||
this.pixelsOwner = null; |
|||
this.paletteOwner = null; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,94 +0,0 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Buffers; |
|||
using System.Runtime.CompilerServices; |
|||
using SixLabors.ImageSharp.Memory; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
|
|||
namespace SixLabors.ImageSharp.Processing.Processors.Quantization |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a quantized image frame where the pixels indexed by a color palette.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
public sealed class QuantizedFrame<TPixel> : IDisposable |
|||
where TPixel : unmanaged, IPixel<TPixel> |
|||
{ |
|||
private IMemoryOwner<TPixel> palette; |
|||
private IMemoryOwner<byte> pixels; |
|||
private bool isDisposed; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="QuantizedFrame{TPixel}"/> class.
|
|||
/// </summary>
|
|||
/// <param name="memoryAllocator">Used to allocated memory for image processing operations.</param>
|
|||
/// <param name="width">The image width.</param>
|
|||
/// <param name="height">The image height.</param>
|
|||
/// <param name="palette">The color palette.</param>
|
|||
internal QuantizedFrame(MemoryAllocator memoryAllocator, int width, int height, ReadOnlySpan<TPixel> palette) |
|||
{ |
|||
Guard.MustBeGreaterThan(width, 0, nameof(width)); |
|||
Guard.MustBeGreaterThan(height, 0, nameof(height)); |
|||
|
|||
this.Width = width; |
|||
this.Height = height; |
|||
this.pixels = memoryAllocator.AllocateManagedByteBuffer(width * height, AllocationOptions.Clean); |
|||
|
|||
this.palette = memoryAllocator.Allocate<TPixel>(palette.Length); |
|||
palette.CopyTo(this.palette.GetSpan()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the width of this <see cref="QuantizedFrame{TPixel}"/>.
|
|||
/// </summary>
|
|||
public int Width { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the height of this <see cref="QuantizedFrame{TPixel}"/>.
|
|||
/// </summary>
|
|||
public int Height { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the color palette of this <see cref="QuantizedFrame{TPixel}"/>.
|
|||
/// </summary>
|
|||
public ReadOnlyMemory<TPixel> Palette |
|||
{ |
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
get { return this.palette.Memory; } |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the pixels of this <see cref="QuantizedFrame{TPixel}"/>.
|
|||
/// </summary>
|
|||
/// <returns>The <see cref="Span{T}"/></returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public Span<byte> GetPixelSpan() => this.pixels.GetSpan(); |
|||
|
|||
/// <summary>
|
|||
/// Gets the representation of the pixels as a <see cref="Span{T}"/> of contiguous memory
|
|||
/// at row <paramref name="rowIndex"/> beginning from the the first pixel on that row.
|
|||
/// </summary>
|
|||
/// <param name="rowIndex">The row.</param>
|
|||
/// <returns>The pixel row as a <see cref="Span{T}"/>.</returns>
|
|||
[MethodImpl(InliningOptions.ShortMethod)] |
|||
public Span<byte> GetPixelRowSpan(int rowIndex) |
|||
=> this.GetPixelSpan().Slice(rowIndex * this.Width, this.Width); |
|||
|
|||
/// <inheritdoc/>
|
|||
public void Dispose() |
|||
{ |
|||
if (!this.isDisposed) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
this.isDisposed = true; |
|||
this.pixels?.Dispose(); |
|||
this.palette?.Dispose(); |
|||
this.pixels = null; |
|||
this.palette = null; |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue