diff --git a/src/ImageSharp/Common/Extensions/ByteExtensions.cs b/src/ImageSharp/Common/Extensions/ByteExtensions.cs
deleted file mode 100644
index b5b868deaa..0000000000
--- a/src/ImageSharp/Common/Extensions/ByteExtensions.cs
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (c) Six Labors and contributors.
-// Licensed under the Apache License, Version 2.0.
-
-using System;
-using System.Runtime.CompilerServices;
-using SixLabors.ImageSharp.PixelFormats;
-
-namespace SixLabors.ImageSharp
-{
- ///
- /// Extension methods for the struct buffers.
- ///
- internal static class ByteExtensions
- {
- ///
- /// Returns a reference to the given position of the array unsafe casted to .
- ///
- /// The byte array.
- /// The offset in bytes.
- /// The reference at the given offset.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static ref Rgb24 GetRgb24(this byte[] bytes, int offset)
- {
- DebugGuard.MustBeLessThan(offset + 2, bytes.Length, nameof(offset));
-
- return ref Unsafe.As(ref bytes[offset]);
- }
-
- ///
- /// Returns a reference to the given position of the span unsafe casted to .
- ///
- /// The byte span.
- /// The offset in bytes.
- /// The reference at the given offset.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static ref Rgb24 GetRgb24(this Span bytes, int offset)
- {
- DebugGuard.MustBeLessThan(offset + 2, bytes.Length, nameof(offset));
-
- return ref Unsafe.As(ref bytes[offset]);
- }
-
- ///
- /// Returns a reference to the given position of the buffer pointed by `baseRef` unsafe casted to .
- ///
- /// A reference to the beginning of the buffer
- /// The offset in bytes.
- /// The reference at the given offset.
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static ref Rgb24 GetRgb24(ref byte baseRef, int offset)
- {
- return ref Unsafe.As(ref Unsafe.Add(ref baseRef, offset));
- }
- }
-}
\ No newline at end of file
diff --git a/src/ImageSharp/Common/Helpers/Guard.cs b/src/ImageSharp/Common/Helpers/Guard.cs
index 9f0a46f80c..9258beb368 100644
--- a/src/ImageSharp/Common/Helpers/Guard.cs
+++ b/src/ImageSharp/Common/Helpers/Guard.cs
@@ -4,7 +4,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
-using System.Linq;
namespace SixLabors.ImageSharp
{
@@ -15,78 +14,62 @@ namespace SixLabors.ImageSharp
internal static class Guard
{
///
- /// Verifies, that the method parameter with specified object value is not null
- /// and throws an exception if it is found to be so.
+ /// Ensures that the value is not null.
///
- /// The target object, which cannot be null.
+ /// The target object, which cannot be null.
/// The name of the parameter that is to be checked.
- /// The error message, if any to add to the exception.
- /// is null
- public static void NotNull(object target, string parameterName, string message = "")
+ /// is null
+ public static void NotNull(object value, string parameterName)
{
- if (target == null)
+ if (value == null)
{
- if (!string.IsNullOrWhiteSpace(message))
- {
- throw new ArgumentNullException(parameterName, message);
- }
-
throw new ArgumentNullException(parameterName);
}
}
///
- /// Verifies, that the string method parameter with specified object value and message
- /// is not null, not empty and does not contain only blanks and throws an exception
- /// if the object is null.
+ /// Ensures that the target value is not null, empty, or whitespace.
///
- /// The target string, which should be checked against being null or empty.
+ /// The target string, which should be checked against being null or empty.
/// Name of the parameter.
- /// The error message, if any to add to the exception.
- /// is null.
- /// is empty or contains only blanks.
- public static void NotNullOrEmpty(string target, string parameterName, string message = "")
+ /// is null.
+ /// is empty or contains only blanks.
+ public static void NotNullOrWhiteSpace(string value, string parameterName)
{
- NotNull(target, parameterName, message);
-
- if (string.IsNullOrWhiteSpace(target))
+ if (value == null)
{
- if (!string.IsNullOrWhiteSpace(message))
- {
- throw new ArgumentException(message, parameterName);
- }
+ throw new ArgumentNullException(parameterName);
+ }
- throw new ArgumentException("Value cannot be null or empty and cannot contain only blanks.", parameterName);
+ if (string.IsNullOrWhiteSpace(value))
+ {
+ throw new ArgumentException("Must not be empty or whitespace.", parameterName);
}
}
///
- /// Verifies, that the enumeration is not null and not empty.
+ /// Ensures that the enumeration is not null or empty.
///
- /// The type of objects in the
- /// The target enumeration, which should be checked against being null or empty.
+ /// The type of objects in the
+ /// The target enumeration, which should be checked against being null or empty.
/// Name of the parameter.
- /// The error message, if any to add to the exception.
- /// is null.
- /// is empty.
- public static void NotNullOrEmpty(IEnumerable target, string parameterName, string message = "")
+ /// is null.
+ /// is empty.
+ public static void NotNullOrEmpty(ICollection value, string parameterName)
{
- NotNull(target, parameterName, message);
-
- if (!target.Any())
+ if (value == null)
{
- if (!string.IsNullOrWhiteSpace(message))
- {
- throw new ArgumentException(message, parameterName);
- }
+ throw new ArgumentNullException(parameterName);
+ }
- throw new ArgumentException("Value cannot be empty.", parameterName);
+ if (value.Count == 0)
+ {
+ throw new ArgumentException("Must not be empty.", parameterName);
}
}
///
- /// Verifies that the specified value is less than a maximum value
- /// and throws an exception if it is not.
+ /// Ensures that the specified value is less than a maximum value.
///
/// The target value, which should be validated.
/// The maximum value.
@@ -191,15 +174,9 @@ public static void MustBeBetweenOrEqualTo(TValue value, TValue min, TVal
/// Verifies, that the method parameter with specified target value is true
/// and throws an exception if it is found to be so.
///
- ///
- /// The target value, which cannot be false.
- ///
- ///
- /// The name of the parameter that is to be checked.
- ///
- ///
- /// The error message, if any to add to the exception.
- ///
+ /// The target value, which cannot be false.
+ /// The name of the parameter that is to be checked.
+ /// The error message, if any to add to the exception.
///
/// is false
///
diff --git a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
index 1900d0df05..4fbd4baf51 100644
--- a/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
+++ b/src/ImageSharp/Formats/Gif/GifDecoderCore.cs
@@ -39,11 +39,6 @@ internal sealed class GifDecoderCore
///
private IManagedByteBuffer globalColorTable;
- ///
- /// The global color table length
- ///
- private int globalColorTableLength;
-
///
/// The area to restore.
///
@@ -333,8 +328,8 @@ private void ReadFrame(ref Image image, ref ImageFrame p
indices = this.configuration.MemoryManager.AllocateManagedByteBuffer(imageDescriptor.Width * imageDescriptor.Height, true);
this.ReadFrameIndices(imageDescriptor, indices.Span);
- IManagedByteBuffer colorTable = localColorTable ?? this.globalColorTable;
- this.ReadFrameColors(ref image, ref previousFrame, indices.Span, colorTable.Span, imageDescriptor);
+ ReadOnlySpan colorTable = MemoryMarshal.Cast((localColorTable ?? this.globalColorTable).Span);
+ this.ReadFrameColors(ref image, ref previousFrame, indices.Span, colorTable, imageDescriptor);
// Skip any remaining blocks
this.Skip(0);
@@ -370,7 +365,7 @@ private void ReadFrameIndices(in GifImageDescriptor imageDescriptor, Span
/// The indexed pixels.
/// The color table containing the available colors.
/// The
- private void ReadFrameColors(ref Image image, ref ImageFrame previousFrame, Span indices, Span colorTable, in GifImageDescriptor descriptor)
+ private void ReadFrameColors(ref Image image, ref ImageFrame previousFrame, Span indices, ReadOnlySpan colorTable, in GifImageDescriptor descriptor)
where TPixel : struct, IPixel
{
ref byte indicesRef = ref MemoryMarshal.GetReference(indices);
@@ -458,11 +453,8 @@ private void ReadFrameColors(ref Image image, ref ImageFrameThe if found otherwise null
public IImageFormat FindFormatByFileExtension(string extension)
{
+ Guard.NotNullOrWhiteSpace(extension, nameof(extension));
+
+ if (extension[0] == '.')
+ {
+ extension = extension.Substring(1);
+ }
+
return this.imageFormats.FirstOrDefault(x => x.FileExtensions.Contains(extension, StringComparer.OrdinalIgnoreCase));
}
diff --git a/src/ImageSharp/Formats/Png/Filters/NoneFilter.cs b/src/ImageSharp/Formats/Png/Filters/NoneFilter.cs
index 0164ceafaa..14af8ca6a0 100644
--- a/src/ImageSharp/Formats/Png/Filters/NoneFilter.cs
+++ b/src/ImageSharp/Formats/Png/Filters/NoneFilter.cs
@@ -20,7 +20,7 @@ internal static class NoneFilter
/// The scanline to encode
/// The filtered scanline result.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void Encode(Span scanline, Span result)
+ public static void Encode(ReadOnlySpan scanline, Span result)
{
// Insert a byte before the data.
result[0] = 0;
diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
index 8fefcb480c..cc98b8450b 100644
--- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs
+++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs
@@ -853,7 +853,7 @@ private void ProcessScanlineFromPalette(ReadOnlySpan defilteredSca
where TPixel : struct, IPixel
{
ReadOnlySpan newScanline = ToArrayByBitsLength(defilteredScanline, this.bytesPerScanline, this.header.BitDepth);
- byte[] pal = this.palette;
+ ReadOnlySpan pal = MemoryMarshal.Cast(this.palette);
var color = default(TPixel);
var rgba = default(Rgba32);
@@ -865,10 +865,9 @@ private void ProcessScanlineFromPalette(ReadOnlySpan defilteredSca
for (int x = 0; x < this.header.Width; x++)
{
int index = newScanline[x];
- int pixelOffset = index * 3;
rgba.A = this.paletteAlpha.Length > index ? this.paletteAlpha[index] : (byte)255;
- rgba.Rgb = pal.GetRgb24(pixelOffset);
+ rgba.Rgb = pal[index];
color.PackFromRgba32(rgba);
row[x] = color;
@@ -881,9 +880,8 @@ private void ProcessScanlineFromPalette(ReadOnlySpan defilteredSca
for (int x = 0; x < this.header.Width; x++)
{
int index = newScanline[x];
- int pixelOffset = index * 3;
- rgba.Rgb = pal.GetRgb24(pixelOffset);
+ rgba.Rgb = pal[index];
color.PackFromRgba32(rgba);
row[x] = color;
@@ -946,6 +944,7 @@ private void ProcessInterlacedDefilteredScanline(ReadOnlySpan defi
ReadOnlySpan newScanline = ToArrayByBitsLength(scanlineBuffer, this.bytesPerScanline, this.header.BitDepth);
var rgba = default(Rgba32);
+ Span pal = MemoryMarshal.Cast(this.palette);
if (this.paletteAlpha != null && this.paletteAlpha.Length > 0)
{
@@ -954,10 +953,9 @@ private void ProcessInterlacedDefilteredScanline(ReadOnlySpan defi
for (int x = pixelOffset, o = 0; x < this.header.Width; x += increment, o++)
{
int index = newScanline[o];
- int offset = index * 3;
rgba.A = this.paletteAlpha.Length > index ? this.paletteAlpha[index] : (byte)255;
- rgba.Rgb = this.palette.GetRgb24(offset);
+ rgba.Rgb = pal[index];
color.PackFromRgba32(rgba);
rowSpan[x] = color;
@@ -970,10 +968,8 @@ private void ProcessInterlacedDefilteredScanline(ReadOnlySpan defi
for (int x = pixelOffset, o = 0; x < this.header.Width; x += increment, o++)
{
int index = newScanline[o];
- int offset = index * 3;
-
- rgba.Rgb = this.palette.GetRgb24(offset);
+ rgba.Rgb = pal[index];
color.PackFromRgba32(rgba);
rowSpan[x] = color;
}
diff --git a/src/ImageSharp/Image.LoadPixelData.cs b/src/ImageSharp/Image.LoadPixelData.cs
index 0179e62acc..282f980865 100644
--- a/src/ImageSharp/Image.LoadPixelData.cs
+++ b/src/ImageSharp/Image.LoadPixelData.cs
@@ -33,7 +33,7 @@ public static Image LoadPixelData(TPixel[] data, int width, int
/// The height of the final image.
/// The pixel format.
/// A new .
- private static Image LoadPixelData(Span data, int width, int height)
+ public static Image LoadPixelData(ReadOnlySpan data, int width, int height)
where TPixel : struct, IPixel
=> LoadPixelData(Configuration.Default, data, width, height);
@@ -57,7 +57,7 @@ public static Image LoadPixelData(byte[] data, int width, int he
/// The height of the final image.
/// The pixel format.
/// A new .
- private static Image LoadPixelData(Span data, int width, int height)
+ public static Image LoadPixelData(ReadOnlySpan data, int width, int height)
where TPixel : struct, IPixel
=> LoadPixelData(Configuration.Default, data, width, height);
@@ -72,7 +72,7 @@ private static Image LoadPixelData(Span data, int width, i
/// A new .
public static Image LoadPixelData(Configuration config, byte[] data, int width, int height)
where TPixel : struct, IPixel
- => LoadPixelData(config, MemoryMarshal.Cast(data.AsSpan()), width, height);
+ => LoadPixelData(config, MemoryMarshal.Cast(new ReadOnlySpan(data)), width, height);
///
/// Create a new instance of the class from the given byte array in format.
@@ -83,7 +83,7 @@ public static Image LoadPixelData(Configuration config, byte[] d
/// The height of the final image.
/// The pixel format.
/// A new .
- private static Image LoadPixelData(Configuration config, Span data, int width, int height)
+ public static Image LoadPixelData(Configuration config, ReadOnlySpan data, int width, int height)
where TPixel : struct, IPixel
=> LoadPixelData(config, MemoryMarshal.Cast(data), width, height);
@@ -99,7 +99,7 @@ private static Image LoadPixelData(Configuration config, Span LoadPixelData(Configuration config, TPixel[] data, int width, int height)
where TPixel : struct, IPixel
{
- return LoadPixelData(config, data.AsSpan(), width, height);
+ return LoadPixelData(config, new ReadOnlySpan(data), width, height);
}
///
@@ -111,7 +111,7 @@ public static Image LoadPixelData(Configuration config, TPixel[]
/// The height of the final image.
/// The pixel format.
/// A new .
- private static Image LoadPixelData(Configuration config, Span data, int width, int height)
+ public static Image LoadPixelData(Configuration config, ReadOnlySpan data, int width, int height)
where TPixel : struct, IPixel
{
int count = width * height;
diff --git a/src/ImageSharp/ImageExtensions.cs b/src/ImageSharp/ImageExtensions.cs
index 2cdb71fc0e..d8cda2f8fc 100644
--- a/src/ImageSharp/ImageExtensions.cs
+++ b/src/ImageSharp/ImageExtensions.cs
@@ -4,13 +4,11 @@
using System;
using System.Collections.Generic;
using System.IO;
-using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.PixelFormats;
-using SixLabors.Primitives;
namespace SixLabors.ImageSharp
{
@@ -21,18 +19,18 @@ public static partial class ImageExtensions
{
#if !NETSTANDARD1_1
///
- /// Saves the image to the given stream using the currently loaded image format.
+ /// Writes the image to the given stream using the currently loaded image format.
///
- /// The Pixel format.
- /// The source image
+ /// The pixel format.
+ /// The source image.
/// The file path to save the image to.
/// Thrown if the stream is null.
public static void Save(this Image source, string filePath)
where TPixel : struct, IPixel
{
- Guard.NotNullOrEmpty(filePath, nameof(filePath));
+ Guard.NotNullOrWhiteSpace(filePath, nameof(filePath));
- string ext = Path.GetExtension(filePath).Trim('.');
+ string ext = Path.GetExtension(filePath);
IImageFormat format = source.GetConfiguration().ImageFormatsManager.FindFormatByFileExtension(ext);
if (format == null)
{
@@ -64,13 +62,13 @@ public static void Save(this Image source, string filePath)
}
///
- /// Saves the image to the given stream using the currently loaded image format.
+ /// Writes the image to the given stream using the currently loaded image format.
///
- /// The Pixel format.
- /// The source image
+ /// The pixel format.
+ /// The source image.
/// The file path to save the image to.
/// The encoder to save the image with.
- /// Thrown if the encoder is null.
+ /// Thrown if the encoder is null.
public static void Save(this Image source, string filePath, IImageEncoder encoder)
where TPixel : struct, IPixel
{
@@ -83,13 +81,13 @@ public static void Save(this Image source, string filePath, IIma
#endif
///
- /// Saves the image to the given stream using the currently loaded image format.
+ /// Writes the image to the given stream using the currently loaded image format.
///
/// The Pixel format.
- /// The source image
+ /// The source image.
/// The stream to save the image to.
- /// The format to save the image to.
- /// Thrown if the stream is null.
+ /// The format to save the image in.
+ /// Thrown if the stream is null.
public static void Save(this Image source, Stream stream, IImageFormat format)
where TPixel : struct, IPixel
{
@@ -113,67 +111,67 @@ public static void Save(this Image source, Stream stream, IImage
}
///
- /// Saves the raw image pixels to a byte array in row-major order.
+ /// Returns the a copy of the image pixels as a byte array in row-major order.
///
- /// The Pixel format.
+ /// The pixel format.
/// The source image
/// A copy of the pixel data as bytes from this frame.
- /// Thrown if the stream is null.
+ /// Thrown if the stream is null.
public static byte[] SavePixelData(this ImageFrame source)
where TPixel : struct, IPixel
=> MemoryMarshal.AsBytes(source.GetPixelSpan()).ToArray();
///
- /// Saves the raw image pixels to the given byte array in row-major order.
+ /// Writes the raw image pixels to the given byte array in row-major order.
///
- /// The Pixel format.
- /// The source image
+ /// The pixel format.
+ /// The source image.
/// The buffer to save the raw pixel data to.
- /// Thrown if the stream is null.
+ /// Thrown if the stream is null.
public static void SavePixelData(this ImageFrame source, byte[] buffer)
where TPixel : struct, IPixel
=> SavePixelData(source, MemoryMarshal.Cast(buffer.AsSpan()));
///
- /// Saves the raw image pixels to the given TPixel array in row-major order.
+ /// Writes the raw image pixels to the given TPixel array in row-major order.
///
- /// The Pixel format.
+ /// The pixel format.
/// The source image
/// The buffer to save the raw pixel data to.
- /// Thrown if the stream is null.
+ /// Thrown if the stream is null.
public static void SavePixelData(this ImageFrame source, TPixel[] buffer)
where TPixel : struct, IPixel
=> SavePixelData(source, buffer.AsSpan());
///
- /// Saves the raw image pixels to a byte array in row-major order.
+ /// Returns a copy of the raw image pixels as a byte array in row-major order.
///
- /// The Pixel format.
- /// The source image
+ /// The pixel format.
+ /// The source image.
/// A copy of the pixel data from the first frame as bytes.
- /// Thrown if the stream is null.
+ /// Thrown if the stream is null.
public static byte[] SavePixelData(this Image source)
where TPixel : struct, IPixel
=> source.Frames.RootFrame.SavePixelData();
///
- /// Saves the raw image pixels to the given byte array in row-major order.
+ /// Writes the raw image pixels to the given byte array in row-major order.
///
- /// The Pixel format.
- /// The source image
+ /// The pixel format.
+ /// The source image.
/// The buffer to save the raw pixel data to.
- /// Thrown if the stream is null.
+ /// Thrown if the stream is null.
public static void SavePixelData(this Image source, byte[] buffer)
where TPixel : struct, IPixel
=> source.Frames.RootFrame.SavePixelData(buffer);
///
- /// Saves the raw image pixels to the given TPixel array in row-major order.
+ /// Writes the raw image pixels to the given TPixel array in row-major order.
///
- /// The Pixel format.
+ /// The pixel format.
/// The source image
/// The buffer to save the raw pixel data to.
- /// Thrown if the stream is null.
+ /// Thrown if the stream is null.
public static void SavePixelData(this Image source, TPixel[] buffer)
where TPixel : struct, IPixel
=> source.Frames.RootFrame.SavePixelData(buffer);
@@ -182,7 +180,7 @@ public static void SavePixelData(this Image source, TPixel[] buf
/// Returns a Base64 encoded string from the given image.
///
///
- /// The Pixel format.
+ /// The pixel format.
/// The source image
/// The format.
/// The
@@ -198,24 +196,24 @@ public static string ToBase64String(this Image source, IImageFor
}
///
- /// Saves the raw image to the given bytes.
+ /// Writes the raw image bytes to the given byte span.
///
- /// The Pixel format.
+ /// The pixel format.
/// The source image
- /// The buffer to save the raw pixel data to.
+ /// The span to save the raw pixel data to.
/// Thrown if the stream is null.
- internal static void SavePixelData(this Image source, Span buffer)
+ public static void SavePixelData(this Image source, Span buffer)
where TPixel : struct, IPixel
=> source.Frames.RootFrame.SavePixelData(MemoryMarshal.Cast(buffer));
///
- /// Saves the raw image to the given bytes.
+ /// Writes the raw image pixels to the given TPixel span.
///
- /// The Pixel format.
+ /// The pixel format.
/// The source image
- /// The buffer to save the raw pixel data to.
+ /// The span to save the raw pixel data to.
/// Thrown if the stream is null.
- internal static void SavePixelData(this ImageFrame source, Span buffer)
+ public static void SavePixelData(this ImageFrame source, Span buffer)
where TPixel : struct, IPixel
{
Span sourceBuffer = source.GetPixelSpan();
@@ -224,4 +222,4 @@ internal static void SavePixelData(this ImageFrame source, Span<
sourceBuffer.CopyTo(buffer);
}
}
-}
+}
\ No newline at end of file
diff --git a/src/ImageSharp/ImageFrame.LoadPixelData.cs b/src/ImageSharp/ImageFrame.LoadPixelData.cs
index 1306c28367..4639a104b1 100644
--- a/src/ImageSharp/ImageFrame.LoadPixelData.cs
+++ b/src/ImageSharp/ImageFrame.LoadPixelData.cs
@@ -23,7 +23,7 @@ internal static partial class ImageFrame
/// The height of the final image.
/// The pixel format.
/// A new .
- public static ImageFrame LoadPixelData(MemoryManager memoryManager, Span data, int width, int height)
+ public static ImageFrame LoadPixelData(MemoryManager memoryManager, ReadOnlySpan data, int width, int height)
where TPixel : struct, IPixel
=> LoadPixelData(memoryManager, MemoryMarshal.Cast(data), width, height);
@@ -36,7 +36,7 @@ public static ImageFrame LoadPixelData(MemoryManager memoryManag
/// The height of the final image.
/// The pixel format.
/// A new .
- public static ImageFrame LoadPixelData(MemoryManager memoryManager, Span data, int width, int height)
+ public static ImageFrame LoadPixelData(MemoryManager memoryManager, ReadOnlySpan data, int width, int height)
where TPixel : struct, IPixel
{
int count = width * height;
diff --git a/src/ImageSharp/ImageFrameCollection.cs b/src/ImageSharp/ImageFrameCollection.cs
index 0318a7068d..be15a6527c 100644
--- a/src/ImageSharp/ImageFrameCollection.cs
+++ b/src/ImageSharp/ImageFrameCollection.cs
@@ -32,7 +32,7 @@ internal ImageFrameCollection(Image parent, int width, int height, TPixe
internal ImageFrameCollection(Image parent, IEnumerable> frames)
{
Guard.NotNull(parent, nameof(parent));
- Guard.NotNullOrEmpty(frames, nameof(frames));
+ Guard.NotNull(frames, nameof(frames));
this.parent = parent;
@@ -42,6 +42,12 @@ internal ImageFrameCollection(Image parent, IEnumerable
@@ -111,7 +117,7 @@ public ImageFrame AddFrame(TPixel[] source)
var frame = ImageFrame.LoadPixelData(
this.parent.GetMemoryManager(),
- new Span(source),
+ new ReadOnlySpan(source),
this.RootFrame.Width,
this.RootFrame.Height);
this.frames.Add(frame);
diff --git a/src/ImageSharp/MetaData/ImageProperty.cs b/src/ImageSharp/MetaData/ImageProperty.cs
index c67c1f3cf9..3e0cccd422 100644
--- a/src/ImageSharp/MetaData/ImageProperty.cs
+++ b/src/ImageSharp/MetaData/ImageProperty.cs
@@ -19,7 +19,7 @@ namespace SixLabors.ImageSharp.MetaData
/// The value of the property.
public ImageProperty(string name, string value)
{
- Guard.NotNullOrEmpty(name, nameof(name));
+ Guard.NotNullOrWhiteSpace(name, nameof(name));
this.Name = name;
this.Value = value;
diff --git a/src/ImageSharp/PixelFormats/ColorBuilder{TPixel}.cs b/src/ImageSharp/PixelFormats/ColorBuilder{TPixel}.cs
index 184928d0e4..c2c0277f9e 100644
--- a/src/ImageSharp/PixelFormats/ColorBuilder{TPixel}.cs
+++ b/src/ImageSharp/PixelFormats/ColorBuilder{TPixel}.cs
@@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
+using System.Buffers.Binary;
using System.Globalization;
namespace SixLabors.ImageSharp.PixelFormats
@@ -23,21 +24,17 @@ public static class ColorBuilder
/// Returns a that represents the color defined by the provided RGBA heax string.
public static TPixel FromHex(string hex)
{
- Guard.NotNullOrEmpty(hex, nameof(hex));
+ Guard.NotNullOrWhiteSpace(hex, nameof(hex));
hex = ToRgbaHex(hex);
- uint packedValue;
- if (hex == null || !uint.TryParse(hex, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out packedValue))
+
+ if (hex == null || !uint.TryParse(hex, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out uint packedValue))
{
throw new ArgumentException("Hexadecimal string is not in the correct format.", nameof(hex));
}
TPixel result = default;
- var rgba = new Rgba32(
- (byte)(packedValue >> 24),
- (byte)(packedValue >> 16),
- (byte)(packedValue >> 8),
- (byte)(packedValue >> 0));
+ var rgba = new Rgba32(BinaryPrimitives.ReverseEndianness(packedValue));
result.PackFromRgba32(rgba);
return result;
@@ -76,7 +73,10 @@ public static TPixel FromRGBA(byte red, byte green, byte blue, byte alpha)
///
private static string ToRgbaHex(string hex)
{
- hex = hex.StartsWith("#") ? hex.Substring(1) : hex;
+ if (hex[0] == '#')
+ {
+ hex = hex.Substring(1);
+ }
if (hex.Length == 8)
{
@@ -93,12 +93,12 @@ private static string ToRgbaHex(string hex)
return null;
}
- string red = char.ToString(hex[0]);
- string green = char.ToString(hex[1]);
- string blue = char.ToString(hex[2]);
- string alpha = hex.Length == 3 ? "F" : char.ToString(hex[3]);
+ char r = hex[0];
+ char g = hex[1];
+ char b = hex[2];
+ char a = hex.Length == 3 ? 'F' : hex[3];
- return string.Concat(red, red, green, green, blue, blue, alpha, alpha);
+ return new string(new[] { r, r, g, g, b, b, a, a });
}
}
}
\ No newline at end of file
diff --git a/tests/ImageSharp.Tests/Helpers/GuardTests.cs b/tests/ImageSharp.Tests/Helpers/GuardTests.cs
index 83075dc83e..42913e02d4 100644
--- a/tests/ImageSharp.Tests/Helpers/GuardTests.cs
+++ b/tests/ImageSharp.Tests/Helpers/GuardTests.cs
@@ -35,27 +35,27 @@ public void NotNullThrowsWhenArgNameEmpty()
///
[Fact]
[SuppressMessage("StyleCop.CSharp.ReadabilityRules", "SA1122:UseStringEmptyForEmptyStrings", Justification = "Reviewed. Suppression is OK here.")]
- public void NotEmptyThrowsWhenEmpty()
+ public void NotEmptyOrWhiteSpaceThrowsWhenEmpty()
{
- Assert.Throws(() => Guard.NotNullOrEmpty("", string.Empty));
+ Assert.Throws(() => Guard.NotNullOrWhiteSpace("", string.Empty));
}
///
/// Tests that the method throws when the argument is whitespace.
///
[Fact]
- public void NotEmptyThrowsWhenWhitespace()
+ public void NotEmptyOrWhiteSpaceThrowsOnWhitespace()
{
- Assert.Throws(() => Guard.NotNullOrEmpty(" ", string.Empty));
+ Assert.Throws(() => Guard.NotNullOrWhiteSpace(" ", string.Empty));
}
///
/// Tests that the method throws when the argument name is null.
///
[Fact]
- public void NotEmptyThrowsWhenParameterNameNull()
+ public void NotEmptyOrWhiteSpaceThrowsWhenParameterNameNull()
{
- Assert.Throws(() => Guard.NotNullOrEmpty(null, null));
+ Assert.Throws(() => Guard.NotNullOrWhiteSpace(null, null));
}
///
diff --git a/tests/ImageSharp.Tests/PixelFormats/ColorBuilderTests.cs b/tests/ImageSharp.Tests/PixelFormats/ColorBuilderTests.cs
new file mode 100644
index 0000000000..e56cac2794
--- /dev/null
+++ b/tests/ImageSharp.Tests/PixelFormats/ColorBuilderTests.cs
@@ -0,0 +1,40 @@
+// Copyright (c) Six Labors and contributors.
+// Licensed under the Apache License, Version 2.0.
+
+using System;
+using SixLabors.ImageSharp.PixelFormats;
+
+using Xunit;
+
+namespace SixLabors.ImageSharp.Tests.Colors
+{
+ public class ColorBuilderTests
+ {
+ [Fact]
+ public void ParseShortHex()
+ {
+ Assert.Equal(new Rgb24(255, 255, 255), ColorBuilder.FromHex("#fff"));
+ Assert.Equal(new Rgb24(255, 255, 255), ColorBuilder.FromHex("fff"));
+ Assert.Equal(new Rgba32(0, 0, 0, 255), ColorBuilder.FromHex("000f"));
+ }
+
+ [Fact]
+ public void ParseHexLeadingPoundIsOptional()
+ {
+ Assert.Equal(new Rgb24(0, 128, 128), ColorBuilder.FromHex("#008080"));
+ Assert.Equal(new Rgb24(0, 128, 128), ColorBuilder.FromHex("008080"));
+ }
+
+ [Fact]
+ public void ParseHexThrowsOnEmpty()
+ {
+ Assert.Throws(() => ColorBuilder.FromHex(""));
+ }
+
+ [Fact]
+ public void ParseHexThrowsOnNull()
+ {
+ Assert.Throws(() => ColorBuilder.FromHex(null));
+ }
+ }
+}
diff --git a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs
index fa9497a8f8..6bebf3887b 100644
--- a/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs
+++ b/tests/ImageSharp.Tests/TestUtilities/TestEnvironment.Formats.cs
@@ -32,8 +32,8 @@ internal static IImageEncoder GetReferenceEncoder(string filePath)
internal static IImageFormat GetImageFormat(string filePath)
{
- string extension = Path.GetExtension(filePath).ToLower();
- if (extension[0] == '.') extension = extension.Substring(1);
+ string extension = Path.GetExtension(filePath);
+
IImageFormat format = Configuration.ImageFormatsManager.FindFormatByFileExtension(extension);
return format;
}