mirror of https://github.com/SixLabors/ImageSharp
470 changed files with 4185 additions and 4105 deletions
@ -1,3 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:e0f7d4c9396d4c7fe8173057c44cc2c0ecc24e52b52ce67c97dd11a7ac6e79ed |
|||
size 8113 |
|||
oid sha256:148a268c589b628f5d0b5af0e86911a0b393c35b8b25233c71553657c88e0b96 |
|||
size 7568 |
|||
|
|||
@ -1,3 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:7583dab9f399b7b9a7f69fc87086caa439249a705b058d6bfbd88238cfd95d4e |
|||
size 16613 |
|||
oid sha256:7e4b2ff72aef1979500cd130c28490a00be116bb833bc96ca30c85dc0596099c |
|||
size 15413 |
|||
|
|||
@ -1,3 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:c2b4b7ede0bf2fb4a9d028c9c4e930ab092b8c45689dd288ed1e419b5207048b |
|||
size 1904 |
|||
oid sha256:021c12313afbdc65f58bfea8c7b436d5c2102513bb63d9e64ee2b61a1344c56a |
|||
size 1799 |
|||
|
|||
@ -1,3 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:cd9c567ef861075fcaef709577e87017b5834556df5fc6ff51c4ded8972568a8 |
|||
size 35069 |
|||
oid sha256:3ae54ae0035df1f8f1459081e2f1d5cceda6f88cca6ec015d8c0209bf0d34edf |
|||
size 32534 |
|||
|
|||
@ -1,3 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:28a0995e02d0535a13d08997d36cc7b4df95760f9499396b209ad2c7d73ccef6 |
|||
size 3962 |
|||
oid sha256:92896854265693f28f9a503b9093cb2c9a4a9b329f310732efdd9c6f6c3761bc |
|||
size 3736 |
|||
|
|||
@ -1,3 +0,0 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:9480cb9ac66963e717b7e89666375e8bb23183e456067fd7d445ffb3c182b425 |
|||
size 11390 |
|||
@ -1,3 +1,3 @@ |
|||
version https://git-lfs.github.com/spec/v1 |
|||
oid sha256:cd9c567ef861075fcaef709577e87017b5834556df5fc6ff51c4ded8972568a8 |
|||
size 35069 |
|||
oid sha256:3ae54ae0035df1f8f1459081e2f1d5cceda6f88cca6ec015d8c0209bf0d34edf |
|||
size 32534 |
|||
|
|||
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 2.7 KiB |
@ -1,149 +0,0 @@ |
|||
|
|||
# Features |
|||
|
|||
### What works so far/ What is planned? |
|||
|
|||
We've achieved a lot so far and hope to do a lot more in the future. We're always looking for help so please pitch in! |
|||
|
|||
- **Encoding/decoding of image formats (plugable).** |
|||
- [x] Jpeg (Includes Subsampling. Progressive writing required) |
|||
- [x] Bmp (Read: 32bit, 24bit, 16 bit. Write: 32bit, 24bit just now) |
|||
- [x] Png (Read: Rgb, Rgba, Grayscale, Grayscale + alpha, Palette. Write: Rgb, Rgba, Grayscale, Grayscale + alpha, Palette) Supports interlaced decoding |
|||
- [x] Gif (Includes animated) |
|||
- [ ] Tiff (Help needed) |
|||
- **Metadata** |
|||
- [x] EXIF Read/Write (Jpeg just now) |
|||
- [ ] ICC (In Progress) |
|||
- **Quantizers (IQuantizer with alpha channel support, dithering, and thresholding)** |
|||
- [x] Octree |
|||
- [x] Xiaolin Wu |
|||
- [x] Palette |
|||
- **DIthering (Error diffusion and Ordered)** |
|||
- [x] Atkinson |
|||
- [x] Burks |
|||
- [x] FloydSteinburg |
|||
- [x] JarvisJudiceNinke |
|||
- [x] Sieera2 |
|||
- [x] Sierra3 |
|||
- [x] SerraLite |
|||
- [x] Bayer |
|||
- [x] Ordered |
|||
- **Basic color structs with implicit operators.** |
|||
- [x] Bgra32 |
|||
- [x] CIE Lab |
|||
- [x] CIE XYZ |
|||
- [x] CMYK |
|||
- [x] HSV |
|||
- [x] HSL |
|||
- [x] YCbCr |
|||
- **IPackedPixel representations of color models. Compatible with Microsoft XNA Game Studio and MonoGame IPackedVector\<TPacked\>.** |
|||
- [x] Alpha8 |
|||
- [x] Argb32 |
|||
- [x] Bgr565 |
|||
- [x] Bgra444 |
|||
- [x] Bgra565 |
|||
- [x] Byte4 |
|||
- [x] HalfSingle |
|||
- [x] HalfVector2 |
|||
- [x] HalfVector4 |
|||
- [x] NormalizedByte2 |
|||
- [x] NormalizedByte4 |
|||
- [x] NormalizedShort2 |
|||
- [x] NormalizedShort4 |
|||
- [x] Rg32 |
|||
- [x] Rgba1010102 |
|||
- [x] Rgba32 - 32bit color in RGBA order - Our default pixel format. |
|||
- [x] Rgba64 |
|||
- [x] RgbaVector |
|||
- [x] Short2 |
|||
- [x] Short4 |
|||
- **Basic shape primitives.** |
|||
- [x] Rectangle |
|||
- [x] Size |
|||
- [x] Point |
|||
- [x] Ellipse |
|||
- **Resampling algorithms. (Optional gamma correction, resize modes, Performance improvements?)** |
|||
- [x] Box |
|||
- [x] Bicubic |
|||
- [x] Lanczos2 |
|||
- [x] Lanczos3 |
|||
- [x] Lanczos5 |
|||
- [x] Lanczos8 |
|||
- [x] MitchelNetravali |
|||
- [x] Nearest Neighbour |
|||
- [x] Robidoux |
|||
- [x] Robidoux Sharp |
|||
- [x] Spline |
|||
- [x] Triangle |
|||
- [x] Welch |
|||
- **Padding** |
|||
- [x] Pad |
|||
- [x] ResizeMode.Pad |
|||
- [x] ResizeMode.BoxPad |
|||
- **Cropping** |
|||
- [x] Rectangular Crop |
|||
- [ ] Elliptical Crop |
|||
- [x] Entropy Crop |
|||
- [x] ResizeMode.Crop |
|||
- **Rotation/Skew** |
|||
- [x] Flip (90, 270, FlipType etc) |
|||
- [x] Rotate by angle and center point (Expandable canvas). |
|||
- [x] Skew by x/y angles and center point (Expandable canvas). |
|||
- **ColorMatrix operations (Uses Matrix4x4)** |
|||
- [x] BlackWhite |
|||
- [x] Grayscale BT709 |
|||
- [x] Grayscale BT601 |
|||
- [x] Hue |
|||
- [x] Saturation |
|||
- [x] Lomograph |
|||
- [x] Polaroid |
|||
- [x] Kodachrome |
|||
- [x] Sepia |
|||
- [x] Achromatomaly |
|||
- [x] Achromatopsia |
|||
- [x] Deuteranomaly |
|||
- [x] Deuteranopia |
|||
- [x] Protanomaly |
|||
- [x] Protanopia |
|||
- [x] Tritanomaly |
|||
- [x] Tritanopia |
|||
- **Edge Detection** |
|||
- [x] Kayyali |
|||
- [x] Kirsch |
|||
- [x] Laplacian3X3 |
|||
- [x] Laplacian5X5 |
|||
- [x] LaplacianOfGaussian |
|||
- [x] Prewitt |
|||
- [x] RobertsCross |
|||
- [x] Robinson |
|||
- [x] Scharr |
|||
- [x] Sobel |
|||
- **Blurring/Sharpening** |
|||
- [x] Gaussian blur |
|||
- [x] Gaussian sharpening |
|||
- [x] Box Blur |
|||
- **Filters** |
|||
- [x] Alpha |
|||
- [x] Contrast |
|||
- [x] Invert |
|||
- [x] BackgroundColor |
|||
- [x] Brightness |
|||
- [x] Pixelate |
|||
- [ ] Mask |
|||
- [x] Oil Painting |
|||
- [x] Vignette |
|||
- [x] Glow |
|||
- [x] Threshold |
|||
- **Drawing** |
|||
- [x] Image brush |
|||
- [x] Pattern brush |
|||
- [x] Solid brush |
|||
- [X] Hatch brush (Partial copy of System.Drawing brushes) |
|||
- [x] Pen (Solid, Dash, Custom) |
|||
- [x] Line drawing |
|||
- [x] Complex Polygons (Fill, draw) |
|||
- [x] DrawImage |
|||
- [ ] Gradient brush (Need help) |
|||
- **DrawingText** |
|||
- [ ] DrawString (In-progress. Single variant support just now, no italic,bold) |
|||
- Other stuff I haven't thought of. |
|||
@ -1,3 +0,0 @@ |
|||
Title: About This Project |
|||
--- |
|||
This project is awesome! |
|||
@ -1,10 +1,9 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using SixLabors.Primitives; |
|||
|
|||
namespace SixLabors.ImageSharp.Drawing |
|||
namespace SixLabors.ImageSharp.Primitives |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a region of an image.
|
|||
@ -1,12 +1,10 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using SixLabors.ImageSharp.Drawing.Brushes.Processors; |
|||
using SixLabors.ImageSharp.Drawing.Processors; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
using SixLabors.Primitives; |
|||
|
|||
namespace SixLabors.ImageSharp.Drawing.Brushes |
|||
namespace SixLabors.ImageSharp.Processing.Drawing.Brushes |
|||
{ |
|||
/// <summary>
|
|||
/// Brush represents a logical configuration of a brush which can be used to source pixel colors
|
|||
@ -1,20 +1,21 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using SixLabors.ImageSharp.Drawing.Brushes; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
using SixLabors.ImageSharp.Processing.Drawing.Brushes; |
|||
|
|||
namespace SixLabors.ImageSharp.Drawing.Pens |
|||
namespace SixLabors.ImageSharp.Processing.Drawing.Pens |
|||
{ |
|||
/// <summary>
|
|||
/// Common Pen styles
|
|||
/// Contains a collection of common Pen styles
|
|||
/// </summary>
|
|||
public static class Pens |
|||
{ |
|||
private static readonly float[] DashDotPattern = new[] { 3f, 1f, 1f, 1f }; |
|||
private static readonly float[] DashDotDotPattern = new[] { 3f, 1f, 1f, 1f, 1f, 1f }; |
|||
private static readonly float[] DottedPattern = new[] { 1f, 1f }; |
|||
private static readonly float[] DashedPattern = new[] { 3f, 1f }; |
|||
private static readonly float[] DashDotPattern = { 3f, 1f, 1f, 1f }; |
|||
private static readonly float[] DashDotDotPattern = { 3f, 1f, 1f, 1f, 1f, 1f }; |
|||
private static readonly float[] DottedPattern = { 1f, 1f }; |
|||
private static readonly float[] DashedPattern = { 3f, 1f }; |
|||
internal static readonly float[] EmptyPattern = new float[0]; |
|||
|
|||
/// <summary>
|
|||
/// Create a solid pen with out any drawing patterns
|
|||
@ -0,0 +1,155 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using SixLabors.ImageSharp.Advanced; |
|||
using SixLabors.ImageSharp.Memory; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
using SixLabors.ImageSharp.Processing.Processors; |
|||
using SixLabors.Primitives; |
|||
|
|||
namespace SixLabors.ImageSharp.Processing.Drawing.Processors |
|||
{ |
|||
/// <summary>
|
|||
/// Combines two images together by blending the pixels.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
internal class DrawImageProcessor<TPixel> : ImageProcessor<TPixel> |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="DrawImageProcessor{TPixel}"/> class.
|
|||
/// </summary>
|
|||
/// <param name="image">The image to blend with the currently processing image.</param>
|
|||
/// <param name="opacity">The opacity of the image to blend. Must be between 0 and 1.</param>
|
|||
public DrawImageProcessor(Image<TPixel> image, float opacity) |
|||
: this(image, Point.Empty, opacity) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="DrawImageProcessor{TPixel}"/> class.
|
|||
/// </summary>
|
|||
/// <param name="image">The image to blend with the currently processing image.</param>
|
|||
/// <param name="options">
|
|||
/// The options containing the opacity of the image to blend and blending mode.
|
|||
/// Opacity must be between 0 and 1.
|
|||
/// </param>
|
|||
public DrawImageProcessor(Image<TPixel> image, GraphicsOptions options) |
|||
: this(image, Point.Empty, options) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="DrawImageProcessor{TPixel}"/> class.
|
|||
/// </summary>
|
|||
/// <param name="image">The image to blend with the currently processing image.</param>
|
|||
/// <param name="location">The location to draw the blended image.</param>
|
|||
/// <param name="opacity">The opacity of the image to blend. Must be between 0 and 1.</param>
|
|||
public DrawImageProcessor(Image<TPixel> image, Point location, float opacity) |
|||
: this(image, location, opacity, GraphicsOptions.Default.BlenderMode) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="DrawImageProcessor{TPixel}"/> class.
|
|||
/// </summary>
|
|||
/// <param name="image">The image to blend with the currently processing image.</param>
|
|||
/// <param name="location">The location to draw the blended image.</param>
|
|||
/// <param name="options">
|
|||
/// The options containing the opacity of the image to blend and blending mode.
|
|||
/// Opacity must be between 0 and 1.
|
|||
/// </param>
|
|||
public DrawImageProcessor(Image<TPixel> image, Point location, GraphicsOptions options) |
|||
: this(image, location, options.BlendPercentage, options.BlenderMode) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="DrawImageProcessor{TPixel}"/> class.
|
|||
/// </summary>
|
|||
/// <param name="image">The image to blend with the currently processing image.</param>
|
|||
/// <param name="opacity">The opacity of the image to blend. Must be between 0 and 1.</param>
|
|||
/// <param name="blenderMode">The blending mode to use when drawing the image.</param>
|
|||
public DrawImageProcessor(Image<TPixel> image, float opacity, PixelBlenderMode blenderMode) |
|||
: this(image, Point.Empty, opacity, blenderMode) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="DrawImageProcessor{TPixel}"/> class.
|
|||
/// </summary>
|
|||
/// <param name="image">The image to blend with the currently processing image.</param>
|
|||
/// <param name="location">The location to draw the blended image.</param>
|
|||
/// <param name="opacity">The opacity of the image to blend. Must be between 0 and 1.</param>
|
|||
/// <param name="blenderMode">The blending mode to use when drawing the image.</param>
|
|||
public DrawImageProcessor(Image<TPixel> image, Point location, float opacity, PixelBlenderMode blenderMode) |
|||
{ |
|||
Guard.MustBeBetweenOrEqualTo(opacity, 0, 1, nameof(opacity)); |
|||
|
|||
this.Image = image; |
|||
this.Opacity = opacity; |
|||
this.Blender = PixelOperations<TPixel>.Instance.GetPixelBlender(blenderMode); |
|||
this.Location = location; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the image to blend
|
|||
/// </summary>
|
|||
public Image<TPixel> Image { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the opacity of the image to blend
|
|||
/// </summary>
|
|||
public float Opacity { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the pixel blender
|
|||
/// </summary>
|
|||
public PixelBlender<TPixel> Blender { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the location to draw the blended image
|
|||
/// </summary>
|
|||
public Point Location { get; } |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override void OnFrameApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration) |
|||
{ |
|||
Image<TPixel> targetImage = this.Image; |
|||
PixelBlender<TPixel> blender = this.Blender; |
|||
int locationY = this.Location.Y; |
|||
|
|||
// Align start/end positions.
|
|||
Rectangle bounds = targetImage.Bounds(); |
|||
|
|||
int minX = Math.Max(this.Location.X, sourceRectangle.X); |
|||
int maxX = Math.Min(this.Location.X + bounds.Width, sourceRectangle.Width); |
|||
int targetX = minX - this.Location.X; |
|||
|
|||
int minY = Math.Max(this.Location.Y, sourceRectangle.Y); |
|||
int maxY = Math.Min(this.Location.Y + bounds.Height, sourceRectangle.Bottom); |
|||
|
|||
int width = maxX - minX; |
|||
|
|||
MemoryManager memoryManager = this.Image.GetConfiguration().MemoryManager; |
|||
|
|||
using (IBuffer<float> amount = memoryManager.Allocate<float>(width)) |
|||
{ |
|||
amount.Span.Fill(this.Opacity); |
|||
|
|||
Parallel.For( |
|||
minY, |
|||
maxY, |
|||
configuration.ParallelOptions, |
|||
y => |
|||
{ |
|||
Span<TPixel> background = source.GetPixelRowSpan(y).Slice(minX, width); |
|||
Span<TPixel> foreground = targetImage.GetPixelRowSpan(y - locationY).Slice(targetX, width); |
|||
blender.Blend(memoryManager, background, background, foreground, amount.Span); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,96 +0,0 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Threading.Tasks; |
|||
using SixLabors.ImageSharp.Advanced; |
|||
using SixLabors.ImageSharp.Helpers; |
|||
using SixLabors.ImageSharp.Memory; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
using SixLabors.ImageSharp.Processing; |
|||
using SixLabors.Primitives; |
|||
|
|||
namespace SixLabors.ImageSharp.Drawing.Processors |
|||
{ |
|||
/// <summary>
|
|||
/// Combines two images together by blending the pixels.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
internal class DrawImageProcessor<TPixel> : ImageProcessor<TPixel> |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="DrawImageProcessor{TPixel}"/> class.
|
|||
/// </summary>
|
|||
/// <param name="image">The image to blend with the currently processing image.</param>
|
|||
/// <param name="location">The location to draw the blended image.</param>
|
|||
/// <param name="options">The opacity of the image to blend. Between 0 and 1.</param>
|
|||
public DrawImageProcessor(Image<TPixel> image, Point location, GraphicsOptions options) |
|||
{ |
|||
Guard.MustBeBetweenOrEqualTo(options.BlendPercentage, 0, 1, nameof(options.BlendPercentage)); |
|||
|
|||
this.Image = image; |
|||
this.Opacity = options.BlendPercentage; |
|||
this.Blender = PixelOperations<TPixel>.Instance.GetPixelBlender(options.BlenderMode); |
|||
this.Location = location; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the image to blend
|
|||
/// </summary>
|
|||
public Image<TPixel> Image { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the opacity of the image to blend
|
|||
/// </summary>
|
|||
public float Opacity { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the pixel blender
|
|||
/// </summary>
|
|||
public PixelBlender<TPixel> Blender { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the location to draw the blended image
|
|||
/// </summary>
|
|||
public Point Location { get; } |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override void OnApply(ImageFrame<TPixel> source, Rectangle sourceRectangle, Configuration configuration) |
|||
{ |
|||
Image<TPixel> targetImage = this.Image; |
|||
PixelBlender<TPixel> blender = this.Blender; |
|||
int locationY = this.Location.Y; |
|||
|
|||
// Align start/end positions.
|
|||
Rectangle bounds = targetImage.Bounds(); |
|||
|
|||
int minX = Math.Max(this.Location.X, sourceRectangle.X); |
|||
int maxX = Math.Min(this.Location.X + bounds.Width, sourceRectangle.Width); |
|||
int targetX = minX - this.Location.X; |
|||
|
|||
int minY = Math.Max(this.Location.Y, sourceRectangle.Y); |
|||
int maxY = Math.Min(this.Location.Y + bounds.Height, sourceRectangle.Bottom); |
|||
|
|||
int width = maxX - minX; |
|||
|
|||
MemoryManager memoryManager = this.Image.GetConfiguration().MemoryManager; |
|||
|
|||
using (IBuffer<float> amount = memoryManager.Allocate<float>(width)) |
|||
{ |
|||
amount.Span.Fill(this.Opacity); |
|||
|
|||
Parallel.For( |
|||
minY, |
|||
maxY, |
|||
configuration.ParallelOptions, |
|||
y => |
|||
{ |
|||
Span<TPixel> background = source.GetPixelRowSpan(y).Slice(minX, width); |
|||
Span<TPixel> foreground = targetImage.GetPixelRowSpan(y - locationY).Slice(targetX, width); |
|||
blender.Blend(memoryManager, background, background, foreground, amount.Span); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -1,61 +0,0 @@ |
|||
// 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); |
|||
} |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using SixLabors.Primitives; |
|||
|
|||
namespace SixLabors.ImageSharp |
|||
{ |
|||
/// <summary>
|
|||
/// Extension methods that allow the addition of geometry calculating methods to the <see cref="IImageInfo"/> type
|
|||
/// </summary>
|
|||
public static class ImageInfoExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the bounds of the image.
|
|||
/// </summary>
|
|||
/// <param name="info">The image info</param>
|
|||
/// <returns>The <see cref="Size"/></returns>
|
|||
public static Size Size(this IImageInfo info) => new Size(info.Width, info.Height); |
|||
|
|||
/// <summary>
|
|||
/// Gets the bounds of the image.
|
|||
/// </summary>
|
|||
/// <param name="info">The image info</param>
|
|||
/// <returns>The <see cref="Rectangle"/></returns>
|
|||
public static Rectangle Bounds(this IImageInfo info) => new Rectangle(0, 0, info.Width, info.Height); |
|||
} |
|||
} |
|||
@ -1,173 +0,0 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Diagnostics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
namespace SixLabors.ImageSharp.Memory |
|||
{ |
|||
/// <summary>
|
|||
/// Provides fast access to 2D arrays.
|
|||
/// </summary>
|
|||
/// <typeparam name="T">The type of elements in the array.</typeparam>
|
|||
internal struct Fast2DArray<T> |
|||
{ |
|||
/// <summary>
|
|||
/// The 1D representation of the 2D array.
|
|||
/// </summary>
|
|||
public T[] Data; |
|||
|
|||
/// <summary>
|
|||
/// Gets the width of the 2D array.
|
|||
/// </summary>
|
|||
public int Width; |
|||
|
|||
/// <summary>
|
|||
/// Gets the height of the 2D array.
|
|||
/// </summary>
|
|||
public int Height; |
|||
|
|||
/// <summary>
|
|||
/// Gets the number of items in the 2D array
|
|||
/// </summary>
|
|||
public int Count; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Fast2DArray{T}" /> struct.
|
|||
/// </summary>
|
|||
/// <param name="length">The length of each dimension.</param>
|
|||
public Fast2DArray(int length) |
|||
: this(length, length) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Fast2DArray{T}" /> struct.
|
|||
/// </summary>
|
|||
/// <param name="width">The width.</param>
|
|||
/// <param name="height">The height.</param>
|
|||
public Fast2DArray(int width, int height) |
|||
{ |
|||
this.Height = height; |
|||
this.Width = width; |
|||
|
|||
Guard.MustBeGreaterThan(width, 0, nameof(width)); |
|||
Guard.MustBeGreaterThan(height, 0, nameof(height)); |
|||
|
|||
this.Count = width * height; |
|||
this.Data = new T[this.Count]; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Fast2DArray{T}"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="data">The 2D array to provide access to.</param>
|
|||
public Fast2DArray(T[,] data) |
|||
{ |
|||
Guard.NotNull(data, nameof(data)); |
|||
this.Height = data.GetLength(0); |
|||
this.Width = data.GetLength(1); |
|||
|
|||
Guard.MustBeGreaterThan(this.Width, 0, nameof(this.Width)); |
|||
Guard.MustBeGreaterThan(this.Height, 0, nameof(this.Height)); |
|||
|
|||
this.Count = this.Width * this.Height; |
|||
this.Data = new T[this.Count]; |
|||
|
|||
for (int y = 0; y < this.Height; y++) |
|||
{ |
|||
for (int x = 0; x < this.Width; x++) |
|||
{ |
|||
this.Data[(y * this.Width) + x] = data[y, x]; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the item at the specified position.
|
|||
/// </summary>
|
|||
/// <param name="row">The row-coordinate of the item. Must be greater than or equal to zero and less than the height of the array.</param>
|
|||
/// <param name="column">The column-coordinate of the item. Must be greater than or equal to zero and less than the width of the array.</param>
|
|||
/// <returns>The <see typeparam="T"/> at the specified position.</returns>
|
|||
public T this[int row, int column] |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get |
|||
{ |
|||
this.CheckCoordinates(row, column); |
|||
return this.Data[(row * this.Width) + column]; |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
set |
|||
{ |
|||
this.CheckCoordinates(row, column); |
|||
this.Data[(row * this.Width) + column] = value; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs an implicit conversion from a 2D array to a <see cref="Fast2DArray{T}" />.
|
|||
/// </summary>
|
|||
/// <param name="data">The source array.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Fast2DArray{T}"/> representation on the source data.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static implicit operator Fast2DArray<T>(T[,] data) |
|||
{ |
|||
return new Fast2DArray<T>(data); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets a <see cref="Span{T}"/> representing the row beginning from the the first item on that row.
|
|||
/// </summary>
|
|||
/// <param name="row">The y-coordinate of the row. Must be greater than or equal to zero and less than the height of the 2D array.</param>
|
|||
/// <returns>The <see cref="Span{T}"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Span<T> GetRowSpan(int row) |
|||
{ |
|||
this.CheckCoordinates(row); |
|||
return new Span<T>(this.Data, row * this.Width, this.Width); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Checks the coordinates to ensure they are within bounds.
|
|||
/// </summary>
|
|||
/// <param name="row">The y-coordinate of the item. Must be greater than zero and smaller than the height of the array.</param>
|
|||
/// <param name="column">The x-coordinate of the item. Must be greater than zero and smaller than the width of the array.</param>
|
|||
/// <exception cref="ArgumentOutOfRangeException">
|
|||
/// Thrown if the coordinates are not within the bounds of the array.
|
|||
/// </exception>
|
|||
[Conditional("DEBUG")] |
|||
private void CheckCoordinates(int row, int column) |
|||
{ |
|||
if (row < 0 || row >= this.Height) |
|||
{ |
|||
throw new ArgumentOutOfRangeException(nameof(row), row, $"{row} is outwith the array bounds."); |
|||
} |
|||
|
|||
if (column < 0 || column >= this.Width) |
|||
{ |
|||
throw new ArgumentOutOfRangeException(nameof(column), column, $"{column} is outwith the array bounds."); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Checks the coordinates to ensure they are within bounds.
|
|||
/// </summary>
|
|||
/// <param name="row">The y-coordinate of the item. Must be greater than zero and smaller than the height of the array.</param>
|
|||
/// <exception cref="ArgumentOutOfRangeException">
|
|||
/// Thrown if the coordinates are not within the bounds of the image.
|
|||
/// </exception>
|
|||
[Conditional("DEBUG")] |
|||
private void CheckCoordinates(int row) |
|||
{ |
|||
if (row < 0 || row >= this.Height) |
|||
{ |
|||
throw new ArgumentOutOfRangeException(nameof(row), row, $"{row} is outwith the array bounds."); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,215 @@ |
|||
// Copyright (c) Six Labors and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
|
|||
using System; |
|||
using System.Diagnostics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
namespace SixLabors.ImageSharp.Primitives |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a dense matrix with arbitrary elements.
|
|||
/// Components that are adjacent in a column of the matrix are adjacent in the storage array.
|
|||
/// The components are said to be stored in column major order.
|
|||
/// </summary>
|
|||
/// <typeparam name="T">The type of elements in the matrix.</typeparam>
|
|||
public readonly struct DenseMatrix<T> : IEquatable<DenseMatrix<T>> |
|||
where T : struct, IEquatable<T> |
|||
{ |
|||
/// <summary>
|
|||
/// The 1D representation of the dense matrix.
|
|||
/// </summary>
|
|||
public readonly T[] Data; |
|||
|
|||
/// <summary>
|
|||
/// Gets the number of columns in the dense matrix.
|
|||
/// </summary>
|
|||
public readonly int Columns; |
|||
|
|||
/// <summary>
|
|||
/// Gets the number of rows in the dense matrix.
|
|||
/// </summary>
|
|||
public readonly int Rows; |
|||
|
|||
/// <summary>
|
|||
/// Gets the number of items in the array.
|
|||
/// </summary>
|
|||
public readonly int Count; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref=" DenseMatrix{T}" /> struct.
|
|||
/// </summary>
|
|||
/// <param name="length">The length of each side in the matrix.</param>
|
|||
public DenseMatrix(int length) |
|||
: this(length, length) |
|||
{ |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref=" DenseMatrix{T}" /> struct.
|
|||
/// </summary>
|
|||
/// <param name="columns">The number of columns.</param>
|
|||
/// <param name="rows">The number of rows.</param>
|
|||
public DenseMatrix(int columns, int rows) |
|||
{ |
|||
Guard.MustBeGreaterThan(columns, 0, nameof(columns)); |
|||
Guard.MustBeGreaterThan(rows, 0, nameof(rows)); |
|||
|
|||
this.Rows = rows; |
|||
this.Columns = columns; |
|||
this.Count = columns * rows; |
|||
this.Data = new T[this.Columns * this.Rows]; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref=" DenseMatrix{T}"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="data">The 2D array to provide access to.</param>
|
|||
public DenseMatrix(T[,] data) |
|||
{ |
|||
Guard.NotNull(data, nameof(data)); |
|||
int rows = data.GetLength(0); |
|||
int columns = data.GetLength(1); |
|||
|
|||
Guard.MustBeGreaterThan(rows, 0, nameof(this.Rows)); |
|||
Guard.MustBeGreaterThan(columns, 0, nameof(this.Columns)); |
|||
|
|||
this.Rows = rows; |
|||
this.Columns = columns; |
|||
this.Count = this.Columns * this.Rows; |
|||
this.Data = new T[this.Columns * this.Rows]; |
|||
|
|||
for (int y = 0; y < this.Rows; y++) |
|||
{ |
|||
for (int x = 0; x < this.Columns; x++) |
|||
{ |
|||
ref T value = ref this[y, x]; |
|||
value = data[y, x]; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the item at the specified position.
|
|||
/// </summary>
|
|||
/// <param name="row">The row-coordinate of the item. Must be greater than or equal to zero and less than the height of the array.</param>
|
|||
/// <param name="column">The column-coordinate of the item. Must be greater than or equal to zero and less than the width of the array.</param>
|
|||
/// <returns>The <see typeparam="T"/> at the specified position.</returns>
|
|||
public ref T this[int row, int column] |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get |
|||
{ |
|||
this.CheckCoordinates(row, column); |
|||
return ref this.Data[(row * this.Columns) + column]; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Performs an implicit conversion from a <see cref="T:T[,]" /> to a <see cref=" DenseMatrix{T}" />.
|
|||
/// </summary>
|
|||
/// <param name="data">The source array.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="DenseMatrix{T}"/> representation on the source data.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static implicit operator DenseMatrix<T>(T[,] data) => new DenseMatrix<T>(data); |
|||
|
|||
/// <summary>
|
|||
/// Performs an implicit conversion from a <see cref="DenseMatrix{T}"/> to a <see cref="T:T[,]" />.
|
|||
/// </summary>
|
|||
/// <param name="data">The source array.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="T:T[,]"/> representation on the source data.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
#pragma warning disable SA1008 // Opening parenthesis should be spaced correctly
|
|||
public static implicit operator T[,] (DenseMatrix<T> data) |
|||
#pragma warning restore SA1008 // Opening parenthesis should be spaced correctly
|
|||
{ |
|||
var result = new T[data.Rows, data.Columns]; |
|||
|
|||
for (int y = 0; y < data.Rows; y++) |
|||
{ |
|||
for (int x = 0; x < data.Columns; x++) |
|||
{ |
|||
ref T value = ref result[y, x]; |
|||
value = data[y, x]; |
|||
} |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Fills the matrix with the given value
|
|||
/// </summary>
|
|||
/// <param name="value">The value to fill each item with</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void Fill(T value) |
|||
{ |
|||
for (int i = 0; i < this.Data.Length; i++) |
|||
{ |
|||
this.Data[i] = value; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Clears the matrix setting each value to the default value for the element type
|
|||
/// </summary>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void Clear() => Array.Clear(this.Data, 0, this.Data.Length); |
|||
|
|||
/// <summary>
|
|||
/// Checks the coordinates to ensure they are within bounds.
|
|||
/// </summary>
|
|||
/// <param name="row">The y-coordinate of the item. Must be greater than zero and smaller than the height of the matrix.</param>
|
|||
/// <param name="column">The x-coordinate of the item. Must be greater than zero and smaller than the width of the matrix.</param>
|
|||
/// <exception cref="ArgumentOutOfRangeException">
|
|||
/// Thrown if the coordinates are not within the bounds of the array.
|
|||
/// </exception>
|
|||
[Conditional("DEBUG")] |
|||
private void CheckCoordinates(int row, int column) |
|||
{ |
|||
if (row < 0 || row >= this.Rows) |
|||
{ |
|||
throw new ArgumentOutOfRangeException(nameof(row), row, $"{row} is outwith the matrix bounds."); |
|||
} |
|||
|
|||
if (column < 0 || column >= this.Columns) |
|||
{ |
|||
throw new ArgumentOutOfRangeException(nameof(column), column, $"{column} is outwith the matrix bounds."); |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public bool Equals(DenseMatrix<T> other) |
|||
{ |
|||
if (this.Columns != other.Columns) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
if (this.Rows != other.Rows) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
for (int i = 0; i < this.Data.Length; i++) |
|||
{ |
|||
if (!this.Data[i].Equals(other.Data[i])) |
|||
{ |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object obj) => obj is DenseMatrix<T> matrix && this.Equals(matrix); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() => this.Data.GetHashCode(); |
|||
} |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue