Browse Source

fix frame double processing

moved some extensions into new namespace
af/merge-core
Scott Williams 9 years ago
parent
commit
74f05629b8
  1. 2
      src/ImageSharp.Drawing/Processors/DrawImageProcessor.cs
  2. 6
      src/ImageSharp.Drawing/Processors/FillProcessor.cs
  3. 37
      src/ImageSharp/Advanced/ImageExtensions.cs
  4. 9
      src/ImageSharp/ApplyProcessors.cs
  5. 1
      src/ImageSharp/DefaultInternalImageProcessorContext.cs
  6. 3
      src/ImageSharp/Formats/Bmp/ImageExtensions.cs
  7. 3
      src/ImageSharp/Formats/Gif/ImageExtensions.cs
  8. 1
      src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegImagePostProcessor.cs
  9. 3
      src/ImageSharp/Formats/Jpeg/ImageExtensions.cs
  10. 3
      src/ImageSharp/Formats/Png/ImageExtensions.cs
  11. 63
      src/ImageSharp/Helpers/ImageExtensions.cs
  12. 108
      src/ImageSharp/Image/ImageExtensions.cs
  13. 54
      src/ImageSharp/Image/ImageFrame.LoadPixelData.cs
  14. 23
      src/ImageSharp/Image/ImageFrameCollection.cs
  15. 19
      src/ImageSharp/Image/ImageFrame{TPixel}.cs
  16. 21
      src/ImageSharp/Image/Image{TPixel}.cs
  17. 3
      src/ImageSharp/Image/PixelAccessor{TPixel}.cs
  18. 1
      src/ImageSharp/Processing/Processors/Binarization/ErrorDiffusionDitherProcessor.cs
  19. 1
      src/ImageSharp/Processing/Processors/Binarization/OrderedDitherProcessor.cs
  20. 2
      src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs
  21. 1
      src/ImageSharp/Processing/Processors/Convolution/EdgeDetection/EdgeDetectorCompassProcessor.cs
  22. 4
      src/ImageSharp/Processing/Processors/ImageProcessor.cs
  23. 1
      src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs
  24. 1
      src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs
  25. 3
      src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs
  26. 1
      src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs
  27. 2
      src/ImageSharp/Processing/Processors/Transforms/SkewProcessor.cs
  28. 3
      src/ImageSharp/Quantizers/Quantize.cs
  29. 6
      tests/ImageSharp.Benchmarks/Samplers/Glow.cs
  30. 5
      tests/ImageSharp.Tests/Image/ImageRotationTests.cs
  31. 1
      tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs
  32. 3
      tests/ImageSharp.Tests/TestFile.cs
  33. 1
      tests/ImageSharp.Tests/TestUtilities/ImageComparison/ExactImageComparer.cs
  34. 2
      tests/ImageSharp.Tests/TestUtilities/ImageComparison/ImageComparer.cs
  35. 1
      tests/ImageSharp.Tests/TestUtilities/ImageComparison/TolerantImageComparer.cs

2
src/ImageSharp.Drawing/Processors/DrawImageProcessor.cs

@ -4,6 +4,8 @@
using System;
using System.Numerics;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Helpers;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;

6
src/ImageSharp.Drawing/Processors/FillProcessor.cs

@ -4,6 +4,7 @@
using System;
using System.Numerics;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Drawing;
using SixLabors.ImageSharp.Drawing.Brushes;
using SixLabors.ImageSharp.Drawing.Brushes.Processors;
@ -64,10 +65,7 @@ namespace SixLabors.ImageSharp.Drawing.Processors
}
int width = maxX - minX;
// We could possibly do some optimization by having knowledge about the individual brushes operate
// for example If brush is SolidBrush<TPixel> then we could just get the color upfront
// and skip using the IBrushApplicator<TPixel>?.
using (var amount = new Buffer<float>(width))
using (BrushApplicator<TPixel> applicator = this.brush.CreateApplicator(source, sourceRectangle, this.options))
{

37
src/ImageSharp/Advanced/ImageExtensions.cs

@ -45,7 +45,7 @@ namespace SixLabors.ImageSharp.Advanced
/// <returns>The <see cref="Span{TPixel}"/></returns>
public static Span<TPixel> GetPixelRowSpan<TPixel>(this ImageFrame<TPixel> source, int row)
where TPixel : struct, IPixel<TPixel>
=> GetSpan(source).Slice(row * source.Width, source.Width);
=> GetSpan(source, row);
/// <summary>
/// Gets a <see cref="Span{TPixal}"/> representing the row 'y' beginning from the the first pixel on that row.
@ -56,7 +56,7 @@ namespace SixLabors.ImageSharp.Advanced
/// <returns>The <see cref="Span{TPixel}"/></returns>
public static Span<TPixel> GetPixelRowSpan<TPixel>(this Image<TPixel> source, int row)
where TPixel : struct, IPixel<TPixel>
=> GetSpan(source).Slice(row * source.Width, source.Width);
=> GetSpan(source, row);
/// <summary>
/// Gets the span.
@ -67,5 +67,38 @@ namespace SixLabors.ImageSharp.Advanced
private static Span<TPixel> GetSpan<TPixel>(IImageFrame<TPixel> source)
where TPixel : struct, IPixel<TPixel>
=> source.PixelBuffer.Span;
/// <summary>
/// Gets the span.
/// </summary>
/// <typeparam name="TPixel">The type of the pixel.</typeparam>
/// <param name="source">The source.</param>
/// <param name="row">The row.</param>
/// <returns>
/// The span retuned from Pixel source
/// </returns>
private static Span<TPixel> GetSpan<TPixel>(IImageFrame<TPixel> source, int row)
where TPixel : struct, IPixel<TPixel>
=> source.PixelBuffer.Span.Slice(row * source.Width, source.Width);
/// <summary>
/// Gets the bounds of the image.
/// </summary>
/// <typeparam name="TPixel">The Pixel format.</typeparam>
/// <param name="source">The source image</param>
/// <returns>Returns the bounds of the image</returns>
public static Configuration Configuration<TPixel>(this ImageFrame<TPixel> source)
where TPixel : struct, IPixel<TPixel>
=> source?.Parent?.ImageConfiguration ?? SixLabors.ImageSharp.Configuration.Default;
/// <summary>
/// Gets the bounds of the image.
/// </summary>
/// <typeparam name="TPixel">The Pixel format.</typeparam>
/// <param name="source">The source image</param>
/// <returns>Returns the bounds of the image</returns>
public static Configuration Configuration<TPixel>(this Image<TPixel> source)
where TPixel : struct, IPixel<TPixel>
=> source?.ImageConfiguration ?? SixLabors.ImageSharp.Configuration.Default;
}
}

9
src/ImageSharp/ApplyProcessors.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
@ -24,7 +25,7 @@ namespace SixLabors.ImageSharp
Guard.NotNull(operation, nameof(operation));
Guard.NotNull(source, nameof(source));
IInternalImageProcessingContext<TPixel> operationsRunner = source.Configuration.ImageOperationsProvider.CreateImageProcessingContext(source, true);
IInternalImageProcessingContext<TPixel> operationsRunner = source.Configuration().ImageOperationsProvider.CreateImageProcessingContext(source, true);
operation(operationsRunner);
operationsRunner.Apply();
}
@ -41,7 +42,7 @@ namespace SixLabors.ImageSharp
Guard.NotNull(operations, nameof(operations));
Guard.NotNull(source, nameof(source));
IInternalImageProcessingContext<TPixel> operationsRunner = source.Configuration.ImageOperationsProvider.CreateImageProcessingContext(source, true);
IInternalImageProcessingContext<TPixel> operationsRunner = source.Configuration().ImageOperationsProvider.CreateImageProcessingContext(source, true);
operationsRunner.ApplyProcessors(operations);
operationsRunner.Apply();
}
@ -59,7 +60,7 @@ namespace SixLabors.ImageSharp
Guard.NotNull(operation, nameof(operation));
Guard.NotNull(source, nameof(source));
IInternalImageProcessingContext<TPixel> operationsRunner = source.Configuration.ImageOperationsProvider.CreateImageProcessingContext(source, false);
IInternalImageProcessingContext<TPixel> operationsRunner = source.Configuration().ImageOperationsProvider.CreateImageProcessingContext(source, false);
operation(operationsRunner);
return operationsRunner.Apply();
}
@ -77,7 +78,7 @@ namespace SixLabors.ImageSharp
Guard.NotNull(operations, nameof(operations));
Guard.NotNull(source, nameof(source));
IInternalImageProcessingContext<TPixel> operationsRunner = source.Configuration.ImageOperationsProvider.CreateImageProcessingContext(source, false);
IInternalImageProcessingContext<TPixel> operationsRunner = source.Configuration().ImageOperationsProvider.CreateImageProcessingContext(source, false);
operationsRunner.ApplyProcessors(operations);
return operationsRunner.Apply();
}

1
src/ImageSharp/DefaultInternalImageProcessorContext.cs

@ -1,6 +1,7 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.Helpers;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using SixLabors.Primitives;

3
src/ImageSharp/Formats/Bmp/ImageExtensions.cs

@ -3,6 +3,7 @@
using System;
using System.IO;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Bmp;
using SixLabors.ImageSharp.PixelFormats;
@ -35,6 +36,6 @@ namespace SixLabors.ImageSharp
/// <exception cref="System.ArgumentNullException">Thrown if the stream is null.</exception>
public static void SaveAsBmp<TPixel>(this Image<TPixel> source, Stream stream, BmpEncoder encoder)
where TPixel : struct, IPixel<TPixel>
=> source.Save(stream, encoder ?? source.Configuration.FindEncoder(ImageFormats.Bmp));
=> source.Save(stream, encoder ?? source.Configuration().FindEncoder(ImageFormats.Bmp));
}
}

3
src/ImageSharp/Formats/Gif/ImageExtensions.cs

@ -3,6 +3,7 @@
using System;
using System.IO;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Gif;
using SixLabors.ImageSharp.PixelFormats;
@ -35,6 +36,6 @@ namespace SixLabors.ImageSharp
/// <exception cref="System.ArgumentNullException">Thrown if the stream is null.</exception>
public static void SaveAsGif<TPixel>(this Image<TPixel> source, Stream stream, GifEncoder encoder)
where TPixel : struct, IPixel<TPixel>
=> source.Save(stream, encoder ?? source.Configuration.FindEncoder(ImageFormats.Gif));
=> source.Save(stream, encoder ?? source.Configuration().FindEncoder(ImageFormats.Gif));
}
}

1
src/ImageSharp/Formats/Jpeg/Common/Decoder/JpegImagePostProcessor.cs

@ -2,6 +2,7 @@ using System;
using System.Linq;
using System.Numerics;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Helpers;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;

3
src/ImageSharp/Formats/Jpeg/ImageExtensions.cs

@ -3,6 +3,7 @@
using System;
using System.IO;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Jpeg;
using SixLabors.ImageSharp.PixelFormats;
@ -35,6 +36,6 @@ namespace SixLabors.ImageSharp
/// <exception cref="System.ArgumentNullException">Thrown if the stream is null.</exception>
public static void SaveAsJpeg<TPixel>(this Image<TPixel> source, Stream stream, JpegEncoder encoder)
where TPixel : struct, IPixel<TPixel>
=> source.Save(stream, encoder ?? source.Configuration.FindEncoder(ImageFormats.Jpeg));
=> source.Save(stream, encoder ?? source.Configuration().FindEncoder(ImageFormats.Jpeg));
}
}

3
src/ImageSharp/Formats/Png/ImageExtensions.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System.IO;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.PixelFormats;
@ -34,6 +35,6 @@ namespace SixLabors.ImageSharp
/// <exception cref="System.ArgumentNullException">Thrown if the stream is null.</exception>
public static void SaveAsPng<TPixel>(this Image<TPixel> source, Stream stream, PngEncoder encoder)
where TPixel : struct, IPixel<TPixel>
=> source.Save(stream, encoder ?? source.Configuration.FindEncoder(ImageFormats.Png));
=> source.Save(stream, encoder ?? source.Configuration().FindEncoder(ImageFormats.Png));
}
}

63
src/ImageSharp/Helpers/ImageExtensions.cs

@ -0,0 +1,63 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Helpers
{
/// <summary>
/// Extension methods over Image{TPixel}
/// </summary>
public static partial class ImageExtensions
{
/// <summary>
/// Gets the bounds of the image.
/// </summary>
/// <typeparam name="TPixel">The Pixel format.</typeparam>
/// <param name="source">The source image</param>
/// <returns>Returns the bounds of the image</returns>
public static Rectangle Bounds<TPixel>(this Image<TPixel> source)
where TPixel : struct, IPixel<TPixel>
=> new Rectangle(0, 0, source.Width, source.Height);
/// <summary>
/// Gets the bounds of the image.
/// </summary>
/// <typeparam name="TPixel">The Pixel format.</typeparam>
/// <param name="source">The source image</param>
/// <returns>Returns the bounds of the image</returns>
public static Rectangle Bounds<TPixel>(this ImageFrame<TPixel> source)
where TPixel : struct, IPixel<TPixel>
=> new Rectangle(0, 0, source.Width, source.Height);
/// <summary>
/// Gets the size of the image.
/// </summary>
/// <typeparam name="TPixel">The Pixel format.</typeparam>
/// <param name="source">The source image</param>
/// <returns>Returns the bounds of the image</returns>
public static Size Size<TPixel>(this Image<TPixel> source)
where TPixel : struct, IPixel<TPixel>
=> new Size(source.Width, source.Height);
/// <summary>
/// Gets the size of the image.
/// </summary>
/// <typeparam name="TPixel">The Pixel format.</typeparam>
/// <param name="source">The source image</param>
/// <returns>Returns the bounds of the image</returns>
public static Size Size<TPixel>(this ImageFrame<TPixel> source)
where TPixel : struct, IPixel<TPixel>
=> new Size(source.Width, source.Height);
}
}

108
src/ImageSharp/Image/ImageExtensions.cs

@ -18,56 +18,6 @@ namespace SixLabors.ImageSharp
/// </summary>
public static partial class ImageExtensions
{
/// <summary>
/// Gets the bounds of the image.
/// </summary>
/// <typeparam name="TPixel">The Pixel format.</typeparam>
/// <param name="source">The source image</param>
/// <returns>Returns the bounds of the image</returns>
public static Configuration Configuration<TPixel>(this ImageFrame<TPixel> source)
where TPixel : struct, IPixel<TPixel>
=> source.Parent?.Configuration ?? SixLabors.ImageSharp.Configuration.Default;
/// <summary>
/// Gets the bounds of the image.
/// </summary>
/// <typeparam name="TPixel">The Pixel format.</typeparam>
/// <param name="source">The source image</param>
/// <returns>Returns the bounds of the image</returns>
public static Rectangle Bounds<TPixel>(this Image<TPixel> source)
where TPixel : struct, IPixel<TPixel>
=> new Rectangle(0, 0, source.Width, source.Height);
/// <summary>
/// Gets the bounds of the image.
/// </summary>
/// <typeparam name="TPixel">The Pixel format.</typeparam>
/// <param name="source">The source image</param>
/// <returns>Returns the bounds of the image</returns>
public static Rectangle Bounds<TPixel>(this ImageFrame<TPixel> source)
where TPixel : struct, IPixel<TPixel>
=> new Rectangle(0, 0, source.Width, source.Height);
/// <summary>
/// Gets the size of the image.
/// </summary>
/// <typeparam name="TPixel">The Pixel format.</typeparam>
/// <param name="source">The source image</param>
/// <returns>Returns the bounds of the image</returns>
public static Size Size<TPixel>(this Image<TPixel> source)
where TPixel : struct, IPixel<TPixel>
=> new Size(source.Width, source.Height);
/// <summary>
/// Gets the size of the image.
/// </summary>
/// <typeparam name="TPixel">The Pixel format.</typeparam>
/// <param name="source">The source image</param>
/// <returns>Returns the bounds of the image</returns>
public static Size Size<TPixel>(this ImageFrame<TPixel> source)
where TPixel : struct, IPixel<TPixel>
=> new Size(source.Width, source.Height);
#if !NETSTANDARD1_1
/// <summary>
/// Saves the image to the given stream using the currently loaded image format.
@ -82,12 +32,12 @@ namespace SixLabors.ImageSharp
Guard.NotNullOrEmpty(filePath, nameof(filePath));
string ext = Path.GetExtension(filePath).Trim('.');
IImageFormat format = source.Configuration.FindFormatByFileExtension(ext);
IImageFormat format = source.Configuration().FindFormatByFileExtension(ext);
if (format == null)
{
var stringBuilder = new StringBuilder();
stringBuilder.AppendLine($"Can't find a format that is associated with the file extention '{ext}'. Registered formats with there extensions include:");
foreach (IImageFormat fmt in source.Configuration.ImageFormats)
foreach (IImageFormat fmt in source.Configuration().ImageFormats)
{
stringBuilder.AppendLine($" - {fmt.Name} : {string.Join(", ", fmt.FileExtensions)}");
}
@ -95,13 +45,13 @@ namespace SixLabors.ImageSharp
throw new NotSupportedException(stringBuilder.ToString());
}
IImageEncoder encoder = source.Configuration.FindEncoder(format);
IImageEncoder encoder = source.Configuration().FindEncoder(format);
if (encoder == null)
{
var stringBuilder = new StringBuilder();
stringBuilder.AppendLine($"Can't find encoder for file extention '{ext}' using image format '{format.Name}'. Registered encoders include:");
foreach (KeyValuePair<IImageFormat, IImageEncoder> enc in source.Configuration.ImageEncoders)
foreach (KeyValuePair<IImageFormat, IImageEncoder> enc in source.Configuration().ImageEncoders)
{
stringBuilder.AppendLine($" - {enc.Key} : {enc.Value.GetType().Name}");
}
@ -124,7 +74,7 @@ namespace SixLabors.ImageSharp
where TPixel : struct, IPixel<TPixel>
{
Guard.NotNull(encoder, nameof(encoder));
using (Stream fs = source.Configuration.FileSystem.Create(filePath))
using (Stream fs = source.Configuration().FileSystem.Create(filePath))
{
source.Save(fs, encoder);
}
@ -143,14 +93,14 @@ namespace SixLabors.ImageSharp
where TPixel : struct, IPixel<TPixel>
{
Guard.NotNull(format, nameof(format));
IImageEncoder encoder = source.Configuration.FindEncoder(format);
IImageEncoder encoder = source.Configuration().FindEncoder(format);
if (encoder == null)
{
var stringBuilder = new StringBuilder();
stringBuilder.AppendLine("Can't find encoder for provided mime type. Available encoded:");
foreach (KeyValuePair<IImageFormat, IImageEncoder> val in source.Configuration.ImageEncoders)
foreach (KeyValuePair<IImageFormat, IImageEncoder> val in source.Configuration().ImageEncoders)
{
stringBuilder.AppendLine($" - {val.Key.Name} : {val.Value.GetType().Name}");
}
@ -161,6 +111,28 @@ namespace SixLabors.ImageSharp
source.Save(stream, encoder);
}
/// <summary>
/// Saves the raw image to the given bytes.
/// </summary>
/// <typeparam name="TPixel">The Pixel format.</typeparam>
/// <param name="source">The source image</param>
/// <returns>A copy of the pixel data as bytes from this frame.</returns>
/// <exception cref="System.ArgumentNullException">Thrown if the stream is null.</exception>
public static byte[] SavePixelData<TPixel>(this ImageFrame<TPixel> source)
where TPixel : struct, IPixel<TPixel>
=> source.GetPixelSpan().AsBytes().ToArray();
/// <summary>
/// Saves the raw image to the given bytes.
/// </summary>
/// <typeparam name="TPixel">The Pixel format.</typeparam>
/// <param name="source">The source image</param>
/// <param name="buffer">The buffer to save the raw pixel data to.</param>
/// <exception cref="System.ArgumentNullException">Thrown if the stream is null.</exception>
public static void SavePixelData<TPixel>(this ImageFrame<TPixel> source, byte[] buffer)
where TPixel : struct, IPixel<TPixel>
=> SavePixelData(source, new Span<byte>(buffer));
/// <summary>
/// Saves the raw image to the given bytes.
/// </summary>
@ -177,6 +149,28 @@ namespace SixLabors.ImageSharp
byteBuffer.CopyTo(buffer);
}
/// <summary>
/// Saves the raw image to the given bytes.
/// </summary>
/// <typeparam name="TPixel">The Pixel format.</typeparam>
/// <param name="source">The source image</param>
/// <returns>A copy of the pixel data from the first frame as bytes.</returns>
/// <exception cref="System.ArgumentNullException">Thrown if the stream is null.</exception>
public static byte[] SavePixelData<TPixel>(this Image<TPixel> source)
where TPixel : struct, IPixel<TPixel>
=> source.GetPixelSpan().AsBytes().ToArray();
/// <summary>
/// Saves the raw image to the given bytes.
/// </summary>
/// <typeparam name="TPixel">The Pixel format.</typeparam>
/// <param name="source">The source image</param>
/// <param name="buffer">The buffer to save the raw pixel data to.</param>
/// <exception cref="System.ArgumentNullException">Thrown if the stream is null.</exception>
public static void SavePixelData<TPixel>(this Image<TPixel> source, byte[] buffer)
where TPixel : struct, IPixel<TPixel>
=> SavePixelData(source, new Span<byte>(buffer));
/// <summary>
/// Saves the raw image to the given bytes.
/// </summary>

54
src/ImageSharp/Image/ImageFrame.LoadPixelData.cs

@ -0,0 +1,54 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.IO;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp
{
/// <content>
/// Adds static methods allowing the creation of new image from raw pixel data.
/// </content>
public static partial class ImageFrame
{
/// <summary>
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given byte array in <typeparamref name="TPixel"/> format.
/// </summary>
/// <param name="config">The config for the decoder.</param>
/// <param name="data">The byte array containing image data.</param>
/// <param name="width">The width of the final image.</param>
/// <param name="height">The height of the final image.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static ImageFrame<TPixel> LoadPixelData<TPixel>(Span<byte> data, int width, int height)
where TPixel : struct, IPixel<TPixel>
=> LoadPixelData(data.NonPortableCast<byte, TPixel>(), width, height);
/// <summary>
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the raw <typeparamref name="TPixel"/> data.
/// </summary>
/// <param name="config">The config for the decoder.</param>
/// <param name="data">The Span containing the image Pixel data.</param>
/// <param name="width">The width of the final image.</param>
/// <param name="height">The height of the final image.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static ImageFrame<TPixel> LoadPixelData<TPixel>(Span<TPixel> data, int width, int height)
where TPixel : struct, IPixel<TPixel>
{
int count = width * height;
Guard.MustBeGreaterThanOrEqualTo(data.Length, count, nameof(data));
var image = new ImageFrame<TPixel>(width, height);
SpanHelper.Copy(data, image.GetPixelSpan(), count);
return image;
}
}
}

23
src/ImageSharp/Image/ImageFrameCollection.cs

@ -37,6 +37,22 @@ namespace SixLabors.ImageSharp
/// </summary>
public int Count { get => this.frames.Count; }
/// <summary>
/// Gets the root frame.
/// </summary>
public ImageFrame<TPixel> RootFrame
{
get
{
if (this.frames.Count > 0)
{
return this.frames[0];
}
return null;
}
}
/// <summary>
/// Gets or sets the <see cref="ImageFrame{TPixel}"/> at the specified index.
/// </summary>
@ -105,9 +121,12 @@ namespace SixLabors.ImageSharp
private void ValidateFrameSize(ImageFrame<TPixel> frame)
{
if (this.parent.Width != frame.Width || this.parent.Height != frame.Height)
if (this.Count != 0)
{
throw new ArgumentException("Frame must have the same dimensions as the image", nameof(frame));
if (this.parent.Width != frame.Width || this.parent.Height != frame.Height)
{
throw new ArgumentException("Frame must have the same dimensions as the image", nameof(frame));
}
}
}

19
src/ImageSharp/Image/ImageFrame{TPixel}.cs

@ -49,8 +49,6 @@ namespace SixLabors.ImageSharp
Guard.MustBeGreaterThan(height, 0, nameof(height));
Guard.NotNull(metaData, nameof(metaData));
this.Width = width;
this.Height = height;
this.pixelBuffer = Buffer2D<TPixel>.CreateClean(width, height);
this.MetaData = metaData;
}
@ -61,9 +59,7 @@ namespace SixLabors.ImageSharp
/// <param name="source">The source.</param>
internal ImageFrame(ImageFrame<TPixel> source)
{
this.Width = source.Width;
this.Height = source.Height;
this.pixelBuffer = new Buffer2D<TPixel>(source.Width, source.Height);
this.pixelBuffer = new Buffer2D<TPixel>(source.pixelBuffer.Width, source.pixelBuffer.Height);
source.pixelBuffer.Span.CopyTo(this.pixelBuffer.Span);
this.MetaData = source.MetaData.Clone();
}
@ -72,10 +68,10 @@ namespace SixLabors.ImageSharp
Buffer2D<TPixel> IImageFrame<TPixel>.PixelBuffer => this.pixelBuffer;
/// <inheritdoc/>
public int Width { get; private set; }
public int Width => this.pixelBuffer.Width;
/// <inheritdoc/>
public int Height { get; private set; }
public int Height => this.pixelBuffer.Height;
/// <summary>
/// Gets the configuration providing initialization code which allows extending the library.
@ -158,13 +154,8 @@ namespace SixLabors.ImageSharp
{
Guard.NotNull(pixelSource, nameof(pixelSource));
int newWidth = pixelSource.Width;
int newHeight = pixelSource.Height;
// Push my memory into the accessor (which in turn unpins the old buffer ready for the images use)
var newPixels = pixelSource.SwapBufferOwnership(this.pixelBuffer);
this.Width = newWidth;
this.Height = newHeight;
this.pixelBuffer = newPixels;
}
@ -181,11 +172,7 @@ namespace SixLabors.ImageSharp
var newPixels = pixelSource.pixelBuffer;
pixelSource.pixelBuffer = this.pixelBuffer;
pixelSource.Width = this.Width;
pixelSource.Height = this.Height;
this.Width = newWidth;
this.Height = newHeight;
this.pixelBuffer = newPixels;
}

21
src/ImageSharp/Image/Image{TPixel}.cs

@ -75,8 +75,6 @@ namespace SixLabors.ImageSharp
{
Guard.NotNull(pixelSource, nameof(pixelSource));
this.Width = pixelSource.Width;
this.Height = pixelSource.Height;
int newHeight = pixelSource.Height;
for (int i = 0; i < this.Frames.Count; i++)
@ -85,7 +83,6 @@ namespace SixLabors.ImageSharp
}
}
/// <summary>
/// Initializes a new instance of the <see cref="Image{TPixel}" /> class
/// with the height and the width of the image.
@ -97,9 +94,7 @@ namespace SixLabors.ImageSharp
/// <param name="frames">The frames that will be owned by this image instance.</param>
internal Image(Configuration configuration, int width, int height, ImageMetaData metadata, IEnumerable<ImageFrame<TPixel>> frames)
{
this.Configuration = configuration ?? Configuration.Default;
this.Width = width;
this.Height = height;
this.ImageConfiguration = configuration ?? Configuration.Default;
this.MetaData = metadata ?? new ImageMetaData();
this.Frames = new ImageFrameCollection<TPixel>(this);
@ -114,7 +109,7 @@ namespace SixLabors.ImageSharp
if (this.Frames.Count == 0)
{
this.Frames.Add(new ImageFrame<TPixel>(this.Width, this.Height));
this.Frames.Add(new ImageFrame<TPixel>(width, height));
}
}
@ -124,17 +119,17 @@ namespace SixLabors.ImageSharp
/// <value>
/// The configuration.
/// </value>
public Configuration Configuration { get; }
internal Configuration ImageConfiguration { get; }
/// <summary>
/// Gets the width.
/// </summary>
public int Width { get; private set; }
public int Width => this.RootFrame?.Width ?? 0;
/// <summary>
/// Gets the height.
/// </summary>
public int Height { get; private set; }
public int Height => this.RootFrame?.Height ?? 0;
/// <summary>
/// Gets the meta data of the image.
@ -149,7 +144,7 @@ namespace SixLabors.ImageSharp
/// <summary>
/// Gets the root frame.
/// </summary>
private IImageFrame<TPixel> RootFrame => this.Frames[0];
private IImageFrame<TPixel> RootFrame => this.Frames.RootFrame;
/// <inheritdoc/>
Buffer2D<TPixel> IImageFrame<TPixel>.PixelBuffer => this.RootFrame.PixelBuffer;
@ -201,7 +196,7 @@ namespace SixLabors.ImageSharp
{
IEnumerable<ImageFrame<TPixel>> frames = this.Frames.Select(x => x.Clone()).ToArray();
return new Image<TPixel>(this.Configuration, this.Width, this.Height, this.MetaData.Clone(), frames);
return new Image<TPixel>(this.ImageConfiguration, this.Width, this.Height, this.MetaData.Clone(), frames);
}
/// <inheritdoc/>
@ -219,7 +214,7 @@ namespace SixLabors.ImageSharp
where TPixel2 : struct, IPixel<TPixel2>
{
IEnumerable<ImageFrame<TPixel2>> frames = this.Frames.Select(x => x.CloneAs<TPixel2>()).ToArray();
var target = new Image<TPixel2>(this.Configuration, this.Width, this.Height, this.MetaData, frames);
var target = new Image<TPixel2>(this.ImageConfiguration, this.Width, this.Height, this.MetaData, frames);
return target;
}

3
src/ImageSharp/Image/PixelAccessor{TPixel}.cs

@ -5,6 +5,7 @@ using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using Unsafe = System.Runtime.CompilerServices.Unsafe;
@ -48,7 +49,7 @@ namespace SixLabors.ImageSharp
Guard.MustBeGreaterThan(image.Height, 0, "image height");
this.SetPixelBufferUnsafe(image.PixelBuffer, false);
Configuration config = image.Parent?.Configuration ?? Configuration.Default;
Configuration config = image.Parent.Configuration();
this.ParallelOptions = config.ParallelOptions;
}

1
src/ImageSharp/Processing/Processors/Binarization/ErrorDiffusionDitherProcessor.cs

@ -4,6 +4,7 @@
using System;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Dithering;
using SixLabors.ImageSharp.Helpers;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;

1
src/ImageSharp/Processing/Processors/Binarization/OrderedDitherProcessor.cs

@ -5,6 +5,7 @@ using System;
using System.Buffers;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Dithering;
using SixLabors.ImageSharp.Helpers;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;

2
src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs

@ -4,6 +4,8 @@
using System;
using System.Numerics;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Helpers;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;

1
src/ImageSharp/Processing/Processors/Convolution/EdgeDetection/EdgeDetectorCompassProcessor.cs

@ -4,6 +4,7 @@
using System;
using System.Numerics;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;

4
src/ImageSharp/Processing/Processors/ImageProcessor.cs

@ -22,10 +22,6 @@ namespace SixLabors.ImageSharp.Processing
{
this.BeforeImageApply(source, sourceRectangle);
this.BeforeApply(source, sourceRectangle);
this.OnApply(source, sourceRectangle);
this.AfterApply(source, sourceRectangle);
foreach (ImageFrame<TPixel> sourceFrame in source.Frames)
{
this.BeforeApply(sourceFrame, sourceRectangle);

1
src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs

@ -5,6 +5,7 @@ using System;
using System.Numerics;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Helpers;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;

1
src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs

@ -5,6 +5,7 @@ using System;
using System.Numerics;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Helpers;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;

3
src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs

@ -52,12 +52,13 @@ namespace SixLabors.ImageSharp.Processing.Processors
/// <inheritdoc/>
protected override Image<TPixel> CreateDestination(Image<TPixel> source, Rectangle sourceRectangle)
{
var config = source.Configuration();
// We will always be creating the clone even for mutate because thats the way this base processor works
// ------------
// For resize we know we are going to populate every pixel with fresh data and we want a different target size so
// let's manually clone an empty set of images at the correct target and then have the base class processs them in turn.
var frames = source.Frames.Select(x => new ImageFrame<TPixel>(this.Width, this.Height, x.MetaData.Clone())); // this will create places holders
var image = new Image<TPixel>(source.Configuration, this.Width, this.Height, source.MetaData.Clone(), frames); // base the place holder images in to prevet a extra frame being added
var image = new Image<TPixel>(config, this.Width, this.Height, source.MetaData.Clone(), frames); // base the place holder images in to prevet a extra frame being added
return image;
}

1
src/ImageSharp/Processing/Processors/Transforms/RotateProcessor.cs

@ -5,6 +5,7 @@ using System;
using System.Numerics;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Helpers;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;

2
src/ImageSharp/Processing/Processors/Transforms/SkewProcessor.cs

@ -4,6 +4,8 @@
using System;
using System.Numerics;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Helpers;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;

3
src/ImageSharp/Quantizers/Quantize.cs

@ -3,6 +3,7 @@
using System;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Quantizers;
@ -65,7 +66,7 @@ namespace SixLabors.ImageSharp
Parallel.For(
0,
pixels.Height,
img.Configuration.ParallelOptions,
img.Configuration().ParallelOptions,
y =>
{
for (int x = 0; x < pixels.Width; x++)

6
tests/ImageSharp.Benchmarks/Samplers/Glow.cs

@ -17,6 +17,8 @@ namespace SixLabors.ImageSharp.Benchmarks
using SixLabors.ImageSharp.Memory;
using SixLabors.Primitives;
using SixLabors.ImageSharp.Helpers;
using SixLabors.ImageSharp.Advanced;
public class Glow : BenchmarkBase
{
@ -35,7 +37,7 @@ namespace SixLabors.ImageSharp.Benchmarks
{
using (Image<Rgba32> image = new Image<Rgba32>(800, 800))
{
bulk.Apply(image, image.Bounds());
this.bulk.Apply(image, image.Bounds());
return new CoreSize(image.Width, image.Height);
}
}
@ -45,7 +47,7 @@ namespace SixLabors.ImageSharp.Benchmarks
{
using (Image<Rgba32> image = new Image<Rgba32>(800, 800))
{
parallel.Apply(image, image.Bounds());
this.parallel.Apply(image, image.Bounds());
return new CoreSize(image.Width, image.Height);
}
}

5
tests/ImageSharp.Tests/Image/ImageRotationTests.cs

@ -1,6 +1,7 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.Helpers;
using SixLabors.Primitives;
using Xunit;
@ -48,9 +49,9 @@ namespace SixLabors.ImageSharp.Tests
var file = TestFile.Create(TestImages.Bmp.Car);
using (var image = Image.Load<Rgba32>(file.FullPath))
{
Size original = image.Bounds().Size;
Size original = image.Size();
image.Mutate(x => x.Rotate(angle));
return (original, image.Bounds().Size);
return (original, image.Size());
}
}
}

1
tests/ImageSharp.Tests/Processing/Processors/Transforms/ResizeTests.cs

@ -1,6 +1,7 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using SixLabors.ImageSharp.Helpers;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;

3
tests/ImageSharp.Tests/TestFile.cs

@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.PixelFormats;
@ -145,7 +146,7 @@ namespace SixLabors.ImageSharp.Tests
/// </returns>
public Image<Rgba32> CreateImage(IImageDecoder decoder)
{
return ImageSharp.Image.Load(this.Image.Configuration, this.Bytes, decoder);
return ImageSharp.Image.Load(this.Image.Configuration(), this.Bytes, decoder);
}
}
}

1
tests/ImageSharp.Tests/TestUtilities/ImageComparison/ExactImageComparer.cs

@ -3,6 +3,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison
using System;
using System.Collections.Generic;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Helpers;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;

2
tests/ImageSharp.Tests/TestUtilities/ImageComparison/ImageComparer.cs

@ -4,7 +4,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using SixLabors.ImageSharp.Helpers;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;

1
tests/ImageSharp.Tests/TestUtilities/ImageComparison/TolerantImageComparer.cs

@ -5,6 +5,7 @@
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Helpers;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Primitives;

Loading…
Cancel
Save