mirror of https://github.com/SixLabors/ImageSharp
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
179 lines
8.6 KiB
179 lines
8.6 KiB
// Copyright (c) Six Labors and contributors.
|
|
// Licensed under the GNU Affero General Public License, Version 3.
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using SixLabors.ImageSharp.Formats;
|
|
using SixLabors.ImageSharp.Memory;
|
|
using SixLabors.ImageSharp.PixelFormats;
|
|
|
|
namespace SixLabors.ImageSharp.Advanced
|
|
{
|
|
/// <summary>
|
|
/// Extension methods over Image{TPixel}
|
|
/// </summary>
|
|
public static class AdvancedImageExtensions
|
|
{
|
|
/// <summary>
|
|
/// For a given path find the best encoder to use
|
|
/// </summary>
|
|
/// <param name="source">The source.</param>
|
|
/// <param name="path">The Path</param>
|
|
/// <returns>The matching encoder.</returns>
|
|
public static IImageEncoder FindEncoded(this Image source, string path)
|
|
{
|
|
Guard.NotNull(path, nameof(path));
|
|
|
|
string ext = Path.GetExtension(path);
|
|
IImageFormat format = source.GetConfiguration().ImageFormatsManager.FindFormatByFileExtension(ext);
|
|
if (format is null)
|
|
{
|
|
var sb = new StringBuilder();
|
|
sb.AppendLine($"No encoder was found for extension '{ext}'. Registered encoders include:");
|
|
foreach (IImageFormat fmt in source.GetConfiguration().ImageFormats)
|
|
{
|
|
sb.AppendFormat(" - {0} : {1}{2}", fmt.Name, string.Join(", ", fmt.FileExtensions), Environment.NewLine);
|
|
}
|
|
|
|
throw new NotSupportedException(sb.ToString());
|
|
}
|
|
|
|
IImageEncoder encoder = source.GetConfiguration().ImageFormatsManager.FindEncoder(format);
|
|
|
|
if (encoder is null)
|
|
{
|
|
var sb = new StringBuilder();
|
|
sb.AppendLine($"No encoder was found for extension '{ext}' using image format '{format.Name}'. Registered encoders include:");
|
|
foreach (KeyValuePair<IImageFormat, IImageEncoder> enc in source.GetConfiguration().ImageFormatsManager.ImageEncoders)
|
|
{
|
|
sb.AppendFormat(" - {0} : {1}{2}", enc.Key, enc.Value.GetType().Name, Environment.NewLine);
|
|
}
|
|
|
|
throw new NotSupportedException(sb.ToString());
|
|
}
|
|
|
|
return encoder;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Accepts a <see cref="IImageVisitor"/> to implement a double-dispatch pattern in order to
|
|
/// apply pixel-specific operations on non-generic <see cref="Image"/> instances
|
|
/// </summary>
|
|
/// <param name="source">The source.</param>
|
|
/// <param name="visitor">The visitor.</param>
|
|
public static void AcceptVisitor(this Image source, IImageVisitor visitor)
|
|
=> source.Accept(visitor);
|
|
|
|
/// <summary>
|
|
/// Accepts a <see cref="IImageVisitor"/> to implement a double-dispatch pattern in order to
|
|
/// apply pixel-specific operations on non-generic <see cref="Image"/> instances
|
|
/// </summary>
|
|
/// <param name="source">The source.</param>
|
|
/// <param name="visitor">The visitor.</param>
|
|
public static Task AcceptVisitorAsync(this Image source, IImageVisitorAsync visitor)
|
|
=> source.AcceptAsync(visitor);
|
|
|
|
/// <summary>
|
|
/// Gets the configuration for the image.
|
|
/// </summary>
|
|
/// <param name="source">The source image.</param>
|
|
/// <returns>Returns the configuration.</returns>
|
|
public static Configuration GetConfiguration(this Image source)
|
|
=> GetConfiguration((IConfigurationProvider)source);
|
|
|
|
/// <summary>
|
|
/// Gets the configuration for the image frame.
|
|
/// </summary>
|
|
/// <param name="source">The source image.</param>
|
|
/// <returns>Returns the configuration.</returns>
|
|
public static Configuration GetConfiguration(this ImageFrame source)
|
|
=> GetConfiguration((IConfigurationProvider)source);
|
|
|
|
/// <summary>
|
|
/// Gets the configuration.
|
|
/// </summary>
|
|
/// <param name="source">The source image</param>
|
|
/// <returns>Returns the bounds of the image</returns>
|
|
private static Configuration GetConfiguration(IConfigurationProvider source)
|
|
=> source?.Configuration ?? Configuration.Default;
|
|
|
|
/// <summary>
|
|
/// Gets the representation of the pixels as a <see cref="IMemoryGroup{T}"/> containing the backing pixel data of the image
|
|
/// stored in row major order, as a list of contiguous <see cref="Memory{T}"/> blocks in the source image's pixel format.
|
|
/// </summary>
|
|
/// <param name="source">The source image.</param>
|
|
/// <typeparam name="TPixel">The type of the pixel.</typeparam>
|
|
/// <returns>The <see cref="IMemoryGroup{T}"/>.</returns>
|
|
/// <remarks>
|
|
/// Certain Image Processors may invalidate the returned <see cref="IMemoryGroup{T}"/> and all it's buffers,
|
|
/// therefore it's not recommended to mutate the image while holding a reference to it's <see cref="IMemoryGroup{T}"/>.
|
|
/// </remarks>
|
|
public static IMemoryGroup<TPixel> GetPixelMemoryGroup<TPixel>(this ImageFrame<TPixel> source)
|
|
where TPixel : unmanaged, IPixel<TPixel>
|
|
=> source?.PixelBuffer.FastMemoryGroup.View ?? throw new ArgumentNullException(nameof(source));
|
|
|
|
/// <summary>
|
|
/// Gets the representation of the pixels as a <see cref="IMemoryGroup{T}"/> containing the backing pixel data of the image
|
|
/// stored in row major order, as a list of contiguous <see cref="Memory{T}"/> blocks in the source image's pixel format.
|
|
/// </summary>
|
|
/// <param name="source">The source image.</param>
|
|
/// <typeparam name="TPixel">The type of the pixel.</typeparam>
|
|
/// <returns>The <see cref="IMemoryGroup{T}"/>.</returns>
|
|
/// <remarks>
|
|
/// Certain Image Processors may invalidate the returned <see cref="IMemoryGroup{T}"/> and all it's buffers,
|
|
/// therefore it's not recommended to mutate the image while holding a reference to it's <see cref="IMemoryGroup{T}"/>.
|
|
/// </remarks>
|
|
public static IMemoryGroup<TPixel> GetPixelMemoryGroup<TPixel>(this Image<TPixel> source)
|
|
where TPixel : unmanaged, IPixel<TPixel>
|
|
=> source?.Frames.RootFrame.GetPixelMemoryGroup() ?? throw new ArgumentNullException(nameof(source));
|
|
|
|
/// <summary>
|
|
/// Gets the representation of the pixels as a <see cref="Span{T}"/> of contiguous memory
|
|
/// at row <paramref name="rowIndex"/> beginning from the the first pixel on that row.
|
|
/// </summary>
|
|
/// <typeparam name="TPixel">The type of the pixel.</typeparam>
|
|
/// <param name="source">The source.</param>
|
|
/// <param name="rowIndex">The row.</param>
|
|
/// <returns>The <see cref="Span{TPixel}"/></returns>
|
|
public static Memory<TPixel> GetPixelRowMemory<TPixel>(this ImageFrame<TPixel> source, int rowIndex)
|
|
where TPixel : unmanaged, IPixel<TPixel>
|
|
{
|
|
Guard.NotNull(source, nameof(source));
|
|
Guard.MustBeGreaterThanOrEqualTo(rowIndex, 0, nameof(rowIndex));
|
|
Guard.MustBeLessThan(rowIndex, source.Height, nameof(rowIndex));
|
|
|
|
return source.PixelBuffer.GetSafeRowMemory(rowIndex);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the representation of the pixels as <see cref="Span{T}"/> of of contiguous memory
|
|
/// at row <paramref name="rowIndex"/> beginning from the the first pixel on that row.
|
|
/// </summary>
|
|
/// <typeparam name="TPixel">The type of the pixel.</typeparam>
|
|
/// <param name="source">The source.</param>
|
|
/// <param name="rowIndex">The row.</param>
|
|
/// <returns>The <see cref="Span{TPixel}"/></returns>
|
|
public static Memory<TPixel> GetPixelRowMemory<TPixel>(this Image<TPixel> source, int rowIndex)
|
|
where TPixel : unmanaged, IPixel<TPixel>
|
|
{
|
|
Guard.NotNull(source, nameof(source));
|
|
Guard.MustBeGreaterThanOrEqualTo(rowIndex, 0, nameof(rowIndex));
|
|
Guard.MustBeLessThan(rowIndex, source.Height, nameof(rowIndex));
|
|
|
|
return source.Frames.RootFrame.PixelBuffer.GetSafeRowMemory(rowIndex);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the <see cref="MemoryAllocator"/> assigned to 'source'.
|
|
/// </summary>
|
|
/// <param name="source">The source image.</param>
|
|
/// <returns>Returns the configuration.</returns>
|
|
internal static MemoryAllocator GetMemoryAllocator(this IConfigurationProvider source)
|
|
=> GetConfiguration(source).MemoryAllocator;
|
|
}
|
|
}
|
|
|