Browse Source

Correct readonly-semantics for QuantizedFrame

af/merge-core
Anton Firszov 7 years ago
parent
commit
63ffdcb18f
  1. 2
      src/ImageSharp/Advanced/AotCompilerTools.cs
  2. 2
      src/ImageSharp/Formats/Gif/GifEncoderCore.cs
  3. 6
      src/ImageSharp/Formats/Gif/LzwEncoder.cs
  4. 2
      src/ImageSharp/Formats/Png/PngEncoderCore.cs
  5. 7
      src/ImageSharp/Processing/Processors/Quantization/FrameQuantizer{TPixel}.cs
  6. 2
      src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs
  7. 11
      src/ImageSharp/Processing/Processors/Quantization/QuantizedFrame{TPixel}.cs
  8. 26
      src/ImageSharp/Processing/Processors/Quantization/WuFrameQuantizer{TPixel}.cs
  9. 8
      src/ImageSharp/Processing/Processors/Quantization/WuQuantizer.cs

2
src/ImageSharp/Advanced/AotCompilerTools.cs

@ -104,7 +104,7 @@ namespace SixLabors.ImageSharp.Advanced
private static void AotCompileWuQuantizer<TPixel>() private static void AotCompileWuQuantizer<TPixel>()
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
var test = new WuFrameQuantizer<TPixel>(new WuQuantizer(false)); var test = new WuFrameQuantizer<TPixel>(Configuration.Default.MemoryAllocator, new WuQuantizer(false));
test.QuantizeFrame(new ImageFrame<TPixel>(Configuration.Default, 1, 1)); test.QuantizeFrame(new ImageFrame<TPixel>(Configuration.Default, 1, 1));
test.AotGetPalette(); test.AotGetPalette();
} }

2
src/ImageSharp/Formats/Gif/GifEncoderCore.cs

@ -164,7 +164,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
using (QuantizedFrame<TPixel> paletteQuantized = palleteFrameQuantizer.QuantizeFrame(frame)) using (QuantizedFrame<TPixel> paletteQuantized = palleteFrameQuantizer.QuantizeFrame(frame))
{ {
this.WriteImageData(paletteQuantized, stream); this.WriteImageData(paletteQuantized, stream);
} }
} }
} }
} }

6
src/ImageSharp/Formats/Gif/LzwEncoder.cs

@ -180,7 +180,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// </summary> /// </summary>
/// <param name="indexedPixels">The span of indexed pixels.</param> /// <param name="indexedPixels">The span of indexed pixels.</param>
/// <param name="stream">The stream to write to.</param> /// <param name="stream">The stream to write to.</param>
public void Encode(Span<byte> indexedPixels, Stream stream) public void Encode(ReadOnlySpan<byte> indexedPixels, Stream stream)
{ {
// Write "initial code size" byte // Write "initial code size" byte
stream.WriteByte((byte)this.initialCodeSize); stream.WriteByte((byte)this.initialCodeSize);
@ -251,7 +251,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// <param name="indexedPixels">The span of indexed pixels.</param> /// <param name="indexedPixels">The span of indexed pixels.</param>
/// <param name="intialBits">The initial bits.</param> /// <param name="intialBits">The initial bits.</param>
/// <param name="stream">The stream to write to.</param> /// <param name="stream">The stream to write to.</param>
private void Compress(Span<byte> indexedPixels, int intialBits, Stream stream) private void Compress(ReadOnlySpan<byte> indexedPixels, int intialBits, Stream stream)
{ {
int fcode; int fcode;
int c; int c;
@ -375,7 +375,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// The <see cref="int"/> /// The <see cref="int"/>
/// </returns> /// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private int NextPixel(Span<byte> indexedPixels) private int NextPixel(ReadOnlySpan<byte> indexedPixels)
{ {
return indexedPixels[this.position++] & 0xFF; return indexedPixels[this.position++] & 0xFF;
} }

2
src/ImageSharp/Formats/Png/PngEncoderCore.cs

@ -676,7 +676,7 @@ namespace SixLabors.ImageSharp.Formats.Png
{ {
ref byte colorTableRef = ref MemoryMarshal.GetReference(colorTable.GetSpan()); ref byte colorTableRef = ref MemoryMarshal.GetReference(colorTable.GetSpan());
ref byte alphaTableRef = ref MemoryMarshal.GetReference(alphaTable.GetSpan()); ref byte alphaTableRef = ref MemoryMarshal.GetReference(alphaTable.GetSpan());
Span<byte> quantizedSpan = quantized.GetPixelSpan(); ReadOnlySpan<byte> quantizedSpan = quantized.GetPixelSpan();
Rgba32 rgba = default; Rgba32 rgba = default;

7
src/ImageSharp/Processing/Processors/Quantization/FrameQuantizer{TPixel}.cs

@ -85,7 +85,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
} }
/// <inheritdoc/> /// <inheritdoc/>
public virtual QuantizedFrame<TPixel> QuantizeFrame(ImageFrame<TPixel> image) public QuantizedFrame<TPixel> QuantizeFrame(ImageFrame<TPixel> image)
{ {
Guard.NotNull(image, nameof(image)); Guard.NotNull(image, nameof(image));
@ -112,17 +112,18 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
var quantizedFrame = new QuantizedFrame<TPixel>(image.MemoryAllocator, width, height, palette); var quantizedFrame = new QuantizedFrame<TPixel>(image.MemoryAllocator, width, height, palette);
Span<byte> pixelSpan = quantizedFrame.GetWritablePixelSpan();
if (this.Dither) if (this.Dither)
{ {
// We clone the image as we don't want to alter the original via dithering. // We clone the image as we don't want to alter the original via dithering.
using (ImageFrame<TPixel> clone = image.Clone()) using (ImageFrame<TPixel> clone = image.Clone())
{ {
this.SecondPass(clone, quantizedFrame.GetPixelSpan(), palette.Span, width, height); this.SecondPass(clone, pixelSpan, palette.Span, width, height);
} }
} }
else else
{ {
this.SecondPass(image, quantizedFrame.GetPixelSpan(), palette.Span, width, height); this.SecondPass(image, pixelSpan, palette.Span, width, height);
} }
return quantizedFrame; return quantizedFrame;

2
src/ImageSharp/Processing/Processors/Quantization/QuantizeProcessor{TPixel}.cs

@ -45,7 +45,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
ReadOnlySpan<byte> quantizedPixelSpan = quantized.GetPixelSpan(); ReadOnlySpan<byte> quantizedPixelSpan = quantized.GetPixelSpan();
ReadOnlySpan<TPixel> paletteSpan = quantized.Palette.Span; ReadOnlySpan<TPixel> paletteSpan = quantized.Palette.Span;
int yy = y * source.Width; int yy = y * source.Width;
for (int x = 0; x < source.Width; x++) for (int x = 0; x < source.Width; x++)

11
src/ImageSharp/Processing/Processors/Quantization/QuantizedFrame{TPixel}.cs

@ -27,7 +27,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// <param name="width">The image width.</param> /// <param name="width">The image width.</param>
/// <param name="height">The image height.</param> /// <param name="height">The image height.</param>
/// <param name="palette">The color palette.</param> /// <param name="palette">The color palette.</param>
public QuantizedFrame(MemoryAllocator memoryAllocator, int width, int height, ReadOnlyMemory<TPixel> palette) internal QuantizedFrame(MemoryAllocator memoryAllocator, int width, int height, ReadOnlyMemory<TPixel> palette)
{ {
Guard.MustBeGreaterThan(width, 0, nameof(width)); Guard.MustBeGreaterThan(width, 0, nameof(width));
Guard.MustBeGreaterThan(height, 0, nameof(height)); Guard.MustBeGreaterThan(height, 0, nameof(height));
@ -58,7 +58,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// </summary> /// </summary>
/// <returns>The <see cref="Span{T}"/></returns> /// <returns>The <see cref="Span{T}"/></returns>
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public Span<byte> GetPixelSpan() => this.pixels.GetSpan(); public ReadOnlySpan<byte> GetPixelSpan() => this.pixels.GetSpan();
/// <summary> /// <summary>
/// Gets the representation of the pixels as a <see cref="Span{T}"/> of contiguous memory /// Gets the representation of the pixels as a <see cref="Span{T}"/> of contiguous memory
@ -67,7 +67,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// <param name="rowIndex">The row.</param> /// <param name="rowIndex">The row.</param>
/// <returns>The <see cref="Span{T}"/></returns> /// <returns>The <see cref="Span{T}"/></returns>
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(InliningOptions.ShortMethod)]
public Span<byte> GetRowSpan(int rowIndex) => this.GetPixelSpan().Slice(rowIndex * this.Width, this.Width); public ReadOnlySpan<byte> GetRowSpan(int rowIndex) => this.GetPixelSpan().Slice(rowIndex * this.Width, this.Width);
/// <inheritdoc/> /// <inheritdoc/>
public void Dispose() public void Dispose()
@ -76,5 +76,10 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
this.pixels = null; this.pixels = null;
this.Palette = null; this.Palette = null;
} }
/// <summary>
/// Get the non-readonly span of pixel data so <see cref="FrameQuantizer{TPixel}"/> can fill it.
/// </summary>
internal Span<byte> GetWritablePixelSpan() => this.pixels.GetSpan();
} }
} }

26
src/ImageSharp/Processing/Processors/Quantization/WuFrameQuantizer{TPixel}.cs

@ -120,33 +120,31 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="WuFrameQuantizer{TPixel}"/> class. /// Initializes a new instance of the <see cref="WuFrameQuantizer{TPixel}"/> class.
/// </summary> /// </summary>
/// <param name="memoryAllocator">The <see cref="MemoryAllocator"/>.</param>
/// <param name="quantizer">The wu quantizer</param> /// <param name="quantizer">The wu quantizer</param>
/// <remarks> /// <remarks>
/// The Wu quantizer is a two pass algorithm. The initial pass sets up the 3-D color histogram, /// The Wu quantizer is a two pass algorithm. The initial pass sets up the 3-D color histogram,
/// the second pass quantizes a color based on the position in the histogram. /// the second pass quantizes a color based on the position in the histogram.
/// </remarks> /// </remarks>
public WuFrameQuantizer(WuQuantizer quantizer) public WuFrameQuantizer(MemoryAllocator memoryAllocator, WuQuantizer quantizer)
: this(quantizer, quantizer.MaxColors) : this(memoryAllocator, quantizer, quantizer.MaxColors)
{ {
} }
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="WuFrameQuantizer{TPixel}"/> class. /// Initializes a new instance of the <see cref="WuFrameQuantizer{TPixel}"/> class.
/// </summary> /// </summary>
/// <param name="memoryAllocator">The <see cref="MemoryAllocator"/>.</param>
/// <param name="quantizer">The wu quantizer.</param> /// <param name="quantizer">The wu quantizer.</param>
/// <param name="maxColors">The maximum number of colors to hold in the color palette.</param> /// <param name="maxColors">The maximum number of colors to hold in the color palette.</param>
/// <remarks> /// <remarks>
/// The Wu quantizer is a two pass algorithm. The initial pass sets up the 3-D color histogram, /// The Wu quantizer is a two pass algorithm. The initial pass sets up the 3-D color histogram,
/// the second pass quantizes a color based on the position in the histogram. /// the second pass quantizes a color based on the position in the histogram.
/// </remarks> /// </remarks>
public WuFrameQuantizer(WuQuantizer quantizer, int maxColors) public WuFrameQuantizer(MemoryAllocator memoryAllocator, WuQuantizer quantizer, int maxColors)
: base(quantizer, false) => this.colors = maxColors; : base(quantizer, false)
/// <inheritdoc/>
public override QuantizedFrame<TPixel> QuantizeFrame(ImageFrame<TPixel> image)
{ {
Guard.NotNull(image, nameof(image)); Guard.NotNull(memoryAllocator, nameof(memoryAllocator));
MemoryAllocator memoryAllocator = image.MemoryAllocator;
this.vwt = memoryAllocator.Allocate<long>(TableLength, AllocationOptions.Clean); this.vwt = memoryAllocator.Allocate<long>(TableLength, AllocationOptions.Clean);
this.vmr = memoryAllocator.Allocate<long>(TableLength, AllocationOptions.Clean); this.vmr = memoryAllocator.Allocate<long>(TableLength, AllocationOptions.Clean);
@ -156,7 +154,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
this.m2 = memoryAllocator.Allocate<double>(TableLength, AllocationOptions.Clean); this.m2 = memoryAllocator.Allocate<double>(TableLength, AllocationOptions.Clean);
this.tag = memoryAllocator.Allocate<byte>(TableLength, AllocationOptions.Clean); this.tag = memoryAllocator.Allocate<byte>(TableLength, AllocationOptions.Clean);
return base.QuantizeFrame(image); this.colors = maxColors;
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -169,6 +167,14 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
this.vma?.Dispose(); this.vma?.Dispose();
this.m2?.Dispose(); this.m2?.Dispose();
this.tag?.Dispose(); this.tag?.Dispose();
this.vwt = null;
this.vmr = null;
this.vmg = null;
this.vmb = null;
this.vma = null;
this.m2 = null;
this.tag = null;
} }
internal ReadOnlyMemory<TPixel> AotGetPalette() => this.GetPalette(); internal ReadOnlyMemory<TPixel> AotGetPalette() => this.GetPalette();

8
src/ImageSharp/Processing/Processors/Quantization/WuQuantizer.cs

@ -72,14 +72,18 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// <inheritdoc /> /// <inheritdoc />
public IFrameQuantizer<TPixel> CreateFrameQuantizer<TPixel>(Configuration configuration) public IFrameQuantizer<TPixel> CreateFrameQuantizer<TPixel>(Configuration configuration)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
=> new WuFrameQuantizer<TPixel>(this); {
Guard.NotNull(configuration, nameof(configuration));
return new WuFrameQuantizer<TPixel>(configuration.MemoryAllocator, this);
}
/// <inheritdoc/> /// <inheritdoc/>
public IFrameQuantizer<TPixel> CreateFrameQuantizer<TPixel>(Configuration configuration, int maxColors) public IFrameQuantizer<TPixel> CreateFrameQuantizer<TPixel>(Configuration configuration, int maxColors)
where TPixel : struct, IPixel<TPixel> where TPixel : struct, IPixel<TPixel>
{ {
Guard.NotNull(configuration, nameof(configuration));
maxColors = maxColors.Clamp(QuantizerConstants.MinColors, QuantizerConstants.MaxColors); maxColors = maxColors.Clamp(QuantizerConstants.MinColors, QuantizerConstants.MaxColors);
return new WuFrameQuantizer<TPixel>(this, maxColors); return new WuFrameQuantizer<TPixel>(configuration.MemoryAllocator, this, maxColors);
} }
private static IErrorDiffuser GetDiffuser(bool dither) => dither ? KnownDiffusers.FloydSteinberg : null; private static IErrorDiffuser GetDiffuser(bool dither) => dither ? KnownDiffusers.FloydSteinberg : null;

Loading…
Cancel
Save