mirror of https://github.com/SixLabors/ImageSharp
286 changed files with 9274 additions and 6139 deletions
@ -1,51 +0,0 @@ |
|||
// <copyright file="Drawable.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.Drawing |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a path or set of paths that can be drawn as an outline.
|
|||
/// </summary>
|
|||
public abstract class Drawable |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the maximum number of intersections to could be returned.
|
|||
/// </summary>
|
|||
public abstract int MaxIntersections { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the bounds.
|
|||
/// </summary>
|
|||
public abstract Rectangle Bounds { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the point information for the specified x and y location.
|
|||
/// </summary>
|
|||
/// <param name="x">The x.</param>
|
|||
/// <param name="y">The y.</param>
|
|||
/// <returns>Information about the point in relation to a drawable edge</returns>
|
|||
public abstract PointInfo GetPointInfo(int x, int y); |
|||
|
|||
/// <summary>
|
|||
/// Scans the X axis for intersections.
|
|||
/// </summary>
|
|||
/// <param name="x">The x.</param>
|
|||
/// <param name="buffer">The buffer.</param>
|
|||
/// <param name="length">The length.</param>
|
|||
/// <param name="offset">The offset.</param>
|
|||
/// <returns>The number of intersections found.</returns>
|
|||
public abstract int ScanX(int x, float[] buffer, int length, int offset); |
|||
|
|||
/// <summary>
|
|||
/// Scans the Y axis for intersections.
|
|||
/// </summary>
|
|||
/// <param name="y">The position along the y axis to find intersections.</param>
|
|||
/// <param name="buffer">The buffer.</param>
|
|||
/// <param name="length">The length.</param>
|
|||
/// <param name="offset">The offset.</param>
|
|||
/// <returns>The number of intersections found.</returns>
|
|||
public abstract int ScanY(int y, float[] buffer, int length, int offset); |
|||
} |
|||
} |
|||
@ -0,0 +1,81 @@ |
|||
// <copyright file="FillPaths.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using Drawing; |
|||
using Drawing.Brushes; |
|||
using ImageSharp.PixelFormats; |
|||
using SixLabors.Shapes; |
|||
|
|||
/// <summary>
|
|||
/// Extension methods for the <see cref="Image{TPixel}"/> type.
|
|||
/// </summary>
|
|||
public static partial class ImageExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// Flood fills the image in the shape of the provided polygon with the specified brush..
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the color.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="brush">The brush.</param>
|
|||
/// <param name="paths">The shapes.</param>
|
|||
/// <param name="options">The graphics options.</param>
|
|||
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
|
|||
public static Image<TPixel> Fill<TPixel>(this Image<TPixel> source, IBrush<TPixel> brush, IPathCollection paths, GraphicsOptions options) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
foreach (IPath s in paths) |
|||
{ |
|||
source.Fill(brush, s, options); |
|||
} |
|||
|
|||
return source; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Flood fills the image in the shape of the provided polygon with the specified brush.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the color.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="brush">The brush.</param>
|
|||
/// <param name="paths">The paths.</param>
|
|||
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
|
|||
public static Image<TPixel> Fill<TPixel>(this Image<TPixel> source, IBrush<TPixel> brush, IPathCollection paths) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
return source.Fill(brush, paths, GraphicsOptions.Default); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Flood fills the image in the shape of the provided polygon with the specified brush..
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the color.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="color">The color.</param>
|
|||
/// <param name="paths">The paths.</param>
|
|||
/// <param name="options">The options.</param>
|
|||
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
|
|||
public static Image<TPixel> Fill<TPixel>(this Image<TPixel> source, TPixel color, IPathCollection paths, GraphicsOptions options) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
return source.Fill(new SolidBrush<TPixel>(color), paths, options); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Flood fills the image in the shape of the provided polygon with the specified brush..
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the color.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="color">The color.</param>
|
|||
/// <param name="paths">The paths.</param>
|
|||
/// <returns>The <see cref="Image{TPixel}"/>.</returns>
|
|||
public static Image<TPixel> Fill<TPixel>(this Image<TPixel> source, TPixel color, IPathCollection paths) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
return source.Fill(new SolidBrush<TPixel>(color), paths); |
|||
} |
|||
} |
|||
} |
|||
@ -1,27 +0,0 @@ |
|||
// <copyright file="ColoredPointInfo.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.Drawing.Processors |
|||
{ |
|||
using ImageSharp.PixelFormats; |
|||
|
|||
/// <summary>
|
|||
/// Returns details about how far away from the inside of a shape and the color the pixel could be.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the color.</typeparam>
|
|||
public struct ColoredPointInfo<TPixel> |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
/// <summary>
|
|||
/// The color
|
|||
/// </summary>
|
|||
public TPixel Color; |
|||
|
|||
/// <summary>
|
|||
/// The distance from element
|
|||
/// </summary>
|
|||
public float DistanceFromElement; |
|||
} |
|||
} |
|||
@ -1,40 +0,0 @@ |
|||
// <copyright file="PenApplicator.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.Drawing.Processors |
|||
{ |
|||
using System; |
|||
using ImageSharp.PixelFormats; |
|||
|
|||
/// <summary>
|
|||
/// primitive that converts a <see cref="PointInfo"/> into a color and a distance away from the drawable part of the path.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the color.</typeparam>
|
|||
public abstract class PenApplicator<TPixel> : IDisposable |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the required region.
|
|||
/// </summary>
|
|||
/// <value>
|
|||
/// The required region.
|
|||
/// </value>
|
|||
public abstract RectangleF RequiredRegion { get; } |
|||
|
|||
/// <inheritdoc/>
|
|||
public abstract void Dispose(); |
|||
|
|||
/// <summary>
|
|||
/// Gets a <see cref="ColoredPointInfo{TPixel}" /> from a point represented by a <see cref="PointInfo" />.
|
|||
/// </summary>
|
|||
/// <param name="x">The x.</param>
|
|||
/// <param name="y">The y.</param>
|
|||
/// <param name="info">The information to extract color details about.</param>
|
|||
/// <returns>
|
|||
/// Returns the color details and distance from a solid bit of the line.
|
|||
/// </returns>
|
|||
public abstract ColoredPointInfo<TPixel> GetColor(int x, int y, PointInfo info); |
|||
} |
|||
} |
|||
@ -1,141 +0,0 @@ |
|||
// <copyright file="DrawPathProcessor.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.Drawing.Processors |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
using System.Threading.Tasks; |
|||
|
|||
using ImageSharp.Memory; |
|||
using ImageSharp.PixelFormats; |
|||
using ImageSharp.Processing; |
|||
using Pens; |
|||
|
|||
/// <summary>
|
|||
/// Draws a path using the processor pipeline
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the color.</typeparam>
|
|||
/// <seealso cref="ImageSharp.Processing.ImageProcessor{TPixel}" />
|
|||
internal class DrawPathProcessor<TPixel> : ImageProcessor<TPixel> |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
private const float AntialiasFactor = 1f; |
|||
private const int PaddingFactor = 1; // needs to been the same or greater than AntialiasFactor
|
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="DrawPathProcessor{TPixel}" /> class.
|
|||
/// </summary>
|
|||
/// <param name="pen">The details how to draw the outline/path.</param>
|
|||
/// <param name="drawable">The details of the paths and outlines to draw.</param>
|
|||
/// <param name="options">The drawing configuration options.</param>
|
|||
public DrawPathProcessor(IPen<TPixel> pen, Drawable drawable, GraphicsOptions options) |
|||
{ |
|||
this.Path = drawable; |
|||
this.Pen = pen; |
|||
this.Options = options; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the graphics options.
|
|||
/// </summary>
|
|||
public GraphicsOptions Options { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the pen.
|
|||
/// </summary>
|
|||
public IPen<TPixel> Pen { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the path.
|
|||
/// </summary>
|
|||
public Drawable Path { get; } |
|||
|
|||
/// <inheritdoc/>
|
|||
protected override void OnApply(ImageBase<TPixel> source, Rectangle sourceRectangle) |
|||
{ |
|||
using (PenApplicator<TPixel> applicator = this.Pen.CreateApplicator(source, this.Path.Bounds, this.Options)) |
|||
{ |
|||
Rectangle rect = RectangleF.Ceiling(applicator.RequiredRegion); |
|||
|
|||
int polyStartY = rect.Y - PaddingFactor; |
|||
int polyEndY = rect.Bottom + PaddingFactor; |
|||
int startX = rect.X - PaddingFactor; |
|||
int endX = rect.Right + PaddingFactor; |
|||
|
|||
int minX = Math.Max(sourceRectangle.Left, startX); |
|||
int maxX = Math.Min(sourceRectangle.Right, endX); |
|||
int minY = Math.Max(sourceRectangle.Top, polyStartY); |
|||
int maxY = Math.Min(sourceRectangle.Bottom, polyEndY); |
|||
|
|||
// Align start/end positions.
|
|||
minX = Math.Max(0, minX); |
|||
maxX = Math.Min(source.Width, maxX); |
|||
minY = Math.Max(0, minY); |
|||
maxY = Math.Min(source.Height, maxY); |
|||
|
|||
// Reset offset if necessary.
|
|||
if (minX > 0) |
|||
{ |
|||
startX = 0; |
|||
} |
|||
|
|||
if (minY > 0) |
|||
{ |
|||
polyStartY = 0; |
|||
} |
|||
|
|||
int width = maxX - minX; |
|||
PixelBlender<TPixel> blender = PixelOperations<TPixel>.Instance.GetPixelBlender(this.Options.BlenderMode); |
|||
|
|||
Parallel.For( |
|||
minY, |
|||
maxY, |
|||
this.ParallelOptions, |
|||
y => |
|||
{ |
|||
int offsetY = y - polyStartY; |
|||
|
|||
using (var amount = new Buffer<float>(width)) |
|||
using (var colors = new Buffer<TPixel>(width)) |
|||
{ |
|||
for (int i = 0; i < width; i++) |
|||
{ |
|||
int x = i + minX; |
|||
int offsetX = x - startX; |
|||
PointInfo info = this.Path.GetPointInfo(offsetX, offsetY); |
|||
ColoredPointInfo<TPixel> color = applicator.GetColor(offsetX, offsetY, info); |
|||
amount[i] = (this.Opacity(color.DistanceFromElement) * this.Options.BlendPercentage).Clamp(0, 1); |
|||
colors[i] = color.Color; |
|||
} |
|||
|
|||
Span<TPixel> destination = source.GetRowSpan(offsetY).Slice(minX - startX, width); |
|||
blender.Blend(destination, destination, colors, amount); |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Returns the correct opacity for the given distance.
|
|||
/// </summary>
|
|||
/// <param name="distance">Thw distance from the central point.</param>
|
|||
/// <returns>The <see cref="float"/></returns>
|
|||
private float Opacity(float distance) |
|||
{ |
|||
if (distance <= 0) |
|||
{ |
|||
return 1; |
|||
} |
|||
|
|||
if (this.Options.Antialias && distance < AntialiasFactor) |
|||
{ |
|||
return 1 - (distance / AntialiasFactor); |
|||
} |
|||
|
|||
return 0; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,200 @@ |
|||
// <copyright file="DrawText.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System.Numerics; |
|||
|
|||
using Drawing; |
|||
using Drawing.Brushes; |
|||
using Drawing.Pens; |
|||
using ImageSharp.PixelFormats; |
|||
using SixLabors.Fonts; |
|||
using SixLabors.Shapes; |
|||
|
|||
/// <summary>
|
|||
/// Extension methods for the <see cref="Image{TPixel}"/> type.
|
|||
/// </summary>
|
|||
public static partial class ImageExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// Draws the text onto the the image filled via the brush.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the color.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="text">The text.</param>
|
|||
/// <param name="font">The font.</param>
|
|||
/// <param name="color">The color.</param>
|
|||
/// <param name="path">The path.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Image{TPixel}" />.
|
|||
/// </returns>
|
|||
public static Image<TPixel> DrawText<TPixel>(this Image<TPixel> source, string text, Font font, TPixel color, IPath path) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
return source.DrawText(text, font, color, path, TextGraphicsOptions.Default); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws the text onto the the image filled via the brush.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the color.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="text">The text.</param>
|
|||
/// <param name="font">The font.</param>
|
|||
/// <param name="color">The color.</param>
|
|||
/// <param name="path">The path.</param>
|
|||
/// <param name="options">The options.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Image{TPixel}" />.
|
|||
/// </returns>
|
|||
public static Image<TPixel> DrawText<TPixel>(this Image<TPixel> source, string text, Font font, TPixel color, IPath path, TextGraphicsOptions options) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
return source.DrawText(text, font, Brushes.Solid(color), null, path, options); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws the text onto the the image filled via the brush.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the color.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="text">The text.</param>
|
|||
/// <param name="font">The font.</param>
|
|||
/// <param name="brush">The brush.</param>
|
|||
/// <param name="path">The location.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Image{TPixel}" />.
|
|||
/// </returns>
|
|||
public static Image<TPixel> DrawText<TPixel>(this Image<TPixel> source, string text, Font font, IBrush<TPixel> brush, IPath path) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
return source.DrawText(text, font, brush, path, TextGraphicsOptions.Default); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws the text onto the the image filled via the brush.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the color.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="text">The text.</param>
|
|||
/// <param name="font">The font.</param>
|
|||
/// <param name="brush">The brush.</param>
|
|||
/// <param name="path">The path.</param>
|
|||
/// <param name="options">The options.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Image{TPixel}" />.
|
|||
/// </returns>
|
|||
public static Image<TPixel> DrawText<TPixel>(this Image<TPixel> source, string text, Font font, IBrush<TPixel> brush, IPath path, TextGraphicsOptions options) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
return source.DrawText(text, font, brush, null, path, options); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws the text onto the the image outlined via the pen.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the color.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="text">The text.</param>
|
|||
/// <param name="font">The font.</param>
|
|||
/// <param name="pen">The pen.</param>
|
|||
/// <param name="path">The path.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Image{TPixel}" />.
|
|||
/// </returns>
|
|||
public static Image<TPixel> DrawText<TPixel>(this Image<TPixel> source, string text, Font font, IPen<TPixel> pen, IPath path) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
return source.DrawText(text, font, pen, path, TextGraphicsOptions.Default); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws the text onto the the image outlined via the pen.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the color.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="text">The text.</param>
|
|||
/// <param name="font">The font.</param>
|
|||
/// <param name="pen">The pen.</param>
|
|||
/// <param name="path">The path.</param>
|
|||
/// <param name="options">The options.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Image{TPixel}" />.
|
|||
/// </returns>
|
|||
public static Image<TPixel> DrawText<TPixel>(this Image<TPixel> source, string text, Font font, IPen<TPixel> pen, IPath path, TextGraphicsOptions options) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
return source.DrawText(text, font, null, pen, path, options); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws the text onto the the image filled via the brush then outlined via the pen.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the color.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="text">The text.</param>
|
|||
/// <param name="font">The font.</param>
|
|||
/// <param name="brush">The brush.</param>
|
|||
/// <param name="pen">The pen.</param>
|
|||
/// <param name="path">The path.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Image{TPixel}" />.
|
|||
/// </returns>
|
|||
public static Image<TPixel> DrawText<TPixel>(this Image<TPixel> source, string text, Font font, IBrush<TPixel> brush, IPen<TPixel> pen, IPath path) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
return source.DrawText(text, font, brush, pen, path, TextGraphicsOptions.Default); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws the text onto the the image filled via the brush then outlined via the pen.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The type of the color.</typeparam>
|
|||
/// <param name="source">The image this method extends.</param>
|
|||
/// <param name="text">The text.</param>
|
|||
/// <param name="font">The font.</param>
|
|||
/// <param name="brush">The brush.</param>
|
|||
/// <param name="pen">The pen.</param>
|
|||
/// <param name="path">The path.</param>
|
|||
/// <param name="options">The options.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Image{TPixel}" />.
|
|||
/// </returns>
|
|||
public static Image<TPixel> DrawText<TPixel>(this Image<TPixel> source, string text, Font font, IBrush<TPixel> brush, IPen<TPixel> pen, IPath path, TextGraphicsOptions options) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
Vector2 dpi = DefaultTextDpi; |
|||
if (options.UseImageResolution) |
|||
{ |
|||
dpi = new Vector2((float)source.MetaData.HorizontalResolution, (float)source.MetaData.VerticalResolution); |
|||
} |
|||
|
|||
var style = new FontSpan(font, dpi) |
|||
{ |
|||
ApplyKerning = options.ApplyKerning, |
|||
TabWidth = options.TabWidth, |
|||
WrappingWidth = options.WrapTextWidth, |
|||
HorizontalAlignment = options.HorizontalAlignment, |
|||
VerticalAlignment = options.VerticalAlignment |
|||
}; |
|||
|
|||
IPathCollection glyphs = TextBuilder.GenerateGlyphs(text, path, style); |
|||
|
|||
var pathOptions = (GraphicsOptions)options; |
|||
if (brush != null) |
|||
{ |
|||
source.Fill(brush, glyphs, pathOptions); |
|||
} |
|||
|
|||
if (pen != null) |
|||
{ |
|||
source.Draw(pen, glyphs, pathOptions); |
|||
} |
|||
|
|||
return source; |
|||
} |
|||
} |
|||
} |
|||
@ -1,127 +0,0 @@ |
|||
// <copyright file="GlyphBuilder.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.Drawing |
|||
{ |
|||
using System.Collections.Generic; |
|||
using System.Numerics; |
|||
|
|||
using SixLabors.Fonts; |
|||
using SixLabors.Shapes; |
|||
|
|||
/// <summary>
|
|||
/// rendering surface that Fonts can use to generate Shapes.
|
|||
/// </summary>
|
|||
internal class GlyphBuilder : IGlyphRenderer |
|||
{ |
|||
private readonly PathBuilder builder = new PathBuilder(); |
|||
private readonly List<IPath> paths = new List<IPath>(); |
|||
private Vector2 currentPoint = default(Vector2); |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="GlyphBuilder"/> class.
|
|||
/// </summary>
|
|||
public GlyphBuilder() |
|||
: this(Vector2.Zero) |
|||
{ |
|||
// glyphs are renderd realative to bottom left so invert the Y axis to allow it to render on top left origin surface
|
|||
this.builder = new PathBuilder(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="GlyphBuilder"/> class.
|
|||
/// </summary>
|
|||
/// <param name="origin">The origin.</param>
|
|||
public GlyphBuilder(Vector2 origin) |
|||
{ |
|||
this.builder = new PathBuilder(); |
|||
this.builder.SetOrigin(origin); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the paths that have been rendered by this.
|
|||
/// </summary>
|
|||
public IEnumerable<IPath> Paths => this.paths; |
|||
|
|||
/// <summary>
|
|||
/// Begins the glyph.
|
|||
/// </summary>
|
|||
/// <param name="location">The offset that the glyph will be rendered at.</param>
|
|||
void IGlyphRenderer.BeginGlyph(Vector2 location) |
|||
{ |
|||
this.builder.Clear(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Begins the figure.
|
|||
/// </summary>
|
|||
void IGlyphRenderer.BeginFigure() |
|||
{ |
|||
this.builder.StartFigure(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws a cubic bezier from the current point to the <paramref name="point"/>
|
|||
/// </summary>
|
|||
/// <param name="secondControlPoint">The second control point.</param>
|
|||
/// <param name="thirdControlPoint">The third control point.</param>
|
|||
/// <param name="point">The point.</param>
|
|||
void IGlyphRenderer.CubicBezierTo(Vector2 secondControlPoint, Vector2 thirdControlPoint, Vector2 point) |
|||
{ |
|||
this.builder.AddBezier(this.currentPoint, secondControlPoint, thirdControlPoint, point); |
|||
this.currentPoint = point; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Ends the glyph.
|
|||
/// </summary>
|
|||
void IGlyphRenderer.EndGlyph() |
|||
{ |
|||
this.paths.Add(this.builder.Build()); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Ends the figure.
|
|||
/// </summary>
|
|||
void IGlyphRenderer.EndFigure() |
|||
{ |
|||
this.builder.CloseFigure(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws a line from the current point to the <paramref name="point"/>.
|
|||
/// </summary>
|
|||
/// <param name="point">The point.</param>
|
|||
void IGlyphRenderer.LineTo(Vector2 point) |
|||
{ |
|||
this.builder.AddLine(this.currentPoint, point); |
|||
this.currentPoint = point; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Moves to current point to the supplied vector.
|
|||
/// </summary>
|
|||
/// <param name="point">The point.</param>
|
|||
void IGlyphRenderer.MoveTo(Vector2 point) |
|||
{ |
|||
this.builder.StartFigure(); |
|||
this.currentPoint = point; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Draws a quadratics bezier from the current point to the <paramref name="point"/>
|
|||
/// </summary>
|
|||
/// <param name="secondControlPoint">The second control point.</param>
|
|||
/// <param name="point">The point.</param>
|
|||
void IGlyphRenderer.QuadraticBezierTo(Vector2 secondControlPoint, Vector2 point) |
|||
{ |
|||
Vector2 c1 = (((secondControlPoint - this.currentPoint) * 2) / 3) + this.currentPoint; |
|||
Vector2 c2 = (((secondControlPoint - point) * 2) / 3) + point; |
|||
|
|||
this.builder.AddBezier(this.currentPoint, c1, c2, point); |
|||
this.currentPoint = point; |
|||
} |
|||
} |
|||
} |
|||
Binary file not shown.
@ -0,0 +1,72 @@ |
|||
// <copyright file="Matrix3x2Extensions.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
/// <summary>
|
|||
/// Extension methods for the <see cref="Matrix3x2"/> struct
|
|||
/// </summary>
|
|||
public static class Matrix3x2Extensions |
|||
{ |
|||
/// <summary>
|
|||
/// Creates a rotation matrix for the given rotation in degrees and a center point.
|
|||
/// </summary>
|
|||
/// <param name="degree">The angle in degrees</param>
|
|||
/// <param name="centerPoint">The center point</param>
|
|||
/// <returns>The rotation <see cref="Matrix3x2"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Matrix3x2 CreateRotation(float degree, Point centerPoint) |
|||
{ |
|||
float radian = MathF.DegreeToRadian(degree); |
|||
return Matrix3x2.CreateRotation(radian, new Vector2(centerPoint.X, centerPoint.Y)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Creates a rotation matrix for the given rotation in degrees and a center point.
|
|||
/// </summary>
|
|||
/// <param name="degree">The angle in degrees</param>
|
|||
/// <param name="centerPoint">The center point</param>
|
|||
/// <returns>The rotation <see cref="Matrix3x2"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Matrix3x2 CreateRotation(float degree, PointF centerPoint) |
|||
{ |
|||
float radian = MathF.DegreeToRadian(degree); |
|||
return Matrix3x2.CreateRotation(radian, centerPoint); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Creates a skew matrix for the given angle in degrees and a center point.
|
|||
/// </summary>
|
|||
/// <param name="degreesX">The x-angle in degrees</param>
|
|||
/// <param name="degreesY">The y-angle in degrees</param>
|
|||
/// <param name="centerPoint">The center point</param>
|
|||
/// <returns>The rotation <see cref="Matrix3x2"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Matrix3x2 CreateSkew(float degreesX, float degreesY, Point centerPoint) |
|||
{ |
|||
float radiansX = MathF.DegreeToRadian(degreesX); |
|||
float radiansY = MathF.DegreeToRadian(degreesY); |
|||
return Matrix3x2.CreateSkew(radiansX, radiansY, new Vector2(centerPoint.X, centerPoint.Y)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Creates a skew matrix for the given angle in degrees and a center point.
|
|||
/// </summary>
|
|||
/// <param name="degreesX">The x-angle in degrees</param>
|
|||
/// <param name="degreesY">The y-angle in degrees</param>
|
|||
/// <returns>The rotation <see cref="Matrix3x2"/></returns>
|
|||
/// <param name="centerPoint">The center point</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static Matrix3x2 CreateSkew(float degreesX, float degreesY, PointF centerPoint) |
|||
{ |
|||
float radiansX = MathF.DegreeToRadian(degreesX); |
|||
float radiansY = MathF.DegreeToRadian(degreesY); |
|||
return Matrix3x2.CreateSkew(radiansX, radiansY, new Vector2(centerPoint.X, centerPoint.Y)); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,233 @@ |
|||
// <copyright file="PointF.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.ComponentModel; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
/// <summary>
|
|||
/// Represents an ordered pair of single precision floating point x- and y-coordinates that defines a point in
|
|||
/// a two-dimensional plane.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// This struct is fully mutable. This is done (against the guidelines) for the sake of performance,
|
|||
/// as it avoids the need to create new values for modification operations.
|
|||
/// </remarks>
|
|||
public struct PointF : IEquatable<PointF> |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a <see cref="PointF"/> that has X and Y values set to zero.
|
|||
/// </summary>
|
|||
public static readonly PointF Empty = default(PointF); |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="PointF"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="x">The horizontal position of the point.</param>
|
|||
/// <param name="y">The vertical position of the point.</param>
|
|||
public PointF(float x, float y) |
|||
: this() |
|||
{ |
|||
this.X = x; |
|||
this.Y = y; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="PointF"/> struct from the given <see cref="SizeF"/>.
|
|||
/// </summary>
|
|||
/// <param name="size">The size</param>
|
|||
public PointF(SizeF size) |
|||
{ |
|||
this.X = size.Width; |
|||
this.Y = size.Height; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the x-coordinate of this <see cref="PointF"/>.
|
|||
/// </summary>
|
|||
public float X { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the y-coordinate of this <see cref="PointF"/>.
|
|||
/// </summary>
|
|||
public float Y { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether this <see cref="PointF"/> is empty.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public bool IsEmpty => this.Equals(Empty); |
|||
|
|||
/// <summary>
|
|||
/// Creates a <see cref="Vector2"/> with the coordinates of the specified <see cref="PointF"/>.
|
|||
/// </summary>
|
|||
/// <param name="vector">The vector.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Vector2"/>.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static implicit operator PointF(Vector2 vector) => new PointF(vector.X, vector.Y); |
|||
|
|||
/// <summary>
|
|||
/// Creates a <see cref="Vector2"/> with the coordinates of the specified <see cref="PointF"/>.
|
|||
/// </summary>
|
|||
/// <param name="point">The point.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Vector2"/>.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static implicit operator Vector2(PointF point) => new Vector2(point.X, point.Y); |
|||
|
|||
/// <summary>
|
|||
/// Creates a <see cref="Point"/> with the coordinates of the specified <see cref="PointF"/> by truncating each of the coordinates.
|
|||
/// </summary>
|
|||
/// <param name="point">The point.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Point"/>.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static explicit operator Point(PointF point) => Point.Truncate(point); |
|||
|
|||
/// <summary>
|
|||
/// Translates a <see cref="PointF"/> by a given <see cref="SizeF"/>.
|
|||
/// </summary>
|
|||
/// <param name="point">The point on the left hand of the operand.</param>
|
|||
/// <param name="size">The size on the right hand of the operand.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="PointF"/>
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static PointF operator +(PointF point, SizeF size) => Add(point, size); |
|||
|
|||
/// <summary>
|
|||
/// Translates a <see cref="PointF"/> by the negative of a given <see cref="SizeF"/>.
|
|||
/// </summary>
|
|||
/// <param name="point">The point on the left hand of the operand.</param>
|
|||
/// <param name="size">The size on the right hand of the operand.</param>
|
|||
/// <returns>The <see cref="PointF"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static PointF operator -(PointF point, SizeF size) => Subtract(point, size); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="PointF"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="PointF"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="PointF"/> on the right side of the operand.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator ==(PointF left, PointF right) => left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="PointF"/> objects for inequality.
|
|||
/// </summary>
|
|||
/// <param name="left">
|
|||
/// The <see cref="PointF"/> on the left side of the operand.
|
|||
/// </param>
|
|||
/// <param name="right">
|
|||
/// The <see cref="PointF"/> on the right side of the operand.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator !=(PointF left, PointF right) => !left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Translates a <see cref="PointF"/> by the negative of a given <see cref="SizeF"/>.
|
|||
/// </summary>
|
|||
/// <param name="point">The point on the left hand of the operand.</param>
|
|||
/// <param name="size">The size on the right hand of the operand.</param>
|
|||
/// <returns>The <see cref="PointF"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static PointF Add(PointF point, SizeF size) => new PointF(point.X + size.Width, point.Y + size.Height); |
|||
|
|||
/// <summary>
|
|||
/// Translates a <see cref="PointF"/> by the negative of a given <see cref="SizeF"/>.
|
|||
/// </summary>
|
|||
/// <param name="point">The point on the left hand of the operand.</param>
|
|||
/// <param name="size">The size on the right hand of the operand.</param>
|
|||
/// <returns>The <see cref="PointF"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static PointF Subtract(PointF point, SizeF size) => new PointF(point.X - size.Width, point.Y - size.Height); |
|||
|
|||
/// <summary>
|
|||
/// Rotates a point around the given rotation matrix.
|
|||
/// </summary>
|
|||
/// <param name="point">The point to rotate</param>
|
|||
/// <param name="rotation">Rotation matrix used</param>
|
|||
/// <returns>The rotated <see cref="PointF"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static PointF Rotate(PointF point, Matrix3x2 rotation) => Vector2.Transform(new Vector2(point.X, point.Y), rotation); |
|||
|
|||
/// <summary>
|
|||
/// Skews a point using the given skew matrix.
|
|||
/// </summary>
|
|||
/// <param name="point">The point to rotate</param>
|
|||
/// <param name="skew">Rotation matrix used</param>
|
|||
/// <returns>The rotated <see cref="PointF"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static PointF Skew(PointF point, Matrix3x2 skew) => Vector2.Transform(new Vector2(point.X, point.Y), skew); |
|||
|
|||
/// <summary>
|
|||
/// Translates this <see cref="PointF"/> by the specified amount.
|
|||
/// </summary>
|
|||
/// <param name="dx">The amount to offset the x-coordinate.</param>
|
|||
/// <param name="dy">The amount to offset the y-coordinate.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void Offset(float dx, float dy) |
|||
{ |
|||
this.X += dx; |
|||
this.Y += dy; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Translates this <see cref="PointF"/> by the specified amount.
|
|||
/// </summary>
|
|||
/// <param name="point">The <see cref="PointF"/> used offset this <see cref="PointF"/>.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void Offset(PointF point) => this.Offset(point.X, point.Y); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() => this.GetHashCode(this); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() |
|||
{ |
|||
if (this.IsEmpty) |
|||
{ |
|||
return "PointF [ Empty ]"; |
|||
} |
|||
|
|||
return $"PointF [ X={this.X}, Y={this.Y} ]"; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object obj) => obj is PointF && this.Equals((PointF)obj); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Equals(PointF other) => this.X.Equals(other.X) && this.Y.Equals(other.Y); |
|||
|
|||
/// <summary>
|
|||
/// Returns the hash code for this instance.
|
|||
/// </summary>
|
|||
/// <param name="point">
|
|||
/// The instance of <see cref="PointF"/> to return the hash code for.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// A 32-bit signed integer that is the hash code for this instance.
|
|||
/// </returns>
|
|||
private int GetHashCode(PointF point) => point.X.GetHashCode() ^ point.Y.GetHashCode(); |
|||
} |
|||
} |
|||
@ -0,0 +1,179 @@ |
|||
// <copyright file="SizeF.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.ComponentModel; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
/// <summary>
|
|||
/// Stores an ordered pair of single precision floating points, which specify a height and width.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// This struct is fully mutable. This is done (against the guidelines) for the sake of performance,
|
|||
/// as it avoids the need to create new values for modification operations.
|
|||
/// </remarks>
|
|||
public struct SizeF : IEquatable<SizeF> |
|||
{ |
|||
/// <summary>
|
|||
/// Represents a <see cref="SizeF"/> that has Width and Height values set to zero.
|
|||
/// </summary>
|
|||
public static readonly SizeF Empty = default(SizeF); |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="SizeF"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="width">The width of the size.</param>
|
|||
/// <param name="height">The height of the size.</param>
|
|||
public SizeF(float width, float height) |
|||
{ |
|||
this.Width = width; |
|||
this.Height = height; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="SizeF"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="size">The size</param>
|
|||
public SizeF(SizeF size) |
|||
: this() |
|||
{ |
|||
this.Width = size.Width; |
|||
this.Height = size.Height; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="SizeF"/> struct from the given <see cref="PointF"/>.
|
|||
/// </summary>
|
|||
/// <param name="point">The point</param>
|
|||
public SizeF(PointF point) |
|||
{ |
|||
this.Width = point.X; |
|||
this.Height = point.Y; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the width of this <see cref="SizeF"/>.
|
|||
/// </summary>
|
|||
public float Width { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the height of this <see cref="SizeF"/>.
|
|||
/// </summary>
|
|||
public float Height { get; set; } |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether this <see cref="SizeF"/> is empty.
|
|||
/// </summary>
|
|||
[EditorBrowsable(EditorBrowsableState.Never)] |
|||
public bool IsEmpty => this.Equals(Empty); |
|||
|
|||
/// <summary>
|
|||
/// Creates a <see cref="Size"/> with the dimensions of the specified <see cref="SizeF"/> by truncating each of the dimensions.
|
|||
/// </summary>
|
|||
/// <param name="size">The size.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="Size"/>.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static explicit operator Size(SizeF size) => new Size(unchecked((int)size.Width), unchecked((int)size.Height)); |
|||
|
|||
/// <summary>
|
|||
/// Converts the given <see cref="SizeF"/> into a <see cref="PointF"/>.
|
|||
/// </summary>
|
|||
/// <param name="size">The size</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static explicit operator PointF(SizeF size) => new PointF(size.Width, size.Height); |
|||
|
|||
/// <summary>
|
|||
/// Computes the sum of adding two sizes.
|
|||
/// </summary>
|
|||
/// <param name="left">The size on the left hand of the operand.</param>
|
|||
/// <param name="right">The size on the right hand of the operand.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="SizeF"/>
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static SizeF operator +(SizeF left, SizeF right) => Add(left, right); |
|||
|
|||
/// <summary>
|
|||
/// Computes the difference left by subtracting one size from another.
|
|||
/// </summary>
|
|||
/// <param name="left">The size on the left hand of the operand.</param>
|
|||
/// <param name="right">The size on the right hand of the operand.</param>
|
|||
/// <returns>
|
|||
/// The <see cref="SizeF"/>
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static SizeF operator -(SizeF left, SizeF right) => Subtract(left, right); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="SizeF"/> objects for equality.
|
|||
/// </summary>
|
|||
/// <param name="left">The size on the left hand of the operand.</param>
|
|||
/// <param name="right">The size on the right hand of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is equal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator ==(SizeF left, SizeF right) => left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Compares two <see cref="SizeF"/> objects for inequality.
|
|||
/// </summary>
|
|||
/// <param name="left">The size on the left hand of the operand.</param>
|
|||
/// <param name="right">The size on the right hand of the operand.</param>
|
|||
/// <returns>
|
|||
/// True if the current left is unequal to the <paramref name="right"/> parameter; otherwise, false.
|
|||
/// </returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static bool operator !=(SizeF left, SizeF right) => !left.Equals(right); |
|||
|
|||
/// <summary>
|
|||
/// Performs vector addition of two <see cref="SizeF"/> objects.
|
|||
/// </summary>
|
|||
/// <param name="left">The size on the left hand of the operand.</param>
|
|||
/// <param name="right">The size on the right hand of the operand.</param>
|
|||
/// <returns>The <see cref="SizeF"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static SizeF Add(SizeF left, SizeF right) => new SizeF(left.Width + right.Width, left.Height + right.Height); |
|||
|
|||
/// <summary>
|
|||
/// Contracts a <see cref="SizeF"/> by another <see cref="SizeF"/>
|
|||
/// </summary>
|
|||
/// <param name="left">The size on the left hand of the operand.</param>
|
|||
/// <param name="right">The size on the right hand of the operand.</param>
|
|||
/// <returns>The <see cref="SizeF"/></returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static SizeF Subtract(SizeF left, SizeF right) => new SizeF(left.Width - right.Width, left.Height - right.Height); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() |
|||
{ |
|||
return this.GetHashCode(this); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override string ToString() |
|||
{ |
|||
if (this.IsEmpty) |
|||
{ |
|||
return "SizeF [ Empty ]"; |
|||
} |
|||
|
|||
return $"SizeF [ Width={this.Width}, Height={this.Height} ]"; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object obj) => obj is SizeF && this.Equals((SizeF)obj); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Equals(SizeF other) => this.Width.Equals(other.Width) && this.Height.Equals(other.Height); |
|||
|
|||
private int GetHashCode(SizeF size) => size.Width.GetHashCode() ^ size.Height.GetHashCode(); |
|||
} |
|||
} |
|||
@ -0,0 +1,135 @@ |
|||
// <copyright file="Bgr24.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.PixelFormats |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
/// <summary>
|
|||
/// Pixel type containing three 8-bit unsigned normalized values ranging from 0 to 255.
|
|||
/// The color components are stored in blue, green, red order.
|
|||
/// </summary>
|
|||
[StructLayout(LayoutKind.Sequential)] |
|||
public struct Bgr24 : IPixel<Bgr24> |
|||
{ |
|||
/// <summary>
|
|||
/// The blue component.
|
|||
/// </summary>
|
|||
public byte B; |
|||
|
|||
/// <summary>
|
|||
/// The green component.
|
|||
/// </summary>
|
|||
public byte G; |
|||
|
|||
/// <summary>
|
|||
/// The red component.
|
|||
/// </summary>
|
|||
public byte R; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Bgr24"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="r">The red component.</param>
|
|||
/// <param name="g">The green component.</param>
|
|||
/// <param name="b">The blue component.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Bgr24(byte r, byte g, byte b) |
|||
{ |
|||
this.R = r; |
|||
this.G = g; |
|||
this.B = b; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public PixelOperations<Bgr24> CreatePixelOperations() => new PixelOperations<Bgr24>(); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Equals(Bgr24 other) |
|||
{ |
|||
return this.R == other.R && this.G == other.G && this.B == other.B; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
return obj?.GetType() == typeof(Bgr24) && this.Equals((Bgr24)obj); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public override int GetHashCode() |
|||
{ |
|||
unchecked |
|||
{ |
|||
int hashCode = this.B; |
|||
hashCode = (hashCode * 397) ^ this.G; |
|||
hashCode = (hashCode * 397) ^ this.R; |
|||
return hashCode; |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void PackFromRgba32(Rgba32 source) |
|||
{ |
|||
this = source.Bgr; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void PackFromVector4(Vector4 vector) |
|||
{ |
|||
var rgba = default(Rgba32); |
|||
rgba.PackFromVector4(vector); |
|||
this.PackFromRgba32(rgba); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Vector4 ToVector4() |
|||
{ |
|||
return new Rgba32(this.R, this.G, this.B, 255).ToVector4(); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void ToRgb24(ref Rgb24 dest) |
|||
{ |
|||
dest.R = this.R; |
|||
dest.G = this.G; |
|||
dest.B = this.B; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void ToRgba32(ref Rgba32 dest) |
|||
{ |
|||
dest.R = this.R; |
|||
dest.G = this.G; |
|||
dest.B = this.B; |
|||
dest.A = 255; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public void ToBgr24(ref Bgr24 dest) |
|||
{ |
|||
dest = this; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public void ToBgra32(ref Bgra32 dest) |
|||
{ |
|||
dest.R = this.R; |
|||
dest.G = this.G; |
|||
dest.B = this.B; |
|||
dest.A = 255; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,187 @@ |
|||
// <copyright file="Bgra32.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.PixelFormats |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
/// <summary>
|
|||
/// Packed pixel type containing four 8-bit unsigned normalized values ranging from 0 to 255.
|
|||
/// The color components are stored in blue, green, red, and alpha order.
|
|||
/// </summary>
|
|||
[StructLayout(LayoutKind.Sequential)] |
|||
public struct Bgra32 : IPixel<Bgra32>, IPackedVector<uint> |
|||
{ |
|||
/// <summary>
|
|||
/// Gets or sets the blue component.
|
|||
/// </summary>
|
|||
public byte B; |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the green component.
|
|||
/// </summary>
|
|||
public byte G; |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the red component.
|
|||
/// </summary>
|
|||
public byte R; |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the alpha component.
|
|||
/// </summary>
|
|||
public byte A; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Bgra32"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="r">The red component.</param>
|
|||
/// <param name="g">The green component.</param>
|
|||
/// <param name="b">The blue component.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Bgra32(byte r, byte g, byte b) |
|||
{ |
|||
this.R = r; |
|||
this.G = g; |
|||
this.B = b; |
|||
this.A = 255; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Bgra32"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="r">The red component.</param>
|
|||
/// <param name="g">The green component.</param>
|
|||
/// <param name="b">The blue component.</param>
|
|||
/// <param name="a">The alpha component.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Bgra32(byte r, byte g, byte b, byte a) |
|||
{ |
|||
this.R = r; |
|||
this.G = g; |
|||
this.B = b; |
|||
this.A = a; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the packed representation of the Bgra32 struct.
|
|||
/// </summary>
|
|||
public uint Bgra |
|||
{ |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
get |
|||
{ |
|||
return Unsafe.As<Bgra32, uint>(ref this); |
|||
} |
|||
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
set |
|||
{ |
|||
Unsafe.As<Bgra32, uint>(ref this) = value; |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public uint PackedValue |
|||
{ |
|||
get => this.Bgra; |
|||
set => this.Bgra = value; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public PixelOperations<Bgra32> CreatePixelOperations() => new PixelOperations<Bgra32>(); |
|||
|
|||
/// <inheritdoc/>
|
|||
public bool Equals(Bgra32 other) |
|||
{ |
|||
return this.R == other.R && this.G == other.G && this.B == other.B && this.A == other.A; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object obj) => obj?.GetType() == typeof(Bgra32) && this.Equals((Bgra32)obj); |
|||
|
|||
/// <inheritdoc/>
|
|||
public override int GetHashCode() |
|||
{ |
|||
unchecked |
|||
{ |
|||
int hashCode = this.B; |
|||
hashCode = (hashCode * 397) ^ this.G; |
|||
hashCode = (hashCode * 397) ^ this.R; |
|||
hashCode = (hashCode * 397) ^ this.A; |
|||
return hashCode; |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void PackFromVector4(Vector4 vector) |
|||
{ |
|||
var rgba = default(Rgba32); |
|||
rgba.PackFromVector4(vector); |
|||
this.PackFromRgba32(rgba); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Vector4 ToVector4() |
|||
{ |
|||
return this.ToRgba32().ToVector4(); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void PackFromRgba32(Rgba32 source) |
|||
{ |
|||
this.R = source.R; |
|||
this.G = source.G; |
|||
this.B = source.B; |
|||
this.A = source.A; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void ToRgb24(ref Rgb24 dest) |
|||
{ |
|||
dest.R = this.R; |
|||
dest.G = this.G; |
|||
dest.B = this.B; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void ToRgba32(ref Rgba32 dest) |
|||
{ |
|||
dest.R = this.R; |
|||
dest.G = this.G; |
|||
dest.B = this.B; |
|||
dest.A = this.A; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void ToBgr24(ref Bgr24 dest) |
|||
{ |
|||
dest = Unsafe.As<Bgra32, Bgr24>(ref this); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void ToBgra32(ref Bgra32 dest) |
|||
{ |
|||
dest = this; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts the pixel to <see cref="Rgba32"/> format.
|
|||
/// </summary>
|
|||
/// <returns>The RGBA value</returns>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Rgba32 ToRgba32() => new Rgba32(this.R, this.G, this.B, this.A); |
|||
} |
|||
} |
|||
@ -0,0 +1,302 @@ |
|||
// <auto-generated />
|
|||
|
|||
// <copyright file="PixelOperations{TPixel}.Generated.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.PixelFormats |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
public partial class PixelOperations<TPixel> |
|||
{ |
|||
|
|||
/// <summary>
|
|||
/// Converts 'count' elements in 'source` span of <see cref="Rgba32"/> data to a span of <typeparamref name="TPixel"/>-s.
|
|||
/// </summary>
|
|||
/// <param name="source">The source <see cref="Span{T}"/> of <see cref="Rgba32"/> data.</param>
|
|||
/// <param name="destPixels">The <see cref="Span{T}"/> to the destination pixels.</param>
|
|||
/// <param name="count">The number of pixels to convert.</param>
|
|||
internal virtual void PackFromRgba32(Span<Rgba32> source, Span<TPixel> destPixels, int count) |
|||
{ |
|||
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); |
|||
|
|||
ref Rgba32 sourceRef = ref source.DangerousGetPinnableReference(); |
|||
ref TPixel destRef = ref destPixels.DangerousGetPinnableReference(); |
|||
|
|||
Rgba32 rgba = new Rgba32(0, 0, 0, 255); |
|||
|
|||
for (int i = 0; i < count; i++) |
|||
{ |
|||
ref TPixel dp = ref Unsafe.Add(ref destRef, i); |
|||
rgba = Unsafe.Add(ref sourceRef, i); |
|||
dp.PackFromRgba32(rgba); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// A helper for <see cref="PackFromRgba32(Span{Rgba32}, Span{TPixel}, int)"/> that expects a byte span.
|
|||
/// The layout of the data in 'sourceBytes' must be compatible with <see cref="Rgba32"/> layout.
|
|||
/// </summary>
|
|||
/// <param name="sourceBytes">The <see cref="Span{T}"/> to the source bytes.</param>
|
|||
/// <param name="destPixels">The <see cref="Span{T}"/> to the destination pixels.</param>
|
|||
/// <param name="count">The number of pixels to convert.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
internal void PackFromRgba32Bytes(Span<byte> sourceBytes, Span<TPixel> destPixels, int count) |
|||
{ |
|||
this.PackFromRgba32(sourceBytes.NonPortableCast<byte, Rgba32>(), destPixels, count); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts 'count' pixels in 'sourcePixels` span to a span of <see cref="Rgba32"/>-s.
|
|||
/// Bulk version of <see cref="IPixel.ToRgba32(ref Rgba32)"/>.
|
|||
/// </summary>
|
|||
/// <param name="sourcePixels">The span of source pixels</param>
|
|||
/// <param name="dest">The destination span of <see cref="Rgba32"/> data.</param>
|
|||
/// <param name="count">The number of pixels to convert.</param>
|
|||
internal virtual void ToRgba32(Span<TPixel> sourcePixels, Span<Rgba32> dest, int count) |
|||
{ |
|||
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); |
|||
|
|||
ref TPixel sourceBaseRef = ref sourcePixels.DangerousGetPinnableReference(); |
|||
ref Rgba32 destBaseRef = ref dest.DangerousGetPinnableReference(); |
|||
|
|||
for (int i = 0; i < count; i++) |
|||
{ |
|||
ref TPixel sp = ref Unsafe.Add(ref sourceBaseRef, i); |
|||
ref Rgba32 dp = ref Unsafe.Add(ref destBaseRef, i); |
|||
sp.ToRgba32(ref dp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// A helper for <see cref="ToRgba32(Span{TPixel}, Span{Rgba32}, int)"/> that expects a byte span as destination.
|
|||
/// The layout of the data in 'destBytes' must be compatible with <see cref="Rgba32"/> layout.
|
|||
/// </summary>
|
|||
/// <param name="sourceColors">The <see cref="Span{T}"/> to the source colors.</param>
|
|||
/// <param name="destBytes">The <see cref="Span{T}"/> to the destination bytes.</param>
|
|||
/// <param name="count">The number of pixels to convert.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
internal void ToRgba32Bytes(Span<TPixel> sourceColors, Span<byte> destBytes, int count) |
|||
{ |
|||
this.ToRgba32(sourceColors, destBytes.NonPortableCast<byte, Rgba32>(), count); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts 'count' elements in 'source` span of <see cref="Bgra32"/> data to a span of <typeparamref name="TPixel"/>-s.
|
|||
/// </summary>
|
|||
/// <param name="source">The source <see cref="Span{T}"/> of <see cref="Bgra32"/> data.</param>
|
|||
/// <param name="destPixels">The <see cref="Span{T}"/> to the destination pixels.</param>
|
|||
/// <param name="count">The number of pixels to convert.</param>
|
|||
internal virtual void PackFromBgra32(Span<Bgra32> source, Span<TPixel> destPixels, int count) |
|||
{ |
|||
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); |
|||
|
|||
ref Bgra32 sourceRef = ref source.DangerousGetPinnableReference(); |
|||
ref TPixel destRef = ref destPixels.DangerousGetPinnableReference(); |
|||
|
|||
Rgba32 rgba = new Rgba32(0, 0, 0, 255); |
|||
|
|||
for (int i = 0; i < count; i++) |
|||
{ |
|||
ref TPixel dp = ref Unsafe.Add(ref destRef, i); |
|||
rgba = Unsafe.Add(ref sourceRef, i).ToRgba32(); |
|||
dp.PackFromRgba32(rgba); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// A helper for <see cref="PackFromBgra32(Span{Bgra32}, Span{TPixel}, int)"/> that expects a byte span.
|
|||
/// The layout of the data in 'sourceBytes' must be compatible with <see cref="Bgra32"/> layout.
|
|||
/// </summary>
|
|||
/// <param name="sourceBytes">The <see cref="Span{T}"/> to the source bytes.</param>
|
|||
/// <param name="destPixels">The <see cref="Span{T}"/> to the destination pixels.</param>
|
|||
/// <param name="count">The number of pixels to convert.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
internal void PackFromBgra32Bytes(Span<byte> sourceBytes, Span<TPixel> destPixels, int count) |
|||
{ |
|||
this.PackFromBgra32(sourceBytes.NonPortableCast<byte, Bgra32>(), destPixels, count); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts 'count' pixels in 'sourcePixels` span to a span of <see cref="Bgra32"/>-s.
|
|||
/// Bulk version of <see cref="IPixel.ToBgra32(ref Bgra32)"/>.
|
|||
/// </summary>
|
|||
/// <param name="sourcePixels">The span of source pixels</param>
|
|||
/// <param name="dest">The destination span of <see cref="Bgra32"/> data.</param>
|
|||
/// <param name="count">The number of pixels to convert.</param>
|
|||
internal virtual void ToBgra32(Span<TPixel> sourcePixels, Span<Bgra32> dest, int count) |
|||
{ |
|||
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); |
|||
|
|||
ref TPixel sourceBaseRef = ref sourcePixels.DangerousGetPinnableReference(); |
|||
ref Bgra32 destBaseRef = ref dest.DangerousGetPinnableReference(); |
|||
|
|||
for (int i = 0; i < count; i++) |
|||
{ |
|||
ref TPixel sp = ref Unsafe.Add(ref sourceBaseRef, i); |
|||
ref Bgra32 dp = ref Unsafe.Add(ref destBaseRef, i); |
|||
sp.ToBgra32(ref dp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// A helper for <see cref="ToBgra32(Span{TPixel}, Span{Bgra32}, int)"/> that expects a byte span as destination.
|
|||
/// The layout of the data in 'destBytes' must be compatible with <see cref="Bgra32"/> layout.
|
|||
/// </summary>
|
|||
/// <param name="sourceColors">The <see cref="Span{T}"/> to the source colors.</param>
|
|||
/// <param name="destBytes">The <see cref="Span{T}"/> to the destination bytes.</param>
|
|||
/// <param name="count">The number of pixels to convert.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
internal void ToBgra32Bytes(Span<TPixel> sourceColors, Span<byte> destBytes, int count) |
|||
{ |
|||
this.ToBgra32(sourceColors, destBytes.NonPortableCast<byte, Bgra32>(), count); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts 'count' elements in 'source` span of <see cref="Rgb24"/> data to a span of <typeparamref name="TPixel"/>-s.
|
|||
/// </summary>
|
|||
/// <param name="source">The source <see cref="Span{T}"/> of <see cref="Rgb24"/> data.</param>
|
|||
/// <param name="destPixels">The <see cref="Span{T}"/> to the destination pixels.</param>
|
|||
/// <param name="count">The number of pixels to convert.</param>
|
|||
internal virtual void PackFromRgb24(Span<Rgb24> source, Span<TPixel> destPixels, int count) |
|||
{ |
|||
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); |
|||
|
|||
ref Rgb24 sourceRef = ref source.DangerousGetPinnableReference(); |
|||
ref TPixel destRef = ref destPixels.DangerousGetPinnableReference(); |
|||
|
|||
Rgba32 rgba = new Rgba32(0, 0, 0, 255); |
|||
|
|||
for (int i = 0; i < count; i++) |
|||
{ |
|||
ref TPixel dp = ref Unsafe.Add(ref destRef, i); |
|||
rgba.Rgb = Unsafe.Add(ref sourceRef, i); |
|||
dp.PackFromRgba32(rgba); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// A helper for <see cref="PackFromRgb24(Span{Rgb24}, Span{TPixel}, int)"/> that expects a byte span.
|
|||
/// The layout of the data in 'sourceBytes' must be compatible with <see cref="Rgb24"/> layout.
|
|||
/// </summary>
|
|||
/// <param name="sourceBytes">The <see cref="Span{T}"/> to the source bytes.</param>
|
|||
/// <param name="destPixels">The <see cref="Span{T}"/> to the destination pixels.</param>
|
|||
/// <param name="count">The number of pixels to convert.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
internal void PackFromRgb24Bytes(Span<byte> sourceBytes, Span<TPixel> destPixels, int count) |
|||
{ |
|||
this.PackFromRgb24(sourceBytes.NonPortableCast<byte, Rgb24>(), destPixels, count); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts 'count' pixels in 'sourcePixels` span to a span of <see cref="Rgb24"/>-s.
|
|||
/// Bulk version of <see cref="IPixel.ToRgb24(ref Rgb24)"/>.
|
|||
/// </summary>
|
|||
/// <param name="sourcePixels">The span of source pixels</param>
|
|||
/// <param name="dest">The destination span of <see cref="Rgb24"/> data.</param>
|
|||
/// <param name="count">The number of pixels to convert.</param>
|
|||
internal virtual void ToRgb24(Span<TPixel> sourcePixels, Span<Rgb24> dest, int count) |
|||
{ |
|||
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); |
|||
|
|||
ref TPixel sourceBaseRef = ref sourcePixels.DangerousGetPinnableReference(); |
|||
ref Rgb24 destBaseRef = ref dest.DangerousGetPinnableReference(); |
|||
|
|||
for (int i = 0; i < count; i++) |
|||
{ |
|||
ref TPixel sp = ref Unsafe.Add(ref sourceBaseRef, i); |
|||
ref Rgb24 dp = ref Unsafe.Add(ref destBaseRef, i); |
|||
sp.ToRgb24(ref dp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// A helper for <see cref="ToRgb24(Span{TPixel}, Span{Rgb24}, int)"/> that expects a byte span as destination.
|
|||
/// The layout of the data in 'destBytes' must be compatible with <see cref="Rgb24"/> layout.
|
|||
/// </summary>
|
|||
/// <param name="sourceColors">The <see cref="Span{T}"/> to the source colors.</param>
|
|||
/// <param name="destBytes">The <see cref="Span{T}"/> to the destination bytes.</param>
|
|||
/// <param name="count">The number of pixels to convert.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
internal void ToRgb24Bytes(Span<TPixel> sourceColors, Span<byte> destBytes, int count) |
|||
{ |
|||
this.ToRgb24(sourceColors, destBytes.NonPortableCast<byte, Rgb24>(), count); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts 'count' elements in 'source` span of <see cref="Bgr24"/> data to a span of <typeparamref name="TPixel"/>-s.
|
|||
/// </summary>
|
|||
/// <param name="source">The source <see cref="Span{T}"/> of <see cref="Bgr24"/> data.</param>
|
|||
/// <param name="destPixels">The <see cref="Span{T}"/> to the destination pixels.</param>
|
|||
/// <param name="count">The number of pixels to convert.</param>
|
|||
internal virtual void PackFromBgr24(Span<Bgr24> source, Span<TPixel> destPixels, int count) |
|||
{ |
|||
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); |
|||
|
|||
ref Bgr24 sourceRef = ref source.DangerousGetPinnableReference(); |
|||
ref TPixel destRef = ref destPixels.DangerousGetPinnableReference(); |
|||
|
|||
Rgba32 rgba = new Rgba32(0, 0, 0, 255); |
|||
|
|||
for (int i = 0; i < count; i++) |
|||
{ |
|||
ref TPixel dp = ref Unsafe.Add(ref destRef, i); |
|||
rgba.Bgr = Unsafe.Add(ref sourceRef, i); |
|||
dp.PackFromRgba32(rgba); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// A helper for <see cref="PackFromBgr24(Span{Bgr24}, Span{TPixel}, int)"/> that expects a byte span.
|
|||
/// The layout of the data in 'sourceBytes' must be compatible with <see cref="Bgr24"/> layout.
|
|||
/// </summary>
|
|||
/// <param name="sourceBytes">The <see cref="Span{T}"/> to the source bytes.</param>
|
|||
/// <param name="destPixels">The <see cref="Span{T}"/> to the destination pixels.</param>
|
|||
/// <param name="count">The number of pixels to convert.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
internal void PackFromBgr24Bytes(Span<byte> sourceBytes, Span<TPixel> destPixels, int count) |
|||
{ |
|||
this.PackFromBgr24(sourceBytes.NonPortableCast<byte, Bgr24>(), destPixels, count); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Converts 'count' pixels in 'sourcePixels` span to a span of <see cref="Bgr24"/>-s.
|
|||
/// Bulk version of <see cref="IPixel.ToBgr24(ref Bgr24)"/>.
|
|||
/// </summary>
|
|||
/// <param name="sourcePixels">The span of source pixels</param>
|
|||
/// <param name="dest">The destination span of <see cref="Bgr24"/> data.</param>
|
|||
/// <param name="count">The number of pixels to convert.</param>
|
|||
internal virtual void ToBgr24(Span<TPixel> sourcePixels, Span<Bgr24> dest, int count) |
|||
{ |
|||
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); |
|||
|
|||
ref TPixel sourceBaseRef = ref sourcePixels.DangerousGetPinnableReference(); |
|||
ref Bgr24 destBaseRef = ref dest.DangerousGetPinnableReference(); |
|||
|
|||
for (int i = 0; i < count; i++) |
|||
{ |
|||
ref TPixel sp = ref Unsafe.Add(ref sourceBaseRef, i); |
|||
ref Bgr24 dp = ref Unsafe.Add(ref destBaseRef, i); |
|||
sp.ToBgr24(ref dp); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// A helper for <see cref="ToBgr24(Span{TPixel}, Span{Bgr24}, int)"/> that expects a byte span as destination.
|
|||
/// The layout of the data in 'destBytes' must be compatible with <see cref="Bgr24"/> layout.
|
|||
/// </summary>
|
|||
/// <param name="sourceColors">The <see cref="Span{T}"/> to the source colors.</param>
|
|||
/// <param name="destBytes">The <see cref="Span{T}"/> to the destination bytes.</param>
|
|||
/// <param name="count">The number of pixels to convert.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
internal void ToBgr24Bytes(Span<TPixel> sourceColors, Span<byte> destBytes, int count) |
|||
{ |
|||
this.ToBgr24(sourceColors, destBytes.NonPortableCast<byte, Bgr24>(), count); |
|||
} |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,130 @@ |
|||
<# |
|||
// <copyright file="PixelOperations{TPixel}.Generated.tt" company="James Jackson-South"> |
|||
// Copyright (c) James Jackson-South and contributors. |
|||
// Licensed under the Apache License, Version 2.0. |
|||
// </copyright> |
|||
#> |
|||
<#@ template debug="false" hostspecific="false" language="C#" #> |
|||
<#@ assembly name="System.Core" #> |
|||
<#@ import namespace="System.Linq" #> |
|||
<#@ import namespace="System.Text" #> |
|||
<#@ import namespace="System.Collections.Generic" #> |
|||
<#@ output extension=".cs" #> |
|||
<# |
|||
void GenerateToDestFormatMethods(string pixelType) |
|||
{ |
|||
#> |
|||
|
|||
/// <summary> |
|||
/// Converts 'count' pixels in 'sourcePixels` span to a span of <see cref="<#=pixelType#>"/>-s. |
|||
/// Bulk version of <see cref="IPixel.To<#=pixelType#>(ref <#=pixelType#>)"/>. |
|||
/// </summary> |
|||
/// <param name="sourcePixels">The span of source pixels</param> |
|||
/// <param name="dest">The destination span of <see cref="<#=pixelType#>"/> data.</param> |
|||
/// <param name="count">The number of pixels to convert.</param> |
|||
internal virtual void To<#=pixelType#>(Span<TPixel> sourcePixels, Span<<#=pixelType#>> dest, int count) |
|||
{ |
|||
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); |
|||
|
|||
ref TPixel sourceBaseRef = ref sourcePixels.DangerousGetPinnableReference(); |
|||
ref <#=pixelType#> destBaseRef = ref dest.DangerousGetPinnableReference(); |
|||
|
|||
for (int i = 0; i < count; i++) |
|||
{ |
|||
ref TPixel sp = ref Unsafe.Add(ref sourceBaseRef, i); |
|||
ref <#=pixelType#> dp = ref Unsafe.Add(ref destBaseRef, i); |
|||
sp.To<#=pixelType#>(ref dp); |
|||
} |
|||
} |
|||
|
|||
/// <summary> |
|||
/// A helper for <see cref="To<#=pixelType#>(Span{TPixel}, Span{<#=pixelType#>}, int)"/> that expects a byte span as destination. |
|||
/// The layout of the data in 'destBytes' must be compatible with <see cref="<#=pixelType#>"/> layout. |
|||
/// </summary> |
|||
/// <param name="sourceColors">The <see cref="Span{T}"/> to the source colors.</param> |
|||
/// <param name="destBytes">The <see cref="Span{T}"/> to the destination bytes.</param> |
|||
/// <param name="count">The number of pixels to convert.</param> |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
internal void To<#=pixelType#>Bytes(Span<TPixel> sourceColors, Span<byte> destBytes, int count) |
|||
{ |
|||
this.To<#=pixelType#>(sourceColors, destBytes.NonPortableCast<byte, <#=pixelType#>>(), count); |
|||
} |
|||
<# |
|||
} |
|||
|
|||
void GeneratePackFromMethodUsingPackFromRgba32(string pixelType, string rgbaOperationCode) |
|||
{ |
|||
#> |
|||
|
|||
/// <summary> |
|||
/// Converts 'count' elements in 'source` span of <see cref="<#=pixelType#>"/> data to a span of <typeparamref name="TPixel"/>-s. |
|||
/// </summary> |
|||
/// <param name="source">The source <see cref="Span{T}"/> of <see cref="<#=pixelType#>"/> data.</param> |
|||
/// <param name="destPixels">The <see cref="Span{T}"/> to the destination pixels.</param> |
|||
/// <param name="count">The number of pixels to convert.</param> |
|||
internal virtual void PackFrom<#=pixelType#>(Span<<#=pixelType#>> source, Span<TPixel> destPixels, int count) |
|||
{ |
|||
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); |
|||
|
|||
ref <#=pixelType#> sourceRef = ref source.DangerousGetPinnableReference(); |
|||
ref TPixel destRef = ref destPixels.DangerousGetPinnableReference(); |
|||
|
|||
Rgba32 rgba = new Rgba32(0, 0, 0, 255); |
|||
|
|||
for (int i = 0; i < count; i++) |
|||
{ |
|||
ref TPixel dp = ref Unsafe.Add(ref destRef, i); |
|||
<#=rgbaOperationCode#> |
|||
dp.PackFromRgba32(rgba); |
|||
} |
|||
} |
|||
|
|||
/// <summary> |
|||
/// A helper for <see cref="PackFrom<#=pixelType#>(Span{<#=pixelType#>}, Span{TPixel}, int)"/> that expects a byte span. |
|||
/// The layout of the data in 'sourceBytes' must be compatible with <see cref="<#=pixelType#>"/> layout. |
|||
/// </summary> |
|||
/// <param name="sourceBytes">The <see cref="Span{T}"/> to the source bytes.</param> |
|||
/// <param name="destPixels">The <see cref="Span{T}"/> to the destination pixels.</param> |
|||
/// <param name="count">The number of pixels to convert.</param> |
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
internal void PackFrom<#=pixelType#>Bytes(Span<byte> sourceBytes, Span<TPixel> destPixels, int count) |
|||
{ |
|||
this.PackFrom<#=pixelType#>(sourceBytes.NonPortableCast<byte, <#=pixelType#>>(), destPixels, count); |
|||
} |
|||
<# |
|||
} |
|||
|
|||
#> |
|||
// <auto-generated /> |
|||
|
|||
// <copyright file="PixelOperations{TPixel}.Generated.cs" company="James Jackson-South"> |
|||
// Copyright (c) James Jackson-South and contributors. |
|||
// Licensed under the Apache License, Version 2.0. |
|||
// </copyright> |
|||
|
|||
namespace ImageSharp.PixelFormats |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
public partial class PixelOperations<TPixel> |
|||
{ |
|||
<# |
|||
|
|||
GeneratePackFromMethodUsingPackFromRgba32("Rgba32", "rgba = Unsafe.Add(ref sourceRef, i);"); |
|||
GenerateToDestFormatMethods("Rgba32"); |
|||
|
|||
GeneratePackFromMethodUsingPackFromRgba32("Bgra32", "rgba = Unsafe.Add(ref sourceRef, i).ToRgba32();"); |
|||
GenerateToDestFormatMethods("Bgra32"); |
|||
|
|||
GeneratePackFromMethodUsingPackFromRgba32("Rgb24", "rgba.Rgb = Unsafe.Add(ref sourceRef, i);"); |
|||
GenerateToDestFormatMethods("Rgb24"); |
|||
|
|||
GeneratePackFromMethodUsingPackFromRgba32("Bgr24", "rgba.Bgr = Unsafe.Add(ref sourceRef, i);"); |
|||
GenerateToDestFormatMethods("Bgr24"); |
|||
|
|||
#> |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,130 @@ |
|||
// <auto-generated />
|
|||
|
|||
// <copyright file="PixelOperations{TPixel}.Generated.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
using ImageSharp.Memory; |
|||
using ImageSharp.PixelFormats; |
|||
|
|||
/// <content>
|
|||
/// Provides optimized overrides for bulk operations.
|
|||
/// </content>
|
|||
public partial struct Rgba32 |
|||
{ |
|||
internal partial class PixelOperations : PixelOperations<Rgba32> |
|||
{ |
|||
|
|||
/// <inheritdoc />
|
|||
internal override void PackFromRgb24(Span<Rgb24> source, Span<Rgba32> destPixels, int count) |
|||
{ |
|||
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); |
|||
|
|||
ref Rgb24 sourceRef = ref source.DangerousGetPinnableReference(); |
|||
ref Rgba32 destRef = ref destPixels.DangerousGetPinnableReference(); |
|||
|
|||
for (int i = 0; i < count; i++) |
|||
{ |
|||
ref Rgb24 sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Rgba32 dp = ref Unsafe.Add(ref destRef, i); |
|||
Unsafe.As<Rgba32, Rgb24>(ref dp) = sp; dp.A = 255; |
|||
} |
|||
} |
|||
|
|||
|
|||
/// <inheritdoc />
|
|||
internal override void ToRgb24(Span<Rgba32> sourcePixels, Span<Rgb24> dest, int count) |
|||
{ |
|||
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); |
|||
|
|||
ref Rgba32 sourceRef = ref sourcePixels.DangerousGetPinnableReference(); |
|||
ref Rgb24 destRef = ref dest.DangerousGetPinnableReference(); |
|||
|
|||
for (int i = 0; i < count; i++) |
|||
{ |
|||
ref Rgba32 sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Rgb24 dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = Unsafe.As<Rgba32, Rgb24>(ref sp); |
|||
} |
|||
} |
|||
|
|||
|
|||
/// <inheritdoc />
|
|||
internal override void PackFromBgr24(Span<Bgr24> source, Span<Rgba32> destPixels, int count) |
|||
{ |
|||
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); |
|||
|
|||
ref Bgr24 sourceRef = ref source.DangerousGetPinnableReference(); |
|||
ref Rgba32 destRef = ref destPixels.DangerousGetPinnableReference(); |
|||
|
|||
for (int i = 0; i < count; i++) |
|||
{ |
|||
ref Bgr24 sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Rgba32 dp = ref Unsafe.Add(ref destRef, i); |
|||
dp.Bgr = sp; dp.A = 255; |
|||
} |
|||
} |
|||
|
|||
|
|||
/// <inheritdoc />
|
|||
internal override void ToBgr24(Span<Rgba32> sourcePixels, Span<Bgr24> dest, int count) |
|||
{ |
|||
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); |
|||
|
|||
ref Rgba32 sourceRef = ref sourcePixels.DangerousGetPinnableReference(); |
|||
ref Bgr24 destRef = ref dest.DangerousGetPinnableReference(); |
|||
|
|||
for (int i = 0; i < count; i++) |
|||
{ |
|||
ref Rgba32 sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Bgr24 dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = sp.Bgr; |
|||
} |
|||
} |
|||
|
|||
|
|||
/// <inheritdoc />
|
|||
internal override void PackFromBgra32(Span<Bgra32> source, Span<Rgba32> destPixels, int count) |
|||
{ |
|||
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); |
|||
|
|||
ref Bgra32 sourceRef = ref source.DangerousGetPinnableReference(); |
|||
ref Rgba32 destRef = ref destPixels.DangerousGetPinnableReference(); |
|||
|
|||
for (int i = 0; i < count; i++) |
|||
{ |
|||
ref Bgra32 sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Rgba32 dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = sp.ToRgba32(); |
|||
} |
|||
} |
|||
|
|||
|
|||
/// <inheritdoc />
|
|||
internal override void ToBgra32(Span<Rgba32> sourcePixels, Span<Bgra32> dest, int count) |
|||
{ |
|||
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); |
|||
|
|||
ref Rgba32 sourceRef = ref sourcePixels.DangerousGetPinnableReference(); |
|||
ref Bgra32 destRef = ref dest.DangerousGetPinnableReference(); |
|||
|
|||
for (int i = 0; i < count; i++) |
|||
{ |
|||
ref Rgba32 sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Bgra32 dp = ref Unsafe.Add(ref destRef, i); |
|||
dp = sp.ToBgra32(); |
|||
} |
|||
} |
|||
|
|||
|
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,99 @@ |
|||
<# |
|||
// <copyright file="Rgba32.PixelOperations.Generated.tt" company="James Jackson-South"> |
|||
// Copyright (c) James Jackson-South and contributors. |
|||
// Licensed under the Apache License, Version 2.0. |
|||
// </copyright> |
|||
#> |
|||
<#@ template debug="false" hostspecific="false" language="C#" #> |
|||
<#@ assembly name="System.Core" #> |
|||
<#@ import namespace="System.Linq" #> |
|||
<#@ import namespace="System.Text" #> |
|||
<#@ import namespace="System.Collections.Generic" #> |
|||
<#@ output extension=".cs" #> |
|||
<# |
|||
|
|||
void GeneratePackFromMethod(string pixelType, string converterCode) |
|||
{ |
|||
#> |
|||
|
|||
/// <inheritdoc /> |
|||
internal override void PackFrom<#=pixelType#>(Span<<#=pixelType#>> source, Span<Rgba32> destPixels, int count) |
|||
{ |
|||
GuardSpans(source, nameof(source), destPixels, nameof(destPixels), count); |
|||
|
|||
ref <#=pixelType#> sourceRef = ref source.DangerousGetPinnableReference(); |
|||
ref Rgba32 destRef = ref destPixels.DangerousGetPinnableReference(); |
|||
|
|||
for (int i = 0; i < count; i++) |
|||
{ |
|||
ref <#=pixelType#> sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref Rgba32 dp = ref Unsafe.Add(ref destRef, i); |
|||
<#=converterCode#> |
|||
} |
|||
} |
|||
|
|||
<# |
|||
} |
|||
|
|||
void GenerateConvertToMethod(string pixelType, string converterCode) |
|||
{ |
|||
#> |
|||
|
|||
/// <inheritdoc /> |
|||
internal override void To<#=pixelType#>(Span<Rgba32> sourcePixels, Span<<#=pixelType#>> dest, int count) |
|||
{ |
|||
GuardSpans(sourcePixels, nameof(sourcePixels), dest, nameof(dest), count); |
|||
|
|||
ref Rgba32 sourceRef = ref sourcePixels.DangerousGetPinnableReference(); |
|||
ref <#=pixelType#> destRef = ref dest.DangerousGetPinnableReference(); |
|||
|
|||
for (int i = 0; i < count; i++) |
|||
{ |
|||
ref Rgba32 sp = ref Unsafe.Add(ref sourceRef, i); |
|||
ref <#=pixelType#> dp = ref Unsafe.Add(ref destRef, i); |
|||
<#=converterCode#> |
|||
} |
|||
} |
|||
|
|||
<# |
|||
} |
|||
|
|||
#> |
|||
// <auto-generated /> |
|||
|
|||
// <copyright file="PixelOperations{TPixel}.Generated.cs" company="James Jackson-South"> |
|||
// Copyright (c) James Jackson-South and contributors. |
|||
// Licensed under the Apache License, Version 2.0. |
|||
// </copyright> |
|||
|
|||
namespace ImageSharp |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
using ImageSharp.Memory; |
|||
using ImageSharp.PixelFormats; |
|||
|
|||
/// <content> |
|||
/// Provides optimized overrides for bulk operations. |
|||
/// </content> |
|||
public partial struct Rgba32 |
|||
{ |
|||
internal partial class PixelOperations : PixelOperations<Rgba32> |
|||
{ |
|||
<# |
|||
GeneratePackFromMethod("Rgb24", "Unsafe.As<Rgba32, Rgb24>(ref dp) = sp; dp.A = 255;"); |
|||
GenerateConvertToMethod("Rgb24", "dp = Unsafe.As<Rgba32, Rgb24>(ref sp);"); |
|||
|
|||
GeneratePackFromMethod("Bgr24", "dp.Bgr = sp; dp.A = 255;"); |
|||
GenerateConvertToMethod("Bgr24", "dp = sp.Bgr;"); |
|||
|
|||
GeneratePackFromMethod("Bgra32", "dp = sp.ToRgba32();"); |
|||
GenerateConvertToMethod("Bgra32", "dp = sp.ToBgra32();"); |
|||
#> |
|||
|
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,76 @@ |
|||
namespace ImageSharp.PixelFormats |
|||
{ |
|||
using System; |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
/// <summary>
|
|||
/// Extension methods for copying single pixel data into byte Spans.
|
|||
/// TODO: This utility class exists for legacy reasons. Need to do a lot of chore work to remove it (mostly in test classes).
|
|||
/// </summary>
|
|||
internal static class PixelConversionExtensions |
|||
{ |
|||
/// <summary>
|
|||
/// Expands the packed representation into a given byte array.
|
|||
/// Output is expanded to X-> Y-> Z order. Equivalent to R-> G-> B in <see cref="Rgb24"/>
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The pixel type.</typeparam>
|
|||
/// <param name="pixel">The pixel to copy the data from.</param>
|
|||
/// <param name="bytes">The bytes to set the color in.</param>
|
|||
/// <param name="startIndex">The starting index of the <paramref name="bytes"/>.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void ToXyzBytes<TPixel>(this TPixel pixel, Span<byte> bytes, int startIndex) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
ref Rgb24 dest = ref bytes.GetRgb24(startIndex); |
|||
pixel.ToRgb24(ref dest); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Expands the packed representation into a given byte array.
|
|||
/// Output is expanded to X-> Y-> Z-> W order. Equivalent to R-> G-> B-> A in <see cref="Rgba32"/>
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The pixel type.</typeparam>
|
|||
/// <param name="pixel">The pixel to copy the data from.</param>
|
|||
/// <param name="bytes">The bytes to set the color in.</param>
|
|||
/// <param name="startIndex">The starting index of the <paramref name="bytes"/>.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void ToXyzwBytes<TPixel>(this TPixel pixel, Span<byte> bytes, int startIndex) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
ref Rgba32 dest = ref Unsafe.As<byte, Rgba32>(ref bytes[startIndex]); |
|||
pixel.ToRgba32(ref dest); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Expands the packed representation into a given byte array.
|
|||
/// Output is expanded to Z-> Y-> X order. Equivalent to B-> G-> R in <see cref="Bgr24"/>
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The pixel type.</typeparam>
|
|||
/// <param name="pixel">The pixel to copy the data from.</param>
|
|||
/// <param name="bytes">The bytes to set the color in.</param>
|
|||
/// <param name="startIndex">The starting index of the <paramref name="bytes"/>.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void ToZyxBytes<TPixel>(this TPixel pixel, Span<byte> bytes, int startIndex) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
ref Bgr24 dest = ref Unsafe.As<byte, Bgr24>(ref bytes[startIndex]); |
|||
pixel.ToBgr24(ref dest); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Expands the packed representation into a given byte array.
|
|||
/// Output is expanded to Z-> Y-> X-> W order. Equivalent to B-> G-> R-> A in <see cref="Bgra32"/>
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The pixel type.</typeparam>
|
|||
/// <param name="pixel">The pixel to copy the data from.</param>
|
|||
/// <param name="bytes">The bytes to set the color in.</param>
|
|||
/// <param name="startIndex">The starting index of the <paramref name="bytes"/>.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public static void ToZyxwBytes<TPixel>(this TPixel pixel, Span<byte> bytes, int startIndex) |
|||
where TPixel : struct, IPixel<TPixel> |
|||
{ |
|||
ref Bgra32 dest = ref Unsafe.As<byte, Bgra32>(ref bytes[startIndex]); |
|||
pixel.ToBgra32(ref dest); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,132 @@ |
|||
// <copyright file="Rgb24.cs" company="James Jackson-South">
|
|||
// Copyright (c) James Jackson-South and contributors.
|
|||
// Licensed under the Apache License, Version 2.0.
|
|||
// </copyright>
|
|||
|
|||
namespace ImageSharp.PixelFormats |
|||
{ |
|||
using System; |
|||
using System.Numerics; |
|||
using System.Runtime.CompilerServices; |
|||
using System.Runtime.InteropServices; |
|||
|
|||
/// <summary>
|
|||
/// Pixel type containing three 8-bit unsigned normalized values ranging from 0 to 255.
|
|||
/// The color components are stored in red, green, blue order.
|
|||
/// </summary>
|
|||
[StructLayout(LayoutKind.Sequential)] |
|||
public struct Rgb24 : IPixel<Rgb24> |
|||
{ |
|||
/// <summary>
|
|||
/// The red component.
|
|||
/// </summary>
|
|||
public byte R; |
|||
|
|||
/// <summary>
|
|||
/// The green component.
|
|||
/// </summary>
|
|||
public byte G; |
|||
|
|||
/// <summary>
|
|||
/// The blue component.
|
|||
/// </summary>
|
|||
public byte B; |
|||
|
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="Rgb24"/> struct.
|
|||
/// </summary>
|
|||
/// <param name="r">The red component.</param>
|
|||
/// <param name="g">The green component.</param>
|
|||
/// <param name="b">The blue component.</param>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Rgb24(byte r, byte g, byte b) |
|||
{ |
|||
this.R = r; |
|||
this.G = g; |
|||
this.B = b; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public PixelOperations<Rgb24> CreatePixelOperations() => new PixelOperations<Rgb24>(); |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public bool Equals(Rgb24 other) |
|||
{ |
|||
return this.R == other.R && this.G == other.G && this.B == other.B; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public override bool Equals(object obj) |
|||
{ |
|||
return obj?.GetType() == typeof(Rgb24) && this.Equals((Rgb24)obj); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public override int GetHashCode() |
|||
{ |
|||
unchecked |
|||
{ |
|||
int hashCode = this.R; |
|||
hashCode = (hashCode * 397) ^ this.G; |
|||
hashCode = (hashCode * 397) ^ this.B; |
|||
return hashCode; |
|||
} |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void PackFromRgba32(Rgba32 source) |
|||
{ |
|||
this = Unsafe.As<Rgba32, Rgb24>(ref source); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void PackFromVector4(Vector4 vector) |
|||
{ |
|||
var rgba = default(Rgba32); |
|||
rgba.PackFromVector4(vector); |
|||
this.PackFromRgba32(rgba); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public Vector4 ToVector4() |
|||
{ |
|||
return new Rgba32(this.R, this.G, this.B, 255).ToVector4(); |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|||
public void ToRgb24(ref Rgb24 dest) |
|||
{ |
|||
dest = this; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public void ToRgba32(ref Rgba32 dest) |
|||
{ |
|||
dest.Rgb = this; |
|||
dest.A = 255; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public void ToBgr24(ref Bgr24 dest) |
|||
{ |
|||
dest.R = this.R; |
|||
dest.G = this.G; |
|||
dest.B = this.B; |
|||
} |
|||
|
|||
/// <inheritdoc/>
|
|||
public void ToBgra32(ref Bgra32 dest) |
|||
{ |
|||
dest.R = this.R; |
|||
dest.G = this.G; |
|||
dest.B = this.B; |
|||
dest.A = 255; |
|||
} |
|||
} |
|||
} |
|||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue