Browse Source

Fix frame enumeration and clean up

pull/2269/head
James Jackson-South 4 years ago
parent
commit
073cefde00
  1. 1
      src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs
  2. 6
      src/ImageSharp/ImageFrameCollection.cs
  3. 10
      src/ImageSharp/ImageFrameCollection{TPixel}.cs
  4. 43
      src/ImageSharp/Image{TPixel}.cs
  5. 2
      src/ImageSharp/Processing/Processors/Quantization/DefaultPixelSamplingStrategy.cs
  6. 6
      src/ImageSharp/Processing/Processors/Quantization/QuantizerUtilities.cs

1
src/ImageSharp/Formats/Bmp/BmpEncoderCore.cs

@ -461,6 +461,7 @@ internal sealed class BmpEncoderCore : IImageEncoderInternals
private void Write8BitColor<TPixel>(Stream stream, ImageFrame<TPixel> image, Span<byte> colorPalette) private void Write8BitColor<TPixel>(Stream stream, ImageFrame<TPixel> image, Span<byte> colorPalette)
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
// TODO: Should we use the pixel sampling strategy here?
using IQuantizer<TPixel> frameQuantizer = this.quantizer.CreatePixelSpecificQuantizer<TPixel>(this.configuration); using IQuantizer<TPixel> frameQuantizer = this.quantizer.CreatePixelSpecificQuantizer<TPixel>(this.configuration);
using IndexedImageFrame<TPixel> quantized = frameQuantizer.BuildPaletteAndQuantizeFrame(image, image.Bounds()); using IndexedImageFrame<TPixel> quantized = frameQuantizer.BuildPaletteAndQuantizeFrame(image, image.Bounds());

6
src/ImageSharp/ImageFrameCollection.cs

@ -180,7 +180,7 @@ public abstract class ImageFrameCollection : IDisposable, IEnumerable<ImageFrame
} }
/// <inheritdoc /> /// <inheritdoc />
public IEnumerator<ImageFrame> GetEnumerator() IEnumerator<ImageFrame> IEnumerable<ImageFrame>.GetEnumerator()
{ {
this.EnsureNotDisposed(); this.EnsureNotDisposed();
@ -188,7 +188,7 @@ public abstract class ImageFrameCollection : IDisposable, IEnumerable<ImageFrame
} }
/// <inheritdoc/> /// <inheritdoc/>
IEnumerator IEnumerable.GetEnumerator() => this.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable<ImageFrame>)this).GetEnumerator();
/// <summary> /// <summary>
/// Throws <see cref="ObjectDisposedException"/> if the image frame is disposed. /// Throws <see cref="ObjectDisposedException"/> if the image frame is disposed.
@ -208,7 +208,7 @@ public abstract class ImageFrameCollection : IDisposable, IEnumerable<ImageFrame
protected abstract void Dispose(bool disposing); protected abstract void Dispose(bool disposing);
/// <summary> /// <summary>
/// Implements <see cref="GetEnumerator"/>. /// Implements <see cref="IEnumerable{ImageFrame}.GetEnumerator"/>.
/// </summary> /// </summary>
/// <returns>The enumerator.</returns> /// <returns>The enumerator.</returns>
protected abstract IEnumerator<ImageFrame> NonGenericGetEnumerator(); protected abstract IEnumerator<ImageFrame> NonGenericGetEnumerator();

10
src/ImageSharp/ImageFrameCollection{TPixel}.cs

@ -168,7 +168,7 @@ public sealed class ImageFrameCollection<TPixel> : ImageFrameCollection, IEnumer
{ {
this.EnsureNotDisposed(); this.EnsureNotDisposed();
var frame = ImageFrame.LoadPixelData( ImageFrame<TPixel> frame = ImageFrame.LoadPixelData(
this.parent.GetConfiguration(), this.parent.GetConfiguration(),
source, source,
this.RootFrame.Width, this.RootFrame.Width,
@ -298,7 +298,7 @@ public sealed class ImageFrameCollection<TPixel> : ImageFrameCollection, IEnumer
{ {
this.EnsureNotDisposed(); this.EnsureNotDisposed();
var frame = new ImageFrame<TPixel>( ImageFrame<TPixel> frame = new(
this.parent.GetConfiguration(), this.parent.GetConfiguration(),
this.RootFrame.Width, this.RootFrame.Width,
this.RootFrame.Height); this.RootFrame.Height);
@ -364,7 +364,7 @@ public sealed class ImageFrameCollection<TPixel> : ImageFrameCollection, IEnumer
/// </returns> /// </returns>
public ImageFrame<TPixel> CreateFrame(TPixel backgroundColor) public ImageFrame<TPixel> CreateFrame(TPixel backgroundColor)
{ {
var frame = new ImageFrame<TPixel>( ImageFrame<TPixel> frame = new(
this.parent.GetConfiguration(), this.parent.GetConfiguration(),
this.RootFrame.Width, this.RootFrame.Width,
this.RootFrame.Height, this.RootFrame.Height,
@ -374,7 +374,7 @@ public sealed class ImageFrameCollection<TPixel> : ImageFrameCollection, IEnumer
} }
/// <inheritdoc/> /// <inheritdoc/>
IEnumerator<ImageFrame<TPixel>> IEnumerable<ImageFrame<TPixel>>.GetEnumerator() => this.frames.GetEnumerator(); public IEnumerator<ImageFrame<TPixel>> GetEnumerator() => this.frames.GetEnumerator();
/// <inheritdoc/> /// <inheritdoc/>
IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)this.frames).GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)this.frames).GetEnumerator();
@ -408,7 +408,7 @@ public sealed class ImageFrameCollection<TPixel> : ImageFrameCollection, IEnumer
private ImageFrame<TPixel> CopyNonCompatibleFrame(ImageFrame source) private ImageFrame<TPixel> CopyNonCompatibleFrame(ImageFrame source)
{ {
var result = new ImageFrame<TPixel>( ImageFrame<TPixel> result = new(
this.parent.GetConfiguration(), this.parent.GetConfiguration(),
source.Size(), source.Size(),
source.Metadata.DeepClone()); source.Metadata.DeepClone());

43
src/ImageSharp/Image{TPixel}.cs

@ -80,9 +80,7 @@ public sealed class Image<TPixel> : Image
/// <param name="metadata">The images metadata.</param> /// <param name="metadata">The images metadata.</param>
internal Image(Configuration configuration, int width, int height, ImageMetadata metadata) internal Image(Configuration configuration, int width, int height, ImageMetadata metadata)
: base(configuration, PixelTypeInfo.Create<TPixel>(), metadata, width, height) : base(configuration, PixelTypeInfo.Create<TPixel>(), metadata, width, height)
{ => this.frames = new ImageFrameCollection<TPixel>(this, width, height, default(TPixel));
this.frames = new ImageFrameCollection<TPixel>(this, width, height, default(TPixel));
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Image{TPixel}"/> class /// Initializes a new instance of the <see cref="Image{TPixel}"/> class
@ -115,9 +113,7 @@ public sealed class Image<TPixel> : Image
int height, int height,
ImageMetadata metadata) ImageMetadata metadata)
: base(configuration, PixelTypeInfo.Create<TPixel>(), metadata, width, height) : base(configuration, PixelTypeInfo.Create<TPixel>(), metadata, width, height)
{ => this.frames = new ImageFrameCollection<TPixel>(this, width, height, memoryGroup);
this.frames = new ImageFrameCollection<TPixel>(this, width, height, memoryGroup);
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Image{TPixel}"/> class /// Initializes a new instance of the <see cref="Image{TPixel}"/> class
@ -135,9 +131,7 @@ public sealed class Image<TPixel> : Image
TPixel backgroundColor, TPixel backgroundColor,
ImageMetadata metadata) ImageMetadata metadata)
: base(configuration, PixelTypeInfo.Create<TPixel>(), metadata, width, height) : base(configuration, PixelTypeInfo.Create<TPixel>(), metadata, width, height)
{ => this.frames = new ImageFrameCollection<TPixel>(this, width, height, backgroundColor);
this.frames = new ImageFrameCollection<TPixel>(this, width, height, backgroundColor);
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="Image{TPixel}" /> class /// Initializes a new instance of the <see cref="Image{TPixel}" /> class
@ -148,9 +142,7 @@ public sealed class Image<TPixel> : Image
/// <param name="frames">The frames that will be owned by this image instance.</param> /// <param name="frames">The frames that will be owned by this image instance.</param>
internal Image(Configuration configuration, ImageMetadata metadata, IEnumerable<ImageFrame<TPixel>> frames) internal Image(Configuration configuration, ImageMetadata metadata, IEnumerable<ImageFrame<TPixel>> frames)
: base(configuration, PixelTypeInfo.Create<TPixel>(), metadata, ValidateFramesAndGetSize(frames)) : base(configuration, PixelTypeInfo.Create<TPixel>(), metadata, ValidateFramesAndGetSize(frames))
{ => this.frames = new ImageFrameCollection<TPixel>(this, frames);
this.frames = new ImageFrameCollection<TPixel>(this, frames);
}
/// <inheritdoc /> /// <inheritdoc />
protected override ImageFrameCollection NonGenericFrameCollection => this.Frames; protected override ImageFrameCollection NonGenericFrameCollection => this.Frames;
@ -181,7 +173,7 @@ public sealed class Image<TPixel> : Image
/// <exception cref="ArgumentOutOfRangeException">Thrown when the provided (x,y) coordinates are outside the image boundary.</exception> /// <exception cref="ArgumentOutOfRangeException">Thrown when the provided (x,y) coordinates are outside the image boundary.</exception>
public TPixel this[int x, int y] public TPixel this[int x, int y]
{ {
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
get get
{ {
this.EnsureNotDisposed(); this.EnsureNotDisposed();
@ -190,7 +182,7 @@ public sealed class Image<TPixel> : Image
return this.PixelSourceUnsafe.PixelBuffer.GetElementUnsafe(x, y); return this.PixelSourceUnsafe.PixelBuffer.GetElementUnsafe(x, y);
} }
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
set set
{ {
this.EnsureNotDisposed(); this.EnsureNotDisposed();
@ -212,7 +204,7 @@ public sealed class Image<TPixel> : Image
try try
{ {
var accessor = new PixelAccessor<TPixel>(buffer); PixelAccessor<TPixel> accessor = new(buffer);
processPixels(accessor); processPixels(accessor);
} }
finally finally
@ -243,8 +235,8 @@ public sealed class Image<TPixel> : Image
try try
{ {
var accessor1 = new PixelAccessor<TPixel>(buffer1); PixelAccessor<TPixel> accessor1 = new(buffer1);
var accessor2 = new PixelAccessor<TPixel2>(buffer2); PixelAccessor<TPixel2> accessor2 = new(buffer2);
processPixels(accessor1, accessor2); processPixels(accessor1, accessor2);
} }
finally finally
@ -283,9 +275,9 @@ public sealed class Image<TPixel> : Image
try try
{ {
var accessor1 = new PixelAccessor<TPixel>(buffer1); PixelAccessor<TPixel> accessor1 = new(buffer1);
var accessor2 = new PixelAccessor<TPixel2>(buffer2); PixelAccessor<TPixel2> accessor2 = new(buffer2);
var accessor3 = new PixelAccessor<TPixel3>(buffer3); PixelAccessor<TPixel3> accessor3 = new(buffer3);
processPixels(accessor1, accessor2, accessor3); processPixels(accessor1, accessor2, accessor3);
} }
finally finally
@ -348,7 +340,7 @@ public sealed class Image<TPixel> : Image
{ {
this.EnsureNotDisposed(); this.EnsureNotDisposed();
var clonedFrames = new ImageFrame<TPixel>[this.frames.Count]; ImageFrame<TPixel>[] clonedFrames = new ImageFrame<TPixel>[this.frames.Count];
for (int i = 0; i < clonedFrames.Length; i++) for (int i = 0; i < clonedFrames.Length; i++)
{ {
clonedFrames[i] = this.frames[i].Clone(configuration); clonedFrames[i] = this.frames[i].Clone(configuration);
@ -367,7 +359,7 @@ public sealed class Image<TPixel> : Image
{ {
this.EnsureNotDisposed(); this.EnsureNotDisposed();
var clonedFrames = new ImageFrame<TPixel2>[this.frames.Count]; ImageFrame<TPixel2>[] clonedFrames = new ImageFrame<TPixel2>[this.frames.Count];
for (int i = 0; i < clonedFrames.Length; i++) for (int i = 0; i < clonedFrames.Length; i++)
{ {
clonedFrames[i] = this.frames[i].CloneAs<TPixel2>(configuration); clonedFrames[i] = this.frames[i].CloneAs<TPixel2>(configuration);
@ -444,7 +436,7 @@ public sealed class Image<TPixel> : Image
return rootSize; return rootSize;
} }
[MethodImpl(InliningOptions.ShortMethod)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private void VerifyCoords(int x, int y) private void VerifyCoords(int x, int y)
{ {
if ((uint)x >= (uint)this.Width) if ((uint)x >= (uint)this.Width)
@ -458,9 +450,6 @@ public sealed class Image<TPixel> : Image
} }
} }
[MethodImpl(InliningOptions.ColdPath)]
private static void ThrowArgumentOutOfRangeException(string paramName) private static void ThrowArgumentOutOfRangeException(string paramName)
{ => throw new ArgumentOutOfRangeException(paramName);
throw new ArgumentOutOfRangeException(paramName);
}
} }

2
src/ImageSharp/Processing/Processors/Quantization/DefaultPixelSamplingStrategy.cs

@ -79,7 +79,7 @@ public class DefaultPixelSamplingStrategy : IPixelSamplingStrategy
r = Math.Max(this.MinimumScanRatio, r); // always visit the minimum defined portion of the image. r = Math.Max(this.MinimumScanRatio, r); // always visit the minimum defined portion of the image.
var ratio = new Rational(r); Rational ratio = new(r);
int denom = (int)ratio.Denominator; int denom = (int)ratio.Denominator;
int num = (int)ratio.Numerator; int num = (int)ratio.Numerator;

6
src/ImageSharp/Processing/Processors/Quantization/QuantizerUtilities.cs

@ -50,7 +50,7 @@ public static class QuantizerUtilities
Guard.NotNull(quantizer, nameof(quantizer)); Guard.NotNull(quantizer, nameof(quantizer));
Guard.NotNull(source, nameof(source)); Guard.NotNull(source, nameof(source));
var interest = Rectangle.Intersect(source.Bounds(), bounds); Rectangle interest = Rectangle.Intersect(source.Bounds(), bounds);
Buffer2DRegion<TPixel> region = source.PixelBuffer.GetRegion(interest); Buffer2DRegion<TPixel> region = source.PixelBuffer.GetRegion(interest);
// Collect the palette. Required before the second pass runs. // Collect the palette. Required before the second pass runs.
@ -77,9 +77,9 @@ public static class QuantizerUtilities
where TPixel : unmanaged, IPixel<TPixel> where TPixel : unmanaged, IPixel<TPixel>
{ {
Guard.NotNull(source, nameof(source)); Guard.NotNull(source, nameof(source));
var interest = Rectangle.Intersect(source.Bounds(), bounds); Rectangle interest = Rectangle.Intersect(source.Bounds(), bounds);
var destination = new IndexedImageFrame<TPixel>( IndexedImageFrame<TPixel> destination = new(
quantizer.Configuration, quantizer.Configuration,
interest.Width, interest.Width,
interest.Height, interest.Height,

Loading…
Cancel
Save