// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
using System.Numerics;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Processing.Processors;
using SixLabors.ImageSharp.Tests.Memory;
using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison;
namespace SixLabors.ImageSharp.Tests;
public static class TestImageExtensions
{
///
/// TODO: Consider adding this private processor to the library
///
/// The image processing context.
public static void MakeOpaque(this IImageProcessingContext ctx) =>
ctx.ApplyProcessor(new MakeOpaqueProcessor());
public static void DebugSave(
this Image image,
ITestImageProvider provider,
FormattableString testOutputDetails,
string extension = "png",
bool appendPixelTypeToFileName = true,
bool appendSourceFileOrDescription = true,
IImageEncoder encoder = null)
=> image.DebugSave(
provider,
(object)testOutputDetails,
extension,
appendPixelTypeToFileName,
appendSourceFileOrDescription,
encoder);
///
/// Saves the image for debugging purpose.
///
/// The image.
/// The image provider.
/// Details to be concatenated to the test output file, describing the parameters of the test.
/// The extension.
/// A boolean indicating whether to append the pixel type to the output file name.
/// A boolean indicating whether to append to the test output file name.
/// Custom encoder to use.
/// The input image.
public static Image DebugSave(
this Image image,
ITestImageProvider provider,
object testOutputDetails = null,
string extension = "png",
bool appendPixelTypeToFileName = true,
bool appendSourceFileOrDescription = true,
IImageEncoder encoder = null)
{
provider.Utility.SaveTestOutputFile(
image,
extension,
encoder: encoder,
testOutputDetails: testOutputDetails,
appendPixelTypeToFileName: appendPixelTypeToFileName,
appendSourceFileOrDescription: appendSourceFileOrDescription);
return image;
}
public static void DebugSave(
this Image image,
ITestImageProvider provider,
IImageEncoder encoder,
FormattableString testOutputDetails,
bool appendPixelTypeToFileName = true)
=> image.DebugSave(provider, encoder, (object)testOutputDetails, appendPixelTypeToFileName);
///
/// Saves the image for debugging purpose.
///
/// The image
/// The image provider
/// The image encoder
/// Details to be concatenated to the test output file, describing the parameters of the test.
/// A boolean indicating whether to append the pixel type to the output file name.
public static void DebugSave(
this Image image,
ITestImageProvider provider,
IImageEncoder encoder,
object testOutputDetails = null,
bool appendPixelTypeToFileName = true)
=> provider.Utility.SaveTestOutputFile(
image,
encoder: encoder,
testOutputDetails: testOutputDetails,
appendPixelTypeToFileName: appendPixelTypeToFileName);
public static Image DebugSaveMultiFrame(
this Image image,
ITestImageProvider provider,
object testOutputDetails = null,
string extension = "png",
IImageEncoder encoder = null,
bool appendPixelTypeToFileName = true,
Func predicate = null)
where TPixel : unmanaged, IPixel
{
provider.Utility.SaveTestOutputFileMultiFrame(
image,
extension,
encoder: encoder,
testOutputDetails: testOutputDetails,
appendPixelTypeToFileName: appendPixelTypeToFileName,
predicate: predicate);
return image;
}
public static Image CompareToReferenceOutput(
this Image image,
ITestImageProvider provider,
FormattableString testOutputDetails,
string extension = "png",
bool grayscale = false,
bool appendPixelTypeToFileName = true,
bool appendSourceFileOrDescription = true)
where TPixel : unmanaged, IPixel
=> image.CompareToReferenceOutput(
provider,
(object)testOutputDetails,
extension,
grayscale,
appendPixelTypeToFileName,
appendSourceFileOrDescription);
///
/// Compares the image against the expected Reference output, throws an exception if the images are not similar enough.
/// The output file should be named identically to the output produced by .
///
/// The pixel format.
/// The image which should be compared to the reference image.
/// The image provider.
/// Details to be concatenated to the test output file, describing the parameters of the test.
/// The extension
/// A boolean indicating whether we should debug save + compare against a grayscale image, smaller in size.
/// A boolean indicating whether to append the pixel type to the output file name.
/// A boolean indicating whether to append to the test output file name.
/// The image.
public static Image CompareToReferenceOutput(
this Image image,
ITestImageProvider provider,
object testOutputDetails = null,
string extension = "png",
bool grayscale = false,
bool appendPixelTypeToFileName = true,
bool appendSourceFileOrDescription = true)
where TPixel : unmanaged, IPixel
=> CompareToReferenceOutput(
image,
ImageComparer.Tolerant(),
provider,
testOutputDetails,
extension,
grayscale,
appendPixelTypeToFileName,
appendSourceFileOrDescription);
public static Image CompareToReferenceOutput(
this Image image,
ImageComparer comparer,
ITestImageProvider provider,
FormattableString testOutputDetails,
string extension = "png",
bool grayscale = false,
bool appendPixelTypeToFileName = true)
where TPixel : unmanaged, IPixel
=> image.CompareToReferenceOutput(
comparer,
provider,
(object)testOutputDetails,
extension,
grayscale,
appendPixelTypeToFileName);
///
/// Compares the image against the expected Reference output, throws an exception if the images are not similar enough.
/// The output file should be named identically to the output produced by .
///
/// The pixel format.
/// The image which should be compared to the reference output.
/// The to use.
/// The image provider.
/// Details to be concatenated to the test output file, describing the parameters of the test.
/// The extension
/// A boolean indicating whether we should debug save + compare against a grayscale image, smaller in size.
/// A boolean indicating whether to append the pixel type to the output file name.
/// A boolean indicating whether to append to the test output file name.
/// A custom decoder.
/// The image.
public static Image CompareToReferenceOutput(
this Image image,
ImageComparer comparer,
ITestImageProvider provider,
object testOutputDetails = null,
string extension = "png",
bool grayscale = false,
bool appendPixelTypeToFileName = true,
bool appendSourceFileOrDescription = true,
IImageDecoder decoder = null)
where TPixel : unmanaged, IPixel
{
using (Image referenceImage = GetReferenceOutputImage(
provider,
testOutputDetails,
extension,
appendPixelTypeToFileName,
appendSourceFileOrDescription,
decoder))
{
comparer.VerifySimilarity(referenceImage, image);
}
return image;
}
public static Image CompareFirstFrameToReferenceOutput(
this Image image,
ImageComparer comparer,
ITestImageProvider provider,
FormattableString testOutputDetails,
string extension = "png",
bool appendPixelTypeToFileName = true,
bool appendSourceFileOrDescription = true)
where TPixel : unmanaged, IPixel
=> image.CompareFirstFrameToReferenceOutput(
comparer,
provider,
(object)testOutputDetails,
extension,
appendPixelTypeToFileName,
appendSourceFileOrDescription);
public static Image CompareFirstFrameToReferenceOutput(
this Image image,
ImageComparer comparer,
ITestImageProvider provider,
object testOutputDetails = null,
string extension = "png",
bool appendPixelTypeToFileName = true,
bool appendSourceFileOrDescription = true)
where TPixel : unmanaged, IPixel
{
using (Image firstFrameOnlyImage = new(image.Width, image.Height))
using (Image referenceImage = GetReferenceOutputImage(
provider,
testOutputDetails,
extension,
appendPixelTypeToFileName,
appendSourceFileOrDescription))
{
firstFrameOnlyImage.Frames.AddFrame(image.Frames.RootFrame);
firstFrameOnlyImage.Frames.RemoveFrame(0);
comparer.VerifySimilarity(referenceImage, firstFrameOnlyImage);
}
return image;
}
public static Image CompareDebugOutputToReferenceOutputMultiFrame(
this Image image,
ITestImageProvider provider,
ImageComparer comparer,
object testOutputDetails = null,
string extension = "png",
IImageEncoder encoder = null,
bool appendPixelTypeToFileName = true,
Func predicate = null)
where TPixel : unmanaged, IPixel
{
image.DebugSaveMultiFrame(
provider,
testOutputDetails,
extension,
encoder,
appendPixelTypeToFileName,
predicate: predicate);
using Image debugImage = GetDebugOutputImageMultiFrame(
provider,
image.Frames.Count,
testOutputDetails,
extension,
appendPixelTypeToFileName,
predicate: predicate);
using Image referenceImage = GetReferenceOutputImageMultiFrame(
provider,
image.Frames.Count,
testOutputDetails,
extension,
appendPixelTypeToFileName,
predicate: predicate);
comparer.VerifySimilarity(referenceImage, debugImage);
return image;
}
public static Image CompareToReferenceOutputMultiFrame(
this Image image,
ITestImageProvider provider,
ImageComparer comparer,
object testOutputDetails = null,
string extension = "png",
bool appendPixelTypeToFileName = true,
Func predicate = null)
where TPixel : unmanaged, IPixel
{
using (Image referenceImage = GetReferenceOutputImageMultiFrame(
provider,
image.Frames.Count,
testOutputDetails,
extension,
appendPixelTypeToFileName,
predicate: predicate))
{
comparer.VerifySimilarity(referenceImage, image, predicate);
}
return image;
}
public static Image GetReferenceOutputImage(
this ITestImageProvider provider,
object testOutputDetails = null,
string extension = "png",
bool appendPixelTypeToFileName = true,
bool appendSourceFileOrDescription = true,
IImageDecoder decoder = null)
where TPixel : unmanaged, IPixel
{
string referenceOutputFile = provider.Utility.GetReferenceOutputFileName(
extension,
testOutputDetails,
appendPixelTypeToFileName,
appendSourceFileOrDescription);
if (!File.Exists(referenceOutputFile))
{
throw new FileNotFoundException("Reference output file missing: " + referenceOutputFile, referenceOutputFile);
}
decoder ??= TestEnvironment.GetReferenceDecoder(referenceOutputFile);
using FileStream stream = File.OpenRead(referenceOutputFile);
return decoder.Decode(DecoderOptions.Default, stream);
}
public static Image GetReferenceOutputImageMultiFrame(
this ITestImageProvider provider,
int frameCount,
object testOutputDetails = null,
string extension = "png",
bool appendPixelTypeToFileName = true,
Func predicate = null)
where TPixel : unmanaged, IPixel
{
(int Index, string FileName)[] frameFiles = provider.Utility.GetReferenceOutputFileNamesMultiFrame(
frameCount,
extension,
testOutputDetails,
appendPixelTypeToFileName,
predicate);
List> temporaryFrameImages = new();
IImageDecoder decoder = TestEnvironment.GetReferenceDecoder(frameFiles[0].FileName);
for (int i = 0; i < frameFiles.Length; i++)
{
string path = frameFiles[i].FileName;
if (!File.Exists(path))
{
throw new FileNotFoundException("Reference output file missing: " + path);
}
using FileStream stream = File.OpenRead(path);
Image tempImage = decoder.Decode(DecoderOptions.Default, stream);
temporaryFrameImages.Add(tempImage);
}
Image firstTemp = temporaryFrameImages[0];
Image result = new(firstTemp.Width, firstTemp.Height);
foreach (Image fi in temporaryFrameImages)
{
result.Frames.AddFrame(fi.Frames.RootFrame);
fi.Dispose();
}
// Remove the initial empty frame:
result.Frames.RemoveFrame(0);
return result;
}
public static Image GetDebugOutputImageMultiFrame(
this ITestImageProvider provider,
int frameCount,
object testOutputDetails = null,
string extension = "png",
bool appendPixelTypeToFileName = true,
Func predicate = null)
where TPixel : unmanaged, IPixel
{
(int Index, string FileName)[] frameFiles = [.. provider.Utility.GetTestOutputFileNamesMultiFrame(
frameCount,
extension,
testOutputDetails,
appendPixelTypeToFileName,
predicate: predicate)];
List> temporaryFrameImages = [];
IImageDecoder decoder = TestEnvironment.GetReferenceDecoder(frameFiles[0].FileName);
for (int i = 0; i < frameFiles.Length; i++)
{
string path = frameFiles[i].FileName;
if (!File.Exists(path))
{
throw new FileNotFoundException("Reference output file missing: " + path);
}
using FileStream stream = File.OpenRead(path);
Image tempImage = decoder.Decode(DecoderOptions.Default, stream);
temporaryFrameImages.Add(tempImage);
}
Image firstTemp = temporaryFrameImages[0];
Image result = new(firstTemp.Width, firstTemp.Height);
foreach (Image fi in temporaryFrameImages)
{
result.Frames.AddFrame(fi.Frames.RootFrame);
fi.Dispose();
}
// Remove the initial empty frame:
result.Frames.RemoveFrame(0);
return result;
}
public static IEnumerable GetReferenceOutputSimilarityReports(
this Image image,
ITestImageProvider provider,
ImageComparer comparer,
object testOutputDetails = null,
string extension = "png",
bool appendPixelTypeToFileName = true)
where TPixel : unmanaged, IPixel
{
using Image referenceImage = provider.GetReferenceOutputImage(
testOutputDetails,
extension,
appendPixelTypeToFileName);
return comparer.CompareImages(referenceImage, image);
}
public static Image ComparePixelBufferTo(
this Image image,
Span expectedPixels)
where TPixel : unmanaged, IPixel
{
Assert.True(image.DangerousTryGetSinglePixelMemory(out Memory actualPixels));
CompareBuffers(expectedPixels, actualPixels.Span);
return image;
}
public static Image ComparePixelBufferTo(
this Image image,
Memory expectedPixels)
where TPixel : unmanaged, IPixel =>
ComparePixelBufferTo(image, expectedPixels.Span);
public static void CompareBuffers(Span expected, Span actual)
where T : struct, IEquatable
{
Assert.True(expected.Length == actual.Length, "Buffer sizes are not equal!");
for (int i = 0; i < expected.Length; i++)
{
T x = expected[i];
T a = actual[i];
Assert.True(x.Equals(a), $"Buffers differ at position {i}! Expected: {x} | Actual: {a}");
}
}
public static void CompareBuffers(Buffer2D expected, Buffer2D actual)
where T : struct, IEquatable
{
Assert.True(expected.Size() == actual.Size(), "Buffer sizes are not equal!");
for (int y = 0; y < expected.Height; y++)
{
Span expectedRow = expected.DangerousGetRowSpan(y);
Span actualRow = actual.DangerousGetRowSpan(y);
for (int x = 0; x < expectedRow.Length; x++)
{
T expectedVal = expectedRow[x];
T actualVal = actualRow[x];
Assert.True(
expectedVal.Equals(actualVal),
$"Buffers differ at position ({x},{y})! Expected: {expectedVal} | Actual: {actualVal}");
}
}
}
///
/// All pixels in all frames should be exactly equal to 'expectedPixel'.
///
/// The pixel type of the image.
/// The image.
public static Image ComparePixelBufferTo(this Image image, TPixel expectedPixel)
where TPixel : unmanaged, IPixel
{
foreach (ImageFrame imageFrame in image.Frames)
{
imageFrame.ComparePixelBufferTo(expectedPixel);
}
return image;
}
///
/// All pixels in all frames should be exactly equal to 'expectedPixelColor.ToPixel()'.
///
/// The pixel type of the image.
/// The image.
public static Image ComparePixelBufferTo(this Image image, Color expectedPixelColor)
where TPixel : unmanaged, IPixel
{
foreach (ImageFrame imageFrame in image.Frames)
{
imageFrame.ComparePixelBufferTo(expectedPixelColor.ToPixel());
}
return image;
}
///
/// All pixels in the frame should be exactly equal to 'expectedPixel'.
///
/// The pixel type of the image.
/// The image.
public static ImageFrame ComparePixelBufferTo(this ImageFrame imageFrame, TPixel expectedPixel)
where TPixel : unmanaged, IPixel
{
Assert.True(imageFrame.DangerousTryGetSinglePixelMemory(out Memory actualPixelMem));
Span actualPixels = actualPixelMem.Span;
for (int i = 0; i < actualPixels.Length; i++)
{
Assert.True(expectedPixel.Equals(actualPixels[i]), $"Pixels are different on position {i}!");
}
return imageFrame;
}
public static ImageFrame ComparePixelBufferTo(
this ImageFrame image,
Span expectedPixels)
where TPixel : unmanaged, IPixel
{
Assert.True(image.DangerousTryGetSinglePixelMemory(out Memory actualMem));
Span actual = actualMem.Span;
Assert.True(expectedPixels.Length == actual.Length, "Buffer sizes are not equal!");
for (int i = 0; i < expectedPixels.Length; i++)
{
Assert.True(expectedPixels[i].Equals(actual[i]), $"Pixels are different on position {i}!");
}
return image;
}
public static Image CompareToOriginal(
this Image image,
ITestImageProvider provider,
IImageDecoder referenceDecoder = null)
where TPixel : unmanaged, IPixel
=> CompareToOriginal(image, provider, ImageComparer.Tolerant(), referenceDecoder);
public static Image CompareToOriginal(
this Image image,
ITestImageProvider provider,
ImageComparer comparer,
IImageDecoder referenceDecoder = null,
DecoderOptions referenceDecoderOptions = null)
where TPixel : unmanaged, IPixel
{
string path = TestImageProvider.GetFilePathOrNull(provider);
if (path == null)
{
throw new InvalidOperationException("CompareToOriginal() works only with file providers!");
}
TestFile testFile = TestFile.Create(path);
referenceDecoder ??= TestEnvironment.GetReferenceDecoder(path);
using MemoryStream stream = new(testFile.Bytes);
using Image original = referenceDecoder.Decode(referenceDecoderOptions ?? DecoderOptions.Default, stream);
comparer.VerifySimilarity(original, image);
return image;
}
public static Image CompareToOriginalMultiFrame(
this Image image,
ITestImageProvider provider,
ImageComparer comparer,
IImageDecoder referenceDecoder = null)
where TPixel : unmanaged, IPixel
{
string path = TestImageProvider.GetFilePathOrNull(provider);
if (path == null)
{
throw new InvalidOperationException("CompareToOriginal() works only with file providers!");
}
TestFile testFile = TestFile.Create(path);
referenceDecoder ??= TestEnvironment.GetReferenceDecoder(path);
using MemoryStream stream = new(testFile.Bytes);
using Image original = referenceDecoder.Decode(DecoderOptions.Default, stream);
comparer.VerifySimilarity(original, image);
return image;
}
///
/// Utility method for doing the following in one step:
/// 1. Executing an operation (taken as a delegate)
/// 2. Executing DebugSave()
/// 3. Executing CompareToReferenceOutput()
///
internal static void VerifyOperation(
this TestImageProvider provider,
ImageComparer comparer,
Action> operation,
FormattableString testOutputDetails,
bool appendPixelTypeToFileName = true,
bool appendSourceFileOrDescription = true)
where TPixel : unmanaged, IPixel
{
using Image image = provider.GetImage();
operation(image);
image.DebugSave(
provider,
testOutputDetails,
appendPixelTypeToFileName: appendPixelTypeToFileName,
appendSourceFileOrDescription: appendSourceFileOrDescription);
image.CompareToReferenceOutput(
comparer,
provider,
testOutputDetails,
appendPixelTypeToFileName: appendPixelTypeToFileName,
appendSourceFileOrDescription: appendSourceFileOrDescription);
}
///
/// Utility method for doing the following in one step:
/// 1. Executing an operation (taken as a delegate)
/// 2. Executing DebugSave()
/// 3. Executing CompareToReferenceOutput()
///
internal static void VerifyOperation(
this TestImageProvider provider,
Action> operation,
FormattableString testOutputDetails,
bool appendPixelTypeToFileName = true,
bool appendSourceFileOrDescription = true)
where TPixel : unmanaged, IPixel
=> provider.VerifyOperation(
ImageComparer.Tolerant(),
operation,
testOutputDetails,
appendPixelTypeToFileName,
appendSourceFileOrDescription);
///
/// Utility method for doing the following in one step:
/// 1. Executing an operation (taken as a delegate)
/// 2. Executing DebugSave()
/// 3. Executing CompareToReferenceOutput()
///
internal static void VerifyOperation(
this TestImageProvider provider,
ImageComparer comparer,
Action> operation,
bool appendPixelTypeToFileName = true,
bool appendSourceFileOrDescription = true)
where TPixel : unmanaged, IPixel
=> provider.VerifyOperation(
comparer,
operation,
$"",
appendPixelTypeToFileName,
appendSourceFileOrDescription);
///
/// Utility method for doing the following in one step:
/// 1. Executing an operation (taken as a delegate)
/// 2. Executing DebugSave()
/// 3. Executing CompareToReferenceOutput()
///
internal static void VerifyOperation(
this TestImageProvider provider,
Action> operation,
bool appendPixelTypeToFileName = true,
bool appendSourceFileOrDescription = true)
where TPixel : unmanaged, IPixel
=> provider.VerifyOperation(operation, $"", appendPixelTypeToFileName, appendSourceFileOrDescription);
///
/// Loads the expected image with a reference decoder + compares it to .
/// Also performs a debug save using .
///
/// The path to the encoded output file.
internal static string VerifyEncoder(
this Image image,
ITestImageProvider provider,
string extension,
object testOutputDetails,
IImageEncoder encoder,
ImageComparer customComparer = null,
bool appendPixelTypeToFileName = true,
string referenceImageExtension = null,
IImageDecoder referenceDecoder = null)
where TPixel : unmanaged, IPixel
{
string actualOutputFile = provider.Utility.SaveTestOutputFile(
image,
extension,
encoder,
testOutputDetails,
appendPixelTypeToFileName);
referenceDecoder ??= TestEnvironment.GetReferenceDecoder(actualOutputFile);
using FileStream stream = File.OpenRead(actualOutputFile);
using Image encodedImage = referenceDecoder.Decode(DecoderOptions.Default, stream);
ImageComparer comparer = customComparer ?? ImageComparer.Exact;
comparer.VerifySimilarity(encodedImage, image);
return actualOutputFile;
}
internal static AllocatorBufferCapacityConfigurator LimitAllocatorBufferCapacity(
this TestImageProvider provider)
where TPixel : unmanaged, IPixel
{
TestMemoryAllocator allocator = new();
provider.Configuration.MemoryAllocator = allocator;
return new AllocatorBufferCapacityConfigurator(allocator, Unsafe.SizeOf());
}
private class MakeOpaqueProcessor : IImageProcessor
{
public IImageProcessor CreatePixelSpecificProcessor(Configuration configuration, Image source, Rectangle sourceRectangle)
where TPixel : unmanaged, IPixel
=> new MakeOpaqueProcessor(configuration, source, sourceRectangle);
}
private class MakeOpaqueProcessor : ImageProcessor
where TPixel : unmanaged, IPixel
{
public MakeOpaqueProcessor(Configuration configuration, Image source, Rectangle sourceRectangle)
: base(configuration, source, sourceRectangle)
{
}
protected override void OnFrameApply(ImageFrame source)
{
Rectangle sourceRectangle = this.SourceRectangle;
Configuration configuration = this.Configuration;
RowOperation operation = new(configuration, sourceRectangle, source.PixelBuffer);
ParallelRowIterator.IterateRowIntervals(
configuration,
sourceRectangle,
in operation);
}
private readonly struct RowOperation : IRowIntervalOperation
{
private readonly Configuration configuration;
private readonly Rectangle bounds;
private readonly Buffer2D source;
public RowOperation(Configuration configuration, Rectangle bounds, Buffer2D source)
{
this.configuration = configuration;
this.bounds = bounds;
this.source = source;
}
public int GetRequiredBufferLength(Rectangle bounds)
=> bounds.Width;
public void Invoke(in RowInterval rows, Span span)
{
for (int y = rows.Min; y < rows.Max; y++)
{
Span rowSpan = this.source.DangerousGetRowSpan(y).Slice(this.bounds.Left, this.bounds.Width);
PixelOperations.Instance.ToVector4(this.configuration, rowSpan, span, PixelConversionModifiers.Scale);
for (int i = 0; i < span.Length; i++)
{
ref Vector4 v = ref span[i];
v.W = 1F;
}
PixelOperations.Instance.FromVector4Destructive(this.configuration, span, rowSpan, PixelConversionModifiers.Scale);
}
}
}
}
}
internal class AllocatorBufferCapacityConfigurator
{
private readonly TestMemoryAllocator allocator;
private readonly int pixelSizeInBytes;
public AllocatorBufferCapacityConfigurator(TestMemoryAllocator allocator, int pixelSizeInBytes)
{
this.allocator = allocator;
this.pixelSizeInBytes = pixelSizeInBytes;
}
public void InBytes(int totalBytes) => this.allocator.BufferCapacityInBytes = totalBytes;
public void InPixels(int totalPixels) => this.InBytes(totalPixels * this.pixelSizeInBytes);
///
/// Set the maximum buffer capacity to bytesSqrt^2 bytes.
///
public void InBytesSqrt(int bytesSqrt) => this.InBytes(bytesSqrt * bytesSqrt);
///
/// Set the maximum buffer capacity to pixelsSqrt^2 x sizeof(TPixel) bytes.
///
public void InPixelsSqrt(int pixelsSqrt) => this.InPixels(pixelsSqrt * pixelsSqrt);
}