Browse Source

Merge branch 'master' into sw/property-bag

pull/1574/head
James Jackson-South 6 years ago
committed by GitHub
parent
commit
43f41ebc1a
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 22
      src/ImageSharp/Common/Exceptions/InvalidImageContentException.cs
  2. 10
      src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs
  3. 2
      src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs
  4. 16
      src/ImageSharp/Formats/Bmp/BmpThrowHelper.cs
  5. 2
      src/ImageSharp/Formats/Gif/GifDecoderCore.cs
  6. 18
      src/ImageSharp/Formats/Gif/GifThrowHelper.cs
  7. 4
      src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs
  8. 4
      src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs
  9. 18
      src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
  10. 27
      src/ImageSharp/Formats/Jpeg/JpegThrowHelper.cs
  11. 28
      src/ImageSharp/Formats/Png/PngDecoderCore.cs
  12. 10
      src/ImageSharp/Formats/Png/PngThrowHelper.cs
  13. 6
      src/ImageSharp/Formats/Tga/TgaDecoderCore.cs
  14. 14
      src/ImageSharp/Formats/Tga/TgaThrowHelper.cs
  15. 147
      src/ImageSharp/Image.FromBytes.cs
  16. 119
      src/ImageSharp/Image.FromFile.cs
  17. 131
      src/ImageSharp/Image.FromStream.cs
  18. 43
      src/ImageSharp/Image.LoadPixelData.cs
  19. 50
      src/ImageSharp/Image.WrapMemory.cs
  20. 46
      src/ImageSharp/ImageExtensions.cs
  21. 4
      src/ImageSharp/Memory/Buffer2D{T}.cs
  22. 8
      src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupExtensions.cs
  23. 67
      src/ImageSharp/Processing/Extensions/ProcessingExtensions.cs
  24. 4
      tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs
  25. 4
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Baseline.cs
  26. 2
      tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.Chunks.cs
  27. 23
      tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs
  28. 1
      tests/ImageSharp.Tests/Memory/DiscontiguousBuffers/MemoryGroupTests.cs
  29. 4
      tests/ImageSharp.Tests/TestImages.cs
  30. 3
      tests/Images/Input/Png/issues/Issue_1177_1.png
  31. 3
      tests/Images/Input/Png/issues/Issue_1177_2.png

22
src/ImageSharp/Common/Exceptions/InvalidImageContentException.cs

@ -0,0 +1,22 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
namespace SixLabors.ImageSharp
{
/// <summary>
/// The exception that is thrown when the library tries to load
/// an image which contains invalid content.
/// </summary>
public sealed class InvalidImageContentException : ImageFormatException
{
/// <summary>
/// Initializes a new instance of the <see cref="InvalidImageContentException"/> class with the name of the
/// parameter that causes this exception.
/// </summary>
/// <param name="errorMessage">The error message that explains the reason for this exception.</param>
public InvalidImageContentException(string errorMessage)
: base(errorMessage)
{
}
}
}

10
src/ImageSharp/Formats/Bmp/BmpDecoderCore.cs

@ -462,7 +462,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
{
if (this.stream.Read(cmd, 0, cmd.Length) != 2)
{
BmpThrowHelper.ThrowImageFormatException("Failed to read 2 bytes from the stream while uncompressing RLE4 bitmap.");
BmpThrowHelper.ThrowInvalidImageContentException("Failed to read 2 bytes from the stream while uncompressing RLE4 bitmap.");
}
if (cmd[0] == RleCommand)
@ -569,7 +569,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
{
if (this.stream.Read(cmd, 0, cmd.Length) != 2)
{
BmpThrowHelper.ThrowImageFormatException("Failed to read 2 bytes from stream while uncompressing RLE8 bitmap.");
BmpThrowHelper.ThrowInvalidImageContentException("Failed to read 2 bytes from stream while uncompressing RLE8 bitmap.");
}
if (cmd[0] == RleCommand)
@ -648,7 +648,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
{
if (this.stream.Read(cmd, 0, cmd.Length) != 2)
{
BmpThrowHelper.ThrowImageFormatException("Failed to read 2 bytes from stream while uncompressing RLE24 bitmap.");
BmpThrowHelper.ThrowInvalidImageContentException("Failed to read 2 bytes from stream while uncompressing RLE24 bitmap.");
}
if (cmd[0] == RleCommand)
@ -1431,7 +1431,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
// Make sure, that we will not read pass the bitmap offset (starting position of image data).
if ((this.stream.Position + colorMapSizeBytes) > this.fileHeader.Offset)
{
BmpThrowHelper.ThrowImageFormatException(
BmpThrowHelper.ThrowInvalidImageContentException(
$"Reading the color map would read beyond the bitmap offset. Either the color map size of '{colorMapSizeBytes}' is invalid or the bitmap offset.");
}
@ -1445,7 +1445,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
int skipAmount = this.fileHeader.Offset - (int)this.stream.Position;
if ((skipAmount + (int)this.stream.Position) > this.stream.Length)
{
BmpThrowHelper.ThrowImageFormatException("Invalid fileheader offset found. Offset is greater than the stream length.");
BmpThrowHelper.ThrowInvalidImageContentException("Invalid fileheader offset found. Offset is greater than the stream length.");
}
if (skipAmount > 0)

2
src/ImageSharp/Formats/Bmp/BmpInfoHeader.cs

@ -393,7 +393,7 @@ namespace SixLabors.ImageSharp.Formats.Bmp
break;
default:
// Compression type 3 (1DHuffman) is not supported.
BmpThrowHelper.ThrowImageFormatException("Compression type is not supported. ImageSharp only supports uncompressed, RLE4, RLE8 and RLE24.");
BmpThrowHelper.ThrowInvalidImageContentException("Compression type is not supported. ImageSharp only supports uncompressed, RLE4, RLE8 and RLE24.");
break;
}

16
src/ImageSharp/Formats/Bmp/BmpThrowHelper.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
@ -9,23 +9,19 @@ namespace SixLabors.ImageSharp.Formats.Bmp
internal static class BmpThrowHelper
{
/// <summary>
/// Cold path optimization for throwing <see cref="ImageFormatException"/>-s
/// Cold path optimization for throwing <see cref="InvalidImageContentException"/>'s
/// </summary>
/// <param name="errorMessage">The error message for the exception.</param>
[MethodImpl(MethodImplOptions.NoInlining)]
public static void ThrowImageFormatException(string errorMessage)
{
throw new ImageFormatException(errorMessage);
}
public static void ThrowInvalidImageContentException(string errorMessage)
=> throw new InvalidImageContentException(errorMessage);
/// <summary>
/// Cold path optimization for throwing <see cref="NotSupportedException"/>-s
/// Cold path optimization for throwing <see cref="NotSupportedException"/>'s
/// </summary>
/// <param name="errorMessage">The error message for the exception.</param>
[MethodImpl(MethodImplOptions.NoInlining)]
public static void ThrowNotSupportedException(string errorMessage)
{
throw new NotSupportedException(errorMessage);
}
=> throw new NotSupportedException(errorMessage);
}
}

2
src/ImageSharp/Formats/Gif/GifDecoderCore.cs

@ -318,7 +318,7 @@ namespace SixLabors.ImageSharp.Formats.Gif
{
if (length > GifConstants.MaxCommentSubBlockLength)
{
throw new ImageFormatException($"Gif comment length '{length}' exceeds max '{GifConstants.MaxCommentSubBlockLength}' of a comment data block");
GifThrowHelper.ThrowInvalidImageContentException($"Gif comment length '{length}' exceeds max '{GifConstants.MaxCommentSubBlockLength}' of a comment data block");
}
if (this.IgnoreMetadata)

18
src/ImageSharp/Formats/Gif/GifThrowHelper.cs

@ -0,0 +1,18 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.Formats.Gif
{
internal static class GifThrowHelper
{
/// <summary>
/// Cold path optimization for throwing <see cref="InvalidImageContentException"/>'s
/// </summary>
/// <param name="errorMessage">The error message for the exception.</param>
[MethodImpl(MethodImplOptions.NoInlining)]
public static void ThrowInvalidImageContentException(string errorMessage)
=> throw new InvalidImageContentException(errorMessage);
}
}

4
src/ImageSharp/Formats/Jpeg/Components/Decoder/ColorConverters/JpegColorConverter.FromYCbCrSimd.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
@ -104,7 +104,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder.ColorConverters
{
// TODO: Run fallback scalar code here
// However, no issues expected before someone implements this: https://github.com/dotnet/coreclr/issues/12007
throw new NotImplementedException("Your CPU architecture is too modern!");
JpegThrowHelper.ThrowNotImplementedException("Your CPU architecture is too modern!");
}
// Collect (r0,r1...r8) (g0,g1...g8) (b0,b1...b8) vector values in the expected (r0,g0,g1,1), (r1,g1,g2,1) ... order:

4
src/ImageSharp/Formats/Jpeg/Components/Decoder/JFifMarker.cs

@ -29,12 +29,12 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
{
if (xDensity <= 0)
{
JpegThrowHelper.ThrowImageFormatException($"X-Density {xDensity} must be greater than 0.");
JpegThrowHelper.ThrowInvalidImageContentException($"X-Density {xDensity} must be greater than 0.");
}
if (yDensity <= 0)
{
JpegThrowHelper.ThrowImageFormatException($"Y-Density {yDensity} must be greater than 0.");
JpegThrowHelper.ThrowInvalidImageContentException($"Y-Density {yDensity} must be greater than 0.");
}
this.MajorVersion = majorVersion;

18
src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs

@ -259,7 +259,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
var fileMarker = new JpegFileMarker(this.markerBuffer[1], 0);
if (fileMarker.Marker != JpegConstants.Markers.SOI)
{
JpegThrowHelper.ThrowImageFormatException("Missing SOI marker.");
JpegThrowHelper.ThrowInvalidImageContentException("Missing SOI marker.");
}
this.InputStream.Read(this.markerBuffer, 0, 2);
@ -423,7 +423,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
: JpegColorSpace.Cmyk;
}
JpegThrowHelper.ThrowImageFormatException($"Unsupported color mode. Supported component counts 1, 3, and 4; found {this.ComponentCount}");
JpegThrowHelper.ThrowInvalidImageContentException($"Unsupported color mode. Supported component counts 1, 3, and 4; found {this.ComponentCount}");
return default;
}
@ -821,7 +821,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
{
if (this.Frame != null)
{
JpegThrowHelper.ThrowImageFormatException("Multiple SOF markers. Only single frame jpegs supported.");
JpegThrowHelper.ThrowInvalidImageContentException("Multiple SOF markers. Only single frame jpegs supported.");
}
// Read initial marker definitions.
@ -831,7 +831,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
// We only support 8-bit and 12-bit precision.
if (Array.IndexOf(this.supportedPrecisions, this.temp[0]) == -1)
{
JpegThrowHelper.ThrowImageFormatException("Only 8-Bit and 12-Bit precision supported.");
JpegThrowHelper.ThrowInvalidImageContentException("Only 8-Bit and 12-Bit precision supported.");
}
this.Precision = this.temp[0];
@ -928,13 +928,13 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
// Types 0..1 DC..AC
if (tableType > 1)
{
JpegThrowHelper.ThrowImageFormatException("Bad Huffman Table type.");
JpegThrowHelper.ThrowInvalidImageContentException("Bad Huffman Table type.");
}
// Max tables of each type
if (tableIndex > 3)
{
JpegThrowHelper.ThrowImageFormatException("Bad Huffman Table index.");
JpegThrowHelper.ThrowInvalidImageContentException("Bad Huffman Table index.");
}
this.InputStream.Read(huffmanData.Array, 0, 16);
@ -953,7 +953,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
if (codeLengthSum > 256 || codeLengthSum > length)
{
JpegThrowHelper.ThrowImageFormatException("Huffman table has excessive length.");
JpegThrowHelper.ThrowInvalidImageContentException("Huffman table has excessive length.");
}
using (IManagedByteBuffer huffmanValues = this.configuration.MemoryAllocator.AllocateManagedByteBuffer(256, AllocationOptions.Clean))
@ -995,7 +995,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
{
if (this.Frame is null)
{
JpegThrowHelper.ThrowImageFormatException("No readable SOFn (Start Of Frame) marker found.");
JpegThrowHelper.ThrowInvalidImageContentException("No readable SOFn (Start Of Frame) marker found.");
}
int selectorsCount = this.InputStream.ReadByte();
@ -1016,7 +1016,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
if (componentIndex < 0)
{
JpegThrowHelper.ThrowImageFormatException($"Unknown component selector {componentIndex}.");
JpegThrowHelper.ThrowInvalidImageContentException($"Unknown component selector {componentIndex}.");
}
ref JpegComponent component = ref this.Frame.Components[componentIndex];

27
src/ImageSharp/Formats/Jpeg/JpegThrowHelper.cs

@ -1,6 +1,7 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.CompilerServices;
namespace SixLabors.ImageSharp.Formats.Jpeg
@ -8,25 +9,33 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
internal static class JpegThrowHelper
{
/// <summary>
/// Cold path optimization for throwing <see cref="ImageFormatException"/>'s.
/// Cold path optimization for throwing <see cref="InvalidImageContentException"/>'s.
/// </summary>
/// <param name="errorMessage">The error message for the exception.</param>
[MethodImpl(InliningOptions.ColdPath)]
public static void ThrowImageFormatException(string errorMessage) => throw new ImageFormatException(errorMessage);
public static void ThrowInvalidImageContentException(string errorMessage) => throw new InvalidImageContentException(errorMessage);
/// <summary>
/// Cold path optimization for throwing <see cref="NotImplementedException"/>'s
/// </summary>
/// <param name="errorMessage">The error message for the exception.</param>
[MethodImpl(InliningOptions.ColdPath)]
public static void ThrowNotImplementedException(string errorMessage)
=> throw new NotImplementedException(errorMessage);
[MethodImpl(InliningOptions.ColdPath)]
public static void ThrowBadMarker(string marker, int length) => throw new ImageFormatException($"Marker {marker} has bad length {length}.");
public static void ThrowBadMarker(string marker, int length) => throw new InvalidImageContentException($"Marker {marker} has bad length {length}.");
[MethodImpl(InliningOptions.ColdPath)]
public static void ThrowBadQuantizationTable() => throw new ImageFormatException("Bad Quantization Table index.");
public static void ThrowBadQuantizationTable() => throw new InvalidImageContentException("Bad Quantization Table index.");
[MethodImpl(InliningOptions.ColdPath)]
public static void ThrowBadSampling() => throw new ImageFormatException("Bad sampling factor.");
public static void ThrowBadSampling() => throw new InvalidImageContentException("Bad sampling factor.");
[MethodImpl(InliningOptions.ColdPath)]
public static void ThrowBadProgressiveScan(int ss, int se, int ah, int al) => throw new ImageFormatException($"Invalid progressive parameters Ss={ss} Se={se} Ah={ah} Al={al}.");
public static void ThrowBadProgressiveScan(int ss, int se, int ah, int al) => throw new InvalidImageContentException($"Invalid progressive parameters Ss={ss} Se={se} Ah={ah} Al={al}.");
[MethodImpl(InliningOptions.ColdPath)]
public static void ThrowInvalidImageDimensions(int width, int height) => throw new ImageFormatException($"Invalid image dimensions: {width}x{height}.");
public static void ThrowInvalidImageDimensions(int width, int height) => throw new InvalidImageContentException($"Invalid image dimensions: {width}x{height}.");
}
}
}

28
src/ImageSharp/Formats/Png/PngDecoderCore.cs

@ -1141,24 +1141,22 @@ namespace SixLabors.ImageSharp.Formats.Png
/// <param name="chunk">The <see cref="PngChunk"/>.</param>
private void ValidateChunk(in PngChunk chunk)
{
if (!chunk.IsCritical)
{
return;
}
Span<byte> chunkType = stackalloc byte[4];
uint crc = this.ReadChunkCrc();
BinaryPrimitives.WriteUInt32BigEndian(chunkType, (uint)chunk.Type);
if (chunk.IsCritical)
{
Span<byte> chunkType = stackalloc byte[4];
BinaryPrimitives.WriteUInt32BigEndian(chunkType, (uint)chunk.Type);
this.crc.Reset();
this.crc.Update(chunkType);
this.crc.Update(chunk.Data.GetSpan());
this.crc.Reset();
this.crc.Update(chunkType);
this.crc.Update(chunk.Data.GetSpan());
uint crc = this.ReadChunkCrc();
if (this.crc.Value != crc)
{
string chunkTypeName = Encoding.ASCII.GetString(chunkType);
PngThrowHelper.ThrowInvalidChunkCrc(chunkTypeName);
if (this.crc.Value != crc)
{
string chunkTypeName = Encoding.ASCII.GetString(chunkType);
PngThrowHelper.ThrowInvalidChunkCrc(chunkTypeName);
}
}
}

10
src/ImageSharp/Formats/Png/PngThrowHelper.cs

@ -12,21 +12,21 @@ namespace SixLabors.ImageSharp.Formats.Png
internal static class PngThrowHelper
{
[MethodImpl(InliningOptions.ColdPath)]
public static void ThrowNoHeader() => throw new ImageFormatException("PNG Image does not contain a header chunk");
public static void ThrowNoHeader() => throw new InvalidImageContentException("PNG Image does not contain a header chunk");
[MethodImpl(InliningOptions.ColdPath)]
public static void ThrowNoData() => throw new ImageFormatException("PNG Image does not contain a data chunk");
public static void ThrowNoData() => throw new InvalidImageContentException("PNG Image does not contain a data chunk");
[MethodImpl(InliningOptions.ColdPath)]
public static void ThrowInvalidChunkType() => throw new ImageFormatException("Invalid PNG data.");
public static void ThrowInvalidChunkType() => throw new InvalidImageContentException("Invalid PNG data.");
[MethodImpl(InliningOptions.ColdPath)]
public static void ThrowInvalidChunkCrc(string chunkTypeName) => throw new ImageFormatException($"CRC Error. PNG {chunkTypeName} chunk is corrupt!");
public static void ThrowInvalidChunkCrc(string chunkTypeName) => throw new InvalidImageContentException($"CRC Error. PNG {chunkTypeName} chunk is corrupt!");
[MethodImpl(InliningOptions.ColdPath)]
public static void ThrowNotSupportedColor() => new NotSupportedException("Unsupported PNG color type");
[MethodImpl(InliningOptions.ColdPath)]
public static void ThrowUnknownFilter() => throw new ImageFormatException("Unknown filter type.");
public static void ThrowUnknownFilter() => throw new InvalidImageContentException("Unknown filter type.");
}
}

6
src/ImageSharp/Formats/Tga/TgaDecoderCore.cs

@ -114,12 +114,12 @@ namespace SixLabors.ImageSharp.Formats.Tga
{
if (this.fileHeader.CMapLength <= 0)
{
TgaThrowHelper.ThrowImageFormatException("Missing tga color map length");
TgaThrowHelper.ThrowInvalidImageContentException("Missing tga color map length");
}
if (this.fileHeader.CMapDepth <= 0)
{
TgaThrowHelper.ThrowImageFormatException("Missing tga color map depth");
TgaThrowHelper.ThrowInvalidImageContentException("Missing tga color map depth");
}
int colorMapPixelSizeInBytes = this.fileHeader.CMapDepth / 8;
@ -898,7 +898,7 @@ namespace SixLabors.ImageSharp.Formats.Tga
var alphaBits = this.fileHeader.ImageDescriptor & 0xf;
if (alphaBits != 0 && alphaBits != 1 && alphaBits != 8)
{
TgaThrowHelper.ThrowImageFormatException("Invalid alpha channel bits");
TgaThrowHelper.ThrowInvalidImageContentException("Invalid alpha channel bits");
}
this.tgaMetadata.AlphaChannelBits = (byte)alphaBits;

14
src/ImageSharp/Formats/Tga/TgaThrowHelper.cs

@ -9,23 +9,19 @@ namespace SixLabors.ImageSharp.Formats.Tga
internal static class TgaThrowHelper
{
/// <summary>
/// Cold path optimization for throwing <see cref="ImageFormatException"/>-s
/// Cold path optimization for throwing <see cref="ImageFormatException"/>'s
/// </summary>
/// <param name="errorMessage">The error message for the exception.</param>
[MethodImpl(MethodImplOptions.NoInlining)]
public static void ThrowImageFormatException(string errorMessage)
{
throw new ImageFormatException(errorMessage);
}
public static void ThrowInvalidImageContentException(string errorMessage)
=> throw new InvalidImageContentException(errorMessage);
/// <summary>
/// Cold path optimization for throwing <see cref="NotSupportedException"/>-s
/// Cold path optimization for throwing <see cref="NotSupportedException"/>'s
/// </summary>
/// <param name="errorMessage">The error message for the exception.</param>
[MethodImpl(MethodImplOptions.NoInlining)]
public static void ThrowNotSupportedException(string errorMessage)
{
throw new NotSupportedException(errorMessage);
}
=> throw new NotSupportedException(errorMessage);
}
}

147
src/ImageSharp/Image.FromBytes.cs

@ -17,21 +17,23 @@ namespace SixLabors.ImageSharp
/// By reading the header on the provided byte array this calculates the images format.
/// </summary>
/// <param name="data">The byte array containing encoded image data to read the header from.</param>
/// <exception cref="ArgumentNullException">The data is null.</exception>
/// <returns>The format or null if none found.</returns>
public static IImageFormat DetectFormat(byte[] data)
{
return DetectFormat(Configuration.Default, data);
}
=> DetectFormat(Configuration.Default, data);
/// <summary>
/// By reading the header on the provided byte array this calculates the images format.
/// </summary>
/// <param name="configuration">The configuration.</param>
/// <param name="data">The byte array containing encoded image data to read the header from.</param>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The data is null.</exception>
/// <returns>The mime type or null if none found.</returns>
public static IImageFormat DetectFormat(Configuration configuration, byte[] data)
{
Guard.NotNull(configuration, nameof(configuration));
Guard.NotNull(data, nameof(data));
using (var stream = new MemoryStream(data, 0, data.Length, false, true))
{
return DetectFormat(configuration, stream);
@ -42,7 +44,8 @@ namespace SixLabors.ImageSharp
/// Reads the raw image information from the specified stream without fully decoding it.
/// </summary>
/// <param name="data">The byte array containing encoded image data to read the header from.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <exception cref="ArgumentNullException">The data is null.</exception>
/// <exception cref="NotSupportedException">The data is not readable.</exception>
/// <returns>
/// The <see cref="IImageInfo"/> or null if suitable info detector not found.
/// </returns>
@ -53,7 +56,8 @@ namespace SixLabors.ImageSharp
/// </summary>
/// <param name="data">The byte array containing encoded image data to read the header from.</param>
/// <param name="format">The format type of the decoded image.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <exception cref="ArgumentNullException">The data is null.</exception>
/// <exception cref="NotSupportedException">The data is not readable.</exception>
/// <returns>
/// The <see cref="IImageInfo"/> or null if suitable info detector not found.
/// </returns>
@ -65,13 +69,16 @@ namespace SixLabors.ImageSharp
/// <param name="configuration">The configuration.</param>
/// <param name="data">The byte array containing encoded image data to read the header from.</param>
/// <param name="format">The format type of the decoded image.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The data is null.</exception>
/// <exception cref="NotSupportedException">The data is not readable.</exception>
/// <returns>
/// The <see cref="IImageInfo"/> or null if suitable info detector is not found.
/// </returns>
public static IImageInfo Identify(Configuration configuration, byte[] data, out IImageFormat format)
{
Guard.NotNull(configuration, nameof(configuration));
Guard.NotNull(data, nameof(data));
using (var stream = new MemoryStream(data, 0, data.Length, false, true))
{
return Identify(configuration, stream, out format);
@ -82,14 +89,20 @@ namespace SixLabors.ImageSharp
/// Load a new instance of <see cref="Image{Rgba32}"/> from the given encoded byte array.
/// </summary>
/// <param name="data">The byte array containing image data.</param>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The data is null.</exception>
/// <returns>A new <see cref="Image{Rgba32}"/>.</returns>
public static Image<Rgba32> Load(byte[] data) => Load<Rgba32>(Configuration.Default, data);
public static Image<Rgba32> Load(byte[] data)
=> Load<Rgba32>(Configuration.Default, data);
/// <summary>
/// Load a new instance of <see cref="Image{TPixel}"/> from the given encoded byte array.
/// </summary>
/// <param name="data">The byte array containing encoded image data.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <exception cref="ArgumentNullException">The data is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Load<TPixel>(byte[] data)
where TPixel : unmanaged, IPixel<TPixel>
@ -101,6 +114,9 @@ namespace SixLabors.ImageSharp
/// <param name="data">The byte array containing image data.</param>
/// <param name="format">The mime type of the decoded image.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <exception cref="ArgumentNullException">The data is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Load<TPixel>(byte[] data, out IImageFormat format)
where TPixel : unmanaged, IPixel<TPixel>
@ -112,10 +128,16 @@ namespace SixLabors.ImageSharp
/// <param name="configuration">The configuration options.</param>
/// <param name="data">The byte array containing encoded image data.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The data is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Load<TPixel>(Configuration configuration, byte[] data)
where TPixel : unmanaged, IPixel<TPixel>
{
Guard.NotNull(data, nameof(data));
using (var stream = new MemoryStream(data, 0, data.Length, false, true))
{
return Load<TPixel>(configuration, stream);
@ -129,10 +151,16 @@ namespace SixLabors.ImageSharp
/// <param name="data">The byte array containing encoded image data.</param>
/// <param name="format">The <see cref="IImageFormat"/> of the decoded image.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The data is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Load<TPixel>(Configuration configuration, byte[] data, out IImageFormat format)
where TPixel : unmanaged, IPixel<TPixel>
{
Guard.NotNull(data, nameof(data));
using (var stream = new MemoryStream(data, 0, data.Length, false, true))
{
return Load<TPixel>(configuration, stream, out format);
@ -145,10 +173,15 @@ namespace SixLabors.ImageSharp
/// <param name="data">The byte array containing encoded image data.</param>
/// <param name="decoder">The decoder.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <exception cref="ArgumentNullException">The data is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Load<TPixel>(byte[] data, IImageDecoder decoder)
where TPixel : unmanaged, IPixel<TPixel>
{
Guard.NotNull(data, nameof(data));
using (var stream = new MemoryStream(data, 0, data.Length, false, true))
{
return Load<TPixel>(stream, decoder);
@ -162,10 +195,16 @@ namespace SixLabors.ImageSharp
/// <param name="data">The byte array containing encoded image data.</param>
/// <param name="decoder">The decoder.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The data is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Load<TPixel>(Configuration configuration, byte[] data, IImageDecoder decoder)
where TPixel : unmanaged, IPixel<TPixel>
{
Guard.NotNull(data, nameof(data));
using (var stream = new MemoryStream(data, 0, data.Length, false, true))
{
return Load<TPixel>(configuration, stream, decoder);
@ -173,9 +212,9 @@ namespace SixLabors.ImageSharp
}
/// <summary>
/// By reading the header on the provided byte array this calculates the images format.
/// By reading the header on the provided byte span this calculates the images format.
/// </summary>
/// <param name="data">The byte array containing encoded image data to read the header from.</param>
/// <param name="data">The byte span containing encoded image data to read the header from.</param>
/// <returns>The format or null if none found.</returns>
public static IImageFormat DetectFormat(ReadOnlySpan<byte> data)
{
@ -183,13 +222,16 @@ namespace SixLabors.ImageSharp
}
/// <summary>
/// By reading the header on the provided byte array this calculates the images format.
/// By reading the header on the provided byte span this calculates the images format.
/// </summary>
/// <param name="configuration">The configuration.</param>
/// <param name="data">The byte array containing encoded image data to read the header from.</param>
/// <param name="data">The byte span containing encoded image data to read the header from.</param>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <returns>The mime type or null if none found.</returns>
public static IImageFormat DetectFormat(Configuration configuration, ReadOnlySpan<byte> data)
{
Guard.NotNull(configuration, nameof(configuration));
int maxHeaderSize = configuration.MaxHeaderSize;
if (maxHeaderSize <= 0)
{
@ -214,28 +256,34 @@ namespace SixLabors.ImageSharp
/// </summary>
/// <param name="data">The byte span containing encoded image data.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Load<TPixel>(ReadOnlySpan<byte> data)
where TPixel : unmanaged, IPixel<TPixel>
=> Load<TPixel>(Configuration.Default, data);
/// <summary>
/// Load a new instance of <see cref="Image{TPixel}"/> from the given encoded byte array.
/// Load a new instance of <see cref="Image{TPixel}"/> from the given encoded byte span.
/// </summary>
/// <param name="data">The byte span containing image data.</param>
/// <param name="format">The mime type of the decoded image.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Load<TPixel>(ReadOnlySpan<byte> data, out IImageFormat format)
where TPixel : unmanaged, IPixel<TPixel>
=> Load<TPixel>(Configuration.Default, data, out format);
/// <summary>
/// Load a new instance of <see cref="Image{TPixel}"/> from the given encoded byte array.
/// Load a new instance of <see cref="Image{TPixel}"/> from the given encoded byte span.
/// </summary>
/// <param name="data">The byte span containing encoded image data.</param>
/// <param name="decoder">The decoder.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Load<TPixel>(ReadOnlySpan<byte> data, IImageDecoder decoder)
where TPixel : unmanaged, IPixel<TPixel>
@ -247,6 +295,9 @@ namespace SixLabors.ImageSharp
/// <param name="configuration">The configuration options.</param>
/// <param name="data">The byte span containing encoded image data.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static unsafe Image<TPixel> Load<TPixel>(Configuration configuration, ReadOnlySpan<byte> data)
where TPixel : unmanaged, IPixel<TPixel>
@ -267,6 +318,9 @@ namespace SixLabors.ImageSharp
/// <param name="data">The byte span containing image data.</param>
/// <param name="decoder">The decoder.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static unsafe Image<TPixel> Load<TPixel>(
Configuration configuration,
@ -290,6 +344,9 @@ namespace SixLabors.ImageSharp
/// <param name="data">The byte span containing image data.</param>
/// <param name="format">The <see cref="IImageFormat"/> of the decoded image.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static unsafe Image<TPixel> Load<TPixel>(
Configuration configuration,
@ -311,25 +368,38 @@ namespace SixLabors.ImageSharp
/// </summary>
/// <param name="data">The byte array containing image data.</param>
/// <param name="format">The detected format.</param>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The data is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>The <see cref="Image"/>.</returns>
public static Image Load(byte[] data, out IImageFormat format) =>
Load(Configuration.Default, data, out format);
public static Image Load(byte[] data, out IImageFormat format)
=> Load(Configuration.Default, data, out format);
/// <summary>
/// Load a new instance of <see cref="Image"/> from the given encoded byte array.
/// </summary>
/// <param name="data">The byte array containing encoded image data.</param>
/// <param name="decoder">The decoder.</param>
/// <exception cref="ArgumentNullException">The data is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>The <see cref="Image"/>.</returns>
public static Image Load(byte[] data, IImageDecoder decoder) => Load(Configuration.Default, data, decoder);
public static Image Load(byte[] data, IImageDecoder decoder)
=> Load(Configuration.Default, data, decoder);
/// <summary>
/// Load a new instance of <see cref="Image"/> from the given encoded byte array.
/// </summary>
/// <param name="configuration">The configuration for the decoder.</param>
/// <param name="data">The byte array containing encoded image data.</param>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The data is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>The <see cref="Image"/>.</returns>
public static Image Load(Configuration configuration, byte[] data) => Load(configuration, data, out _);
public static Image Load(Configuration configuration, byte[] data)
=> Load(configuration, data, out _);
/// <summary>
/// Load a new instance of <see cref="Image"/> from the given encoded byte array.
@ -337,6 +407,10 @@ namespace SixLabors.ImageSharp
/// <param name="configuration">The configuration for the decoder.</param>
/// <param name="data">The byte array containing image data.</param>
/// <param name="decoder">The decoder.</param>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The data is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>The <see cref="Image"/>.</returns>
public static Image Load(Configuration configuration, byte[] data, IImageDecoder decoder)
{
@ -352,6 +426,10 @@ namespace SixLabors.ImageSharp
/// <param name="configuration">The configuration for the decoder.</param>
/// <param name="data">The byte array containing image data.</param>
/// <param name="format">The mime type of the decoded image.</param>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The data is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>The <see cref="Image"/>.</returns>
public static Image Load(Configuration configuration, byte[] data, out IImageFormat format)
{
@ -365,26 +443,36 @@ namespace SixLabors.ImageSharp
/// Load a new instance of <see cref="Image"/> from the given encoded byte span.
/// </summary>
/// <param name="data">The byte span containing image data.</param>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>The <see cref="Image"/>.</returns>
public static Image Load(ReadOnlySpan<byte> data) => Load(Configuration.Default, data);
public static Image Load(ReadOnlySpan<byte> data)
=> Load(Configuration.Default, data);
/// <summary>
/// Load a new instance of <see cref="Image"/> from the given encoded byte span.
/// </summary>
/// <param name="data">The byte span containing image data.</param>
/// <param name="decoder">The decoder.</param>
/// <exception cref="ArgumentNullException">The data is null.</exception>
/// <exception cref="ArgumentNullException">The decoder is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>The <see cref="Image"/>.</returns>
public static Image Load(ReadOnlySpan<byte> data, IImageDecoder decoder) =>
Load(Configuration.Default, data, decoder);
public static Image Load(ReadOnlySpan<byte> data, IImageDecoder decoder)
=> Load(Configuration.Default, data, decoder);
/// <summary>
/// Load a new instance of <see cref="Image"/> from the given encoded byte array.
/// </summary>
/// <param name="data">The byte span containing image data.</param>
/// <param name="format">The detected format.</param>
/// <exception cref="ArgumentNullException">The decoder is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>The <see cref="Image"/>.</returns>
public static Image Load(ReadOnlySpan<byte> data, out IImageFormat format) =>
Load(Configuration.Default, data, out format);
public static Image Load(ReadOnlySpan<byte> data, out IImageFormat format)
=> Load(Configuration.Default, data, out format);
/// <summary>
/// Decodes a new instance of <see cref="Image"/> from the given encoded byte span.
@ -392,7 +480,8 @@ namespace SixLabors.ImageSharp
/// <param name="configuration">The configuration options.</param>
/// <param name="data">The byte span containing image data.</param>
/// <returns>The <see cref="Image"/>.</returns>
public static Image Load(Configuration configuration, ReadOnlySpan<byte> data) => Load(configuration, data, out _);
public static Image Load(Configuration configuration, ReadOnlySpan<byte> data)
=> Load(configuration, data, out _);
/// <summary>
/// Load a new instance of <see cref="Image"/> from the given encoded byte span.
@ -400,6 +489,11 @@ namespace SixLabors.ImageSharp
/// <param name="configuration">The Configuration.</param>
/// <param name="data">The byte span containing image data.</param>
/// <param name="decoder">The decoder.</param>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The decoder is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>The <see cref="Image"/>.</returns>
public static unsafe Image Load(
Configuration configuration,
@ -421,6 +515,9 @@ namespace SixLabors.ImageSharp
/// <param name="configuration">The configuration options.</param>
/// <param name="data">The byte span containing image data.</param>
/// <param name="format">The <see cref="IImageFormat"/> of the decoded image.</param>>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>The <see cref="Image"/>.</returns>
public static unsafe Image Load(
Configuration configuration,

119
src/ImageSharp/Image.FromFile.cs

@ -19,19 +19,19 @@ namespace SixLabors.ImageSharp
/// <param name="filePath">The image file to open and to read the header from.</param>
/// <returns>The mime type or null if none found.</returns>
public static IImageFormat DetectFormat(string filePath)
{
return DetectFormat(Configuration.Default, filePath);
}
=> DetectFormat(Configuration.Default, filePath);
/// <summary>
/// By reading the header on the provided file this calculates the images mime type.
/// </summary>
/// <param name="configuration">The configuration.</param>
/// <param name="filePath">The image file to open and to read the header from.</param>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <returns>The mime type or null if none found.</returns>
public static IImageFormat DetectFormat(Configuration configuration, string filePath)
{
Guard.NotNull(configuration, nameof(configuration));
using (Stream file = configuration.FileSystem.OpenRead(filePath))
{
return DetectFormat(configuration, file);
@ -42,22 +42,22 @@ namespace SixLabors.ImageSharp
/// Reads the raw image information from the specified stream without fully decoding it.
/// </summary>
/// <param name="filePath">The image file to open and to read the header from.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <returns>
/// The <see cref="IImageInfo"/> or null if suitable info detector not found.
/// </returns>
public static IImageInfo Identify(string filePath) => Identify(filePath, out IImageFormat _);
public static IImageInfo Identify(string filePath)
=> Identify(filePath, out IImageFormat _);
/// <summary>
/// Reads the raw image information from the specified stream without fully decoding it.
/// </summary>
/// <param name="filePath">The image file to open and to read the header from.</param>
/// <param name="format">The format type of the decoded image.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <returns>
/// The <see cref="IImageInfo"/> or null if suitable info detector not found.
/// </returns>
public static IImageInfo Identify(string filePath, out IImageFormat format) => Identify(Configuration.Default, filePath, out format);
public static IImageInfo Identify(string filePath, out IImageFormat format)
=> Identify(Configuration.Default, filePath, out format);
/// <summary>
/// Reads the raw image information from the specified stream without fully decoding it.
@ -65,7 +65,7 @@ namespace SixLabors.ImageSharp
/// <param name="configuration">The configuration.</param>
/// <param name="filePath">The image file to open and to read the header from.</param>
/// <param name="format">The format type of the decoded image.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <returns>
/// The <see cref="IImageInfo"/> or null if suitable info detector is not found.
/// </returns>
@ -86,7 +86,8 @@ namespace SixLabors.ImageSharp
/// Thrown if the stream is not readable nor seekable.
/// </exception>
/// <returns>The <see cref="Image"/>.</returns>
public static Image Load(string path) => Load(Configuration.Default, path);
public static Image Load(string path)
=> Load(Configuration.Default, path);
/// <summary>
/// Create a new instance of the <see cref="Image"/> class from the given file.
@ -97,18 +98,21 @@ namespace SixLabors.ImageSharp
/// Thrown if the stream is not readable nor seekable.
/// </exception>
/// <returns>A new <see cref="Image{Rgba32}"/>.</returns>
public static Image Load(string path, out IImageFormat format) => Load(Configuration.Default, path, out format);
public static Image Load(string path, out IImageFormat format)
=> Load(Configuration.Default, path, out format);
/// <summary>
/// Create a new instance of the <see cref="Image"/> class from the given file.
/// </summary>
/// <param name="configuration">The configuration for the decoder.</param>
/// <param name="path">The file path to the image.</param>
/// <exception cref="NotSupportedException">
/// Thrown if the stream is not readable nor seekable.
/// </exception>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The path is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>The <see cref="Image"/>.</returns>
public static Image Load(Configuration configuration, string path) => Load(configuration, path, out _);
public static Image Load(Configuration configuration, string path)
=> Load(configuration, path, out _);
/// <summary>
/// Create a new instance of the <see cref="Image"/> class from the given file.
@ -116,13 +120,17 @@ namespace SixLabors.ImageSharp
/// <param name="configuration">The Configuration.</param>
/// <param name="path">The file path to the image.</param>
/// <param name="decoder">The decoder.</param>
/// <exception cref="NotSupportedException">
/// Thrown if the stream is not readable nor seekable.
/// </exception>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The path is null.</exception>
/// <exception cref="ArgumentNullException">The decoder is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>The <see cref="Image"/>.</returns>
public static Image Load(Configuration configuration, string path, IImageDecoder decoder)
{
Guard.NotNull(configuration, nameof(configuration));
Guard.NotNull(path, nameof(path));
using (Stream stream = configuration.FileSystem.OpenRead(path))
{
return Load(configuration, stream, decoder);
@ -134,57 +142,58 @@ namespace SixLabors.ImageSharp
/// </summary>
/// <param name="path">The file path to the image.</param>
/// <param name="decoder">The decoder.</param>
/// <exception cref="NotSupportedException">
/// Thrown if the stream is not readable nor seekable.
/// </exception>
/// <exception cref="ArgumentNullException">The path is null.</exception>
/// <exception cref="ArgumentNullException">The decoder is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>The <see cref="Image"/>.</returns>
public static Image Load(string path, IImageDecoder decoder) => Load(Configuration.Default, path, decoder);
public static Image Load(string path, IImageDecoder decoder)
=> Load(Configuration.Default, path, decoder);
/// <summary>
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given file.
/// </summary>
/// <param name="path">The file path to the image.</param>
/// <exception cref="NotSupportedException">
/// Thrown if the stream is not readable nor seekable.
/// </exception>
/// <exception cref="ArgumentNullException">The path is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Load<TPixel>(string path)
where TPixel : unmanaged, IPixel<TPixel>
{
return Load<TPixel>(Configuration.Default, path);
}
=> Load<TPixel>(Configuration.Default, path);
/// <summary>
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given file.
/// </summary>
/// <param name="path">The file path to the image.</param>
/// <param name="format">The mime type of the decoded image.</param>
/// <exception cref="NotSupportedException">
/// Thrown if the stream is not readable nor seekable.
/// </exception>
/// <exception cref="ArgumentNullException">The path is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Load<TPixel>(string path, out IImageFormat format)
where TPixel : unmanaged, IPixel<TPixel>
{
return Load<TPixel>(Configuration.Default, path, out format);
}
=> Load<TPixel>(Configuration.Default, path, out format);
/// <summary>
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given file.
/// </summary>
/// <param name="configuration">The configuration options.</param>
/// <param name="path">The file path to the image.</param>
/// <exception cref="NotSupportedException">
/// Thrown if the stream is not readable nor seekable.
/// </exception>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The path is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Load<TPixel>(Configuration configuration, string path)
where TPixel : unmanaged, IPixel<TPixel>
{
Guard.NotNull(configuration, nameof(configuration));
Guard.NotNull(path, nameof(path));
using (Stream stream = configuration.FileSystem.OpenRead(path))
{
return Load<TPixel>(configuration, stream);
@ -197,15 +206,18 @@ namespace SixLabors.ImageSharp
/// <param name="configuration">The configuration options.</param>
/// <param name="path">The file path to the image.</param>
/// <param name="format">The mime type of the decoded image.</param>
/// <exception cref="NotSupportedException">
/// Thrown if the stream is not readable nor seekable.
/// </exception>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The path is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Load<TPixel>(Configuration configuration, string path, out IImageFormat format)
where TPixel : unmanaged, IPixel<TPixel>
{
Guard.NotNull(configuration, nameof(configuration));
Guard.NotNull(path, nameof(path));
using (Stream stream = configuration.FileSystem.OpenRead(path))
{
return Load<TPixel>(configuration, stream, out format);
@ -219,13 +231,16 @@ namespace SixLabors.ImageSharp
/// <param name="configuration">The configuration options.</param>
/// <param name="path">The file path to the image.</param>
/// <param name="format">The mime type of the decoded image.</param>
/// <exception cref="NotSupportedException">
/// Thrown if the stream is not readable nor seekable.
/// </exception>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The path is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image Load(Configuration configuration, string path, out IImageFormat format)
{
Guard.NotNull(configuration, nameof(configuration));
Guard.NotNull(path, nameof(path));
using (Stream stream = configuration.FileSystem.OpenRead(path))
{
return Load(configuration, stream, out format);
@ -237,16 +252,14 @@ namespace SixLabors.ImageSharp
/// </summary>
/// <param name="path">The file path to the image.</param>
/// <param name="decoder">The decoder.</param>
/// <exception cref="NotSupportedException">
/// Thrown if the stream is not readable nor seekable.
/// </exception>
/// <exception cref="ArgumentNullException">The path is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Load<TPixel>(string path, IImageDecoder decoder)
where TPixel : unmanaged, IPixel<TPixel>
{
return Load<TPixel>(Configuration.Default, path, decoder);
}
=> Load<TPixel>(Configuration.Default, path, decoder);
/// <summary>
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given file.
@ -254,15 +267,19 @@ namespace SixLabors.ImageSharp
/// <param name="configuration">The Configuration.</param>
/// <param name="path">The file path to the image.</param>
/// <param name="decoder">The decoder.</param>
/// <exception cref="NotSupportedException">
/// Thrown if the stream is not readable nor seekable.
/// </exception>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The path is null.</exception>
/// <exception cref="ArgumentNullException">The decoder is null.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Load<TPixel>(Configuration configuration, string path, IImageDecoder decoder)
where TPixel : unmanaged, IPixel<TPixel>
{
Guard.NotNull(configuration, nameof(configuration));
Guard.NotNull(path, nameof(path));
using (Stream stream = configuration.FileSystem.OpenRead(path))
{
return Load<TPixel>(configuration, stream, decoder);

131
src/ImageSharp/Image.FromStream.cs

@ -19,16 +19,20 @@ namespace SixLabors.ImageSharp
/// By reading the header on the provided stream this calculates the images format type.
/// </summary>
/// <param name="stream">The image stream to read the header from.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
/// <returns>The format type or null if none found.</returns>
public static IImageFormat DetectFormat(Stream stream) => DetectFormat(Configuration.Default, stream);
public static IImageFormat DetectFormat(Stream stream)
=> DetectFormat(Configuration.Default, stream);
/// <summary>
/// By reading the header on the provided stream this calculates the images format type.
/// </summary>
/// <param name="configuration">The configuration.</param>
/// <param name="stream">The image stream to read the header from.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
/// <returns>The format type or null if none found.</returns>
public static IImageFormat DetectFormat(Configuration configuration, Stream stream)
=> WithSeekableStream(configuration, stream, s => InternalDetectFormat(s, configuration));
@ -37,22 +41,28 @@ namespace SixLabors.ImageSharp
/// Reads the raw image information from the specified stream without fully decoding it.
/// </summary>
/// <param name="stream">The image stream to read the header from.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>
/// The <see cref="IImageInfo"/> or null if suitable info detector not found.
/// </returns>
public static IImageInfo Identify(Stream stream) => Identify(stream, out IImageFormat _);
public static IImageInfo Identify(Stream stream)
=> Identify(stream, out IImageFormat _);
/// <summary>
/// Reads the raw image information from the specified stream without fully decoding it.
/// </summary>
/// <param name="stream">The image stream to read the header from.</param>
/// <param name="format">The format type of the decoded image.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>
/// The <see cref="IImageInfo"/> or null if suitable info detector not found.
/// </returns>
public static IImageInfo Identify(Stream stream, out IImageFormat format) => Identify(Configuration.Default, stream, out format);
public static IImageInfo Identify(Stream stream, out IImageFormat format)
=> Identify(Configuration.Default, stream, out format);
/// <summary>
/// Reads the raw image information from the specified stream without fully decoding it.
@ -60,7 +70,10 @@ namespace SixLabors.ImageSharp
/// <param name="configuration">The configuration.</param>
/// <param name="stream">The image stream to read the information from.</param>
/// <param name="format">The format type of the decoded image.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>
/// The <see cref="IImageInfo"/> or null if suitable info detector is not found.
/// </returns>
@ -78,18 +91,23 @@ namespace SixLabors.ImageSharp
/// </summary>
/// <param name="stream">The stream containing image information.</param>
/// <param name="format">The format type of the decoded image.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <exception cref="UnknownImageFormatException">Image cannot be loaded.</exception>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>The <see cref="Image"/>.</returns>
public static Image Load(Stream stream, out IImageFormat format) => Load(Configuration.Default, stream, out format);
public static Image Load(Stream stream, out IImageFormat format)
=> Load(Configuration.Default, stream, out format);
/// <summary>
/// Decode a new instance of the <see cref="Image"/> class from the given stream.
/// The pixel format is selected by the decoder.
/// </summary>
/// <param name="stream">The stream containing image information.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <exception cref="UnknownImageFormatException">Image cannot be loaded.</exception>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>The <see cref="Image"/>.</returns>
public static Image Load(Stream stream) => Load(Configuration.Default, stream);
@ -99,10 +117,14 @@ namespace SixLabors.ImageSharp
/// </summary>
/// <param name="stream">The stream containing image information.</param>
/// <param name="decoder">The decoder.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <exception cref="UnknownImageFormatException">Image cannot be loaded.</exception>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="ArgumentNullException">The decoder is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>The <see cref="Image"/>.</returns>
public static Image Load(Stream stream, IImageDecoder decoder) => Load(Configuration.Default, stream, decoder);
public static Image Load(Stream stream, IImageDecoder decoder)
=> Load(Configuration.Default, stream, decoder);
/// <summary>
/// Decode a new instance of the <see cref="Image"/> class from the given stream.
@ -111,19 +133,29 @@ namespace SixLabors.ImageSharp
/// <param name="configuration">The configuration for the decoder.</param>
/// <param name="stream">The stream containing image information.</param>
/// <param name="decoder">The decoder.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <exception cref="UnknownImageFormatException">Image cannot be loaded.</exception>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="ArgumentNullException">The decoder is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>A new <see cref="Image"/>.</returns>>
public static Image Load(Configuration configuration, Stream stream, IImageDecoder decoder) =>
WithSeekableStream(configuration, stream, s => decoder.Decode(configuration, s));
public static Image Load(Configuration configuration, Stream stream, IImageDecoder decoder)
{
Guard.NotNull(decoder, nameof(decoder));
return WithSeekableStream(configuration, stream, s => decoder.Decode(configuration, s));
}
/// <summary>
/// Decode a new instance of the <see cref="Image"/> class from the given stream.
/// </summary>
/// <param name="configuration">The configuration for the decoder.</param>
/// <param name="stream">The stream containing image information.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <exception cref="UnknownImageFormatException">Image cannot be loaded.</exception>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>A new <see cref="Image"/>.</returns>>
public static Image Load(Configuration configuration, Stream stream) => Load(configuration, stream, out _);
@ -131,8 +163,10 @@ namespace SixLabors.ImageSharp
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given stream.
/// </summary>
/// <param name="stream">The stream containing image information.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <exception cref="UnknownImageFormatException">Image cannot be loaded.</exception>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>>
public static Image<TPixel> Load<TPixel>(Stream stream)
@ -144,8 +178,10 @@ namespace SixLabors.ImageSharp
/// </summary>
/// <param name="stream">The stream containing image information.</param>
/// <param name="format">The format type of the decoded image.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <exception cref="UnknownImageFormatException">Image cannot be loaded.</exception>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>>
public static Image<TPixel> Load<TPixel>(Stream stream, out IImageFormat format)
@ -157,8 +193,10 @@ namespace SixLabors.ImageSharp
/// </summary>
/// <param name="stream">The stream containing image information.</param>
/// <param name="decoder">The decoder.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <exception cref="UnknownImageFormatException">Image cannot be loaded.</exception>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>>
public static Image<TPixel> Load<TPixel>(Stream stream, IImageDecoder decoder)
@ -171,8 +209,11 @@ namespace SixLabors.ImageSharp
/// <param name="configuration">The Configuration.</param>
/// <param name="stream">The stream containing image information.</param>
/// <param name="decoder">The decoder.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <exception cref="UnknownImageFormatException">Image cannot be loaded.</exception>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>>
public static Image<TPixel> Load<TPixel>(Configuration configuration, Stream stream, IImageDecoder decoder)
@ -184,8 +225,11 @@ namespace SixLabors.ImageSharp
/// </summary>
/// <param name="configuration">The configuration options.</param>
/// <param name="stream">The stream containing image information.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <exception cref="UnknownImageFormatException">Image cannot be loaded.</exception>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>>
public static Image<TPixel> Load<TPixel>(Configuration configuration, Stream stream)
@ -198,14 +242,16 @@ namespace SixLabors.ImageSharp
/// <param name="configuration">The configuration options.</param>
/// <param name="stream">The stream containing image information.</param>
/// <param name="format">The format type of the decoded image.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <exception cref="UnknownImageFormatException">Image cannot be loaded.</exception>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Load<TPixel>(Configuration configuration, Stream stream, out IImageFormat format)
where TPixel : unmanaged, IPixel<TPixel>
{
Guard.NotNull(configuration, nameof(configuration));
(Image<TPixel> img, IImageFormat format) data = WithSeekableStream(configuration, stream, s => Decode<TPixel>(s, configuration));
format = data.format;
@ -220,7 +266,7 @@ namespace SixLabors.ImageSharp
foreach (KeyValuePair<IImageFormat, IImageDecoder> val in configuration.ImageFormatsManager.ImageDecoders)
{
sb.AppendLine($" - {val.Key.Name} : {val.Value.GetType().Name}");
sb.AppendFormat(" - {0} : {1}{2}", val.Key.Name, val.Value.GetType().Name, Environment.NewLine);
}
throw new UnknownImageFormatException(sb.ToString());
@ -233,12 +279,14 @@ namespace SixLabors.ImageSharp
/// <param name="configuration">The configuration options.</param>
/// <param name="stream">The stream containing image information.</param>
/// <param name="format">The format type of the decoded image.</param>
/// <exception cref="NotSupportedException">Thrown if the stream is not readable.</exception>
/// <exception cref="UnknownImageFormatException">Image cannot be loaded.</exception>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="NotSupportedException">The stream is not readable.</exception>
/// <exception cref="UnknownImageFormatException">Image format not recognised.</exception>
/// <exception cref="InvalidImageContentException">Image contains invalid content.</exception>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image Load(Configuration configuration, Stream stream, out IImageFormat format)
{
Guard.NotNull(configuration, nameof(configuration));
(Image img, IImageFormat format) data = WithSeekableStream(configuration, stream, s => Decode(s, configuration));
format = data.format;
@ -253,7 +301,7 @@ namespace SixLabors.ImageSharp
foreach (KeyValuePair<IImageFormat, IImageDecoder> val in configuration.ImageFormatsManager.ImageDecoders)
{
sb.AppendLine($" - {val.Key.Name} : {val.Value.GetType().Name}");
sb.AppendFormat(" - {0} : {1}{2}", val.Key.Name, val.Value.GetType().Name, Environment.NewLine);
}
throw new UnknownImageFormatException(sb.ToString());
@ -261,6 +309,9 @@ namespace SixLabors.ImageSharp
private static T WithSeekableStream<T>(Configuration configuration, Stream stream, Func<Stream, T> action)
{
Guard.NotNull(configuration, nameof(configuration));
Guard.NotNull(stream, nameof(stream));
if (!stream.CanRead)
{
throw new NotSupportedException("Cannot read from the stream.");

43
src/ImageSharp/Image.LoadPixelData.cs

@ -1,9 +1,8 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Runtime.InteropServices;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Memory;
using SixLabors.ImageSharp.PixelFormats;
@ -21,6 +20,7 @@ namespace SixLabors.ImageSharp
/// <param name="width">The width of the final image.</param>
/// <param name="height">The height of the final image.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <exception cref="ArgumentException">The data length is incorrect.</exception>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> LoadPixelData<TPixel>(TPixel[] data, int width, int height)
where TPixel : unmanaged, IPixel<TPixel>
@ -33,6 +33,7 @@ namespace SixLabors.ImageSharp
/// <param name="width">The width of the final image.</param>
/// <param name="height">The height of the final image.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <exception cref="ArgumentException">The data length is incorrect.</exception>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> LoadPixelData<TPixel>(ReadOnlySpan<TPixel> data, int width, int height)
where TPixel : unmanaged, IPixel<TPixel>
@ -45,6 +46,7 @@ namespace SixLabors.ImageSharp
/// <param name="width">The width of the final image.</param>
/// <param name="height">The height of the final image.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <exception cref="ArgumentException">The data length is incorrect.</exception>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> LoadPixelData<TPixel>(byte[] data, int width, int height)
where TPixel : unmanaged, IPixel<TPixel>
@ -57,6 +59,7 @@ namespace SixLabors.ImageSharp
/// <param name="width">The width of the final image.</param>
/// <param name="height">The height of the final image.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <exception cref="ArgumentException">The data length is incorrect.</exception>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> LoadPixelData<TPixel>(ReadOnlySpan<byte> data, int width, int height)
where TPixel : unmanaged, IPixel<TPixel>
@ -65,60 +68,68 @@ namespace SixLabors.ImageSharp
/// <summary>
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given byte array in <typeparamref name="TPixel"/> format.
/// </summary>
/// <param name="config">The config for the decoder.</param>
/// <param name="configuration">The configuration for the decoder.</param>
/// <param name="data">The byte array containing image data.</param>
/// <param name="width">The width of the final image.</param>
/// <param name="height">The height of the final image.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentException">The data length is incorrect.</exception>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> LoadPixelData<TPixel>(Configuration config, byte[] data, int width, int height)
public static Image<TPixel> LoadPixelData<TPixel>(Configuration configuration, byte[] data, int width, int height)
where TPixel : unmanaged, IPixel<TPixel>
=> LoadPixelData(config, MemoryMarshal.Cast<byte, TPixel>(new ReadOnlySpan<byte>(data)), width, height);
=> LoadPixelData(configuration, MemoryMarshal.Cast<byte, TPixel>(new ReadOnlySpan<byte>(data)), width, height);
/// <summary>
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the given byte array in <typeparamref name="TPixel"/> format.
/// </summary>
/// <param name="config">The config for the decoder.</param>
/// <param name="configuration">The configuration for the decoder.</param>
/// <param name="data">The byte array containing image data.</param>
/// <param name="width">The width of the final image.</param>
/// <param name="height">The height of the final image.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentException">The data length is incorrect.</exception>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> LoadPixelData<TPixel>(Configuration config, ReadOnlySpan<byte> data, int width, int height)
public static Image<TPixel> LoadPixelData<TPixel>(Configuration configuration, ReadOnlySpan<byte> data, int width, int height)
where TPixel : unmanaged, IPixel<TPixel>
=> LoadPixelData(config, MemoryMarshal.Cast<byte, TPixel>(data), width, height);
=> LoadPixelData(configuration, MemoryMarshal.Cast<byte, TPixel>(data), width, height);
/// <summary>
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the raw <typeparamref name="TPixel"/> data.
/// </summary>
/// <param name="config">The config for the decoder.</param>
/// <param name="configuration">The configuration for the decoder.</param>
/// <param name="data">The Span containing the image Pixel data.</param>
/// <param name="width">The width of the final image.</param>
/// <param name="height">The height of the final image.</param>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentException">The data length is incorrect.</exception>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> LoadPixelData<TPixel>(Configuration config, TPixel[] data, int width, int height)
public static Image<TPixel> LoadPixelData<TPixel>(Configuration configuration, TPixel[] data, int width, int height)
where TPixel : unmanaged, IPixel<TPixel>
{
return LoadPixelData(config, new ReadOnlySpan<TPixel>(data), width, height);
}
=> LoadPixelData(configuration, new ReadOnlySpan<TPixel>(data), width, height);
/// <summary>
/// Create a new instance of the <see cref="Image{TPixel}"/> class from the raw <typeparamref name="TPixel"/> data.
/// </summary>
/// <param name="config">The config for the decoder.</param>
/// <param name="configuration">The configuration for the decoder.</param>
/// <param name="data">The Span containing the image Pixel data.</param>
/// <param name="width">The width of the final image.</param>
/// <param name="height">The height of the final image.</param>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentException">The data length is incorrect.</exception>
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <returns>A new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> LoadPixelData<TPixel>(Configuration config, ReadOnlySpan<TPixel> data, int width, int height)
public static Image<TPixel> LoadPixelData<TPixel>(Configuration configuration, ReadOnlySpan<TPixel> data, int width, int height)
where TPixel : unmanaged, IPixel<TPixel>
{
Guard.NotNull(configuration, nameof(configuration));
int count = width * height;
Guard.MustBeGreaterThanOrEqualTo(data.Length, count, nameof(data));
var image = new Image<TPixel>(config, width, height);
var image = new Image<TPixel>(configuration, width, height);
data = data.Slice(0, count);
data.CopyTo(image.Frames.RootFrame.PixelBuffer.FastMemoryGroup);

50
src/ImageSharp/Image.WrapMemory.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
@ -20,22 +20,27 @@ namespace SixLabors.ImageSharp
/// allowing to view/manipulate it as an ImageSharp <see cref="Image{TPixel}"/> instance.
/// </summary>
/// <typeparam name="TPixel">The pixel type</typeparam>
/// <param name="config">The <see cref="ImageSharp.Configuration"/></param>
/// <param name="configuration">The <see cref="Configuration"/></param>
/// <param name="pixelMemory">The pixel memory.</param>
/// <param name="width">The width of the memory image.</param>
/// <param name="height">The height of the memory image.</param>
/// <param name="metadata">The <see cref="ImageMetadata"/>.</param>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The metadata is null.</exception>
/// <returns>An <see cref="Image{TPixel}"/> instance</returns>
public static Image<TPixel> WrapMemory<TPixel>(
Configuration config,
Configuration configuration,
Memory<TPixel> pixelMemory,
int width,
int height,
ImageMetadata metadata)
where TPixel : unmanaged, IPixel<TPixel>
{
Guard.NotNull(configuration, nameof(configuration));
Guard.NotNull(metadata, nameof(metadata));
var memorySource = MemoryGroup<TPixel>.Wrap(pixelMemory);
return new Image<TPixel>(config, memorySource, width, height, metadata);
return new Image<TPixel>(configuration, memorySource, width, height, metadata);
}
/// <summary>
@ -43,20 +48,19 @@ namespace SixLabors.ImageSharp
/// allowing to view/manipulate it as an ImageSharp <see cref="Image{TPixel}"/> instance.
/// </summary>
/// <typeparam name="TPixel">The pixel type</typeparam>
/// <param name="config">The <see cref="ImageSharp.Configuration"/></param>
/// <param name="configuration">The <see cref="Configuration"/></param>
/// <param name="pixelMemory">The pixel memory.</param>
/// <param name="width">The width of the memory image.</param>
/// <param name="height">The height of the memory image.</param>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <returns>An <see cref="Image{TPixel}"/> instance.</returns>
public static Image<TPixel> WrapMemory<TPixel>(
Configuration config,
Configuration configuration,
Memory<TPixel> pixelMemory,
int width,
int height)
where TPixel : unmanaged, IPixel<TPixel>
{
return WrapMemory(config, pixelMemory, width, height, new ImageMetadata());
}
=> WrapMemory(configuration, pixelMemory, width, height, new ImageMetadata());
/// <summary>
/// Wraps an existing contiguous memory area of 'width' x 'height' pixels,
@ -73,9 +77,7 @@ namespace SixLabors.ImageSharp
int width,
int height)
where TPixel : unmanaged, IPixel<TPixel>
{
return WrapMemory(Configuration.Default, pixelMemory, width, height);
}
=> WrapMemory(Configuration.Default, pixelMemory, width, height);
/// <summary>
/// Wraps an existing contiguous memory area of 'width' x 'height' pixels,
@ -85,22 +87,27 @@ namespace SixLabors.ImageSharp
/// It will be disposed together with the result image.
/// </summary>
/// <typeparam name="TPixel">The pixel type</typeparam>
/// <param name="config">The <see cref="ImageSharp.Configuration"/></param>
/// <param name="configuration">The <see cref="Configuration"/></param>
/// <param name="pixelMemoryOwner">The <see cref="IMemoryOwner{T}"/> that is being transferred to the image</param>
/// <param name="width">The width of the memory image.</param>
/// <param name="height">The height of the memory image.</param>
/// <param name="metadata">The <see cref="ImageMetadata"/></param>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The metadata is null.</exception>
/// <returns>An <see cref="Image{TPixel}"/> instance</returns>
public static Image<TPixel> WrapMemory<TPixel>(
Configuration config,
Configuration configuration,
IMemoryOwner<TPixel> pixelMemoryOwner,
int width,
int height,
ImageMetadata metadata)
where TPixel : unmanaged, IPixel<TPixel>
{
Guard.NotNull(configuration, nameof(configuration));
Guard.NotNull(metadata, nameof(metadata));
var memorySource = MemoryGroup<TPixel>.Wrap(pixelMemoryOwner);
return new Image<TPixel>(config, memorySource, width, height, metadata);
return new Image<TPixel>(configuration, memorySource, width, height, metadata);
}
/// <summary>
@ -111,20 +118,19 @@ namespace SixLabors.ImageSharp
/// It will be disposed together with the result image.
/// </summary>
/// <typeparam name="TPixel">The pixel type.</typeparam>
/// <param name="config">The <see cref="ImageSharp.Configuration"/></param>
/// <param name="configuration">The <see cref="Configuration"/></param>
/// <param name="pixelMemoryOwner">The <see cref="IMemoryOwner{T}"/> that is being transferred to the image.</param>
/// <param name="width">The width of the memory image.</param>
/// <param name="height">The height of the memory image.</param>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <returns>An <see cref="Image{TPixel}"/> instance</returns>
public static Image<TPixel> WrapMemory<TPixel>(
Configuration config,
Configuration configuration,
IMemoryOwner<TPixel> pixelMemoryOwner,
int width,
int height)
where TPixel : unmanaged, IPixel<TPixel>
{
return WrapMemory(config, pixelMemoryOwner, width, height, new ImageMetadata());
}
=> WrapMemory(configuration, pixelMemoryOwner, width, height, new ImageMetadata());
/// <summary>
/// Wraps an existing contiguous memory area of 'width' x 'height' pixels,
@ -143,8 +149,6 @@ namespace SixLabors.ImageSharp
int width,
int height)
where TPixel : unmanaged, IPixel<TPixel>
{
return WrapMemory(Configuration.Default, pixelMemoryOwner, width, height);
}
=> WrapMemory(Configuration.Default, pixelMemoryOwner, width, height);
}
}

46
src/ImageSharp/ImageExtensions.cs

@ -7,12 +7,11 @@ using System.IO;
using System.Text;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.Formats;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp
{
/// <summary>
/// Extension methods over Image{TPixel}.
/// Extension methods for the <see cref="Image"/> type.
/// </summary>
public static partial class ImageExtensions
{
@ -20,13 +19,13 @@ namespace SixLabors.ImageSharp
/// Writes the image to the given stream using the currently loaded image format.
/// </summary>
/// <param name="source">The source image.</param>
/// <param name="filePath">The file path to save the image to.</param>
/// <exception cref="System.ArgumentNullException">Thrown if the stream is null.</exception>
public static void Save(this Image source, string filePath)
/// <param name="path">The file path to save the image to.</param>
/// <exception cref="ArgumentNullException">The path is null.</exception>
public static void Save(this Image source, string path)
{
Guard.NotNullOrWhiteSpace(filePath, nameof(filePath));
Guard.NotNull(path, nameof(path));
string ext = Path.GetExtension(filePath);
string ext = Path.GetExtension(path);
IImageFormat format = source.GetConfiguration().ImageFormatsManager.FindFormatByFileExtension(ext);
if (format is null)
{
@ -34,7 +33,7 @@ namespace SixLabors.ImageSharp
sb.AppendLine($"No encoder was found for extension '{ext}'. Registered encoders include:");
foreach (IImageFormat fmt in source.GetConfiguration().ImageFormats)
{
sb.AppendLine($" - {fmt.Name} : {string.Join(", ", fmt.FileExtensions)}");
sb.AppendFormat(" - {0} : {1}{2}", fmt.Name, string.Join(", ", fmt.FileExtensions), Environment.NewLine);
}
throw new NotSupportedException(sb.ToString());
@ -48,26 +47,28 @@ namespace SixLabors.ImageSharp
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.AppendLine($" - {enc.Key} : {enc.Value.GetType().Name}");
sb.AppendFormat(" - {0} : {1}{2}", enc.Key, enc.Value.GetType().Name, Environment.NewLine);
}
throw new NotSupportedException(sb.ToString());
}
source.Save(filePath, encoder);
source.Save(path, encoder);
}
/// <summary>
/// Writes the image to the given stream using the currently loaded image format.
/// </summary>
/// <param name="source">The source image.</param>
/// <param name="filePath">The file path to save the image to.</param>
/// <param name="path">The file path to save the image to.</param>
/// <param name="encoder">The encoder to save the image with.</param>
/// <exception cref="ArgumentNullException">Thrown if the encoder is null.</exception>
public static void Save(this Image source, string filePath, IImageEncoder encoder)
/// <exception cref="ArgumentNullException">The path is null.</exception>
/// <exception cref="ArgumentNullException">The encoder is null.</exception>
public static void Save(this Image source, string path, IImageEncoder encoder)
{
Guard.NotNull(path, nameof(path));
Guard.NotNull(encoder, nameof(encoder));
using (Stream fs = source.GetConfiguration().FileSystem.Create(filePath))
using (Stream fs = source.GetConfiguration().FileSystem.Create(path))
{
source.Save(fs, encoder);
}
@ -79,10 +80,20 @@ namespace SixLabors.ImageSharp
/// <param name="source">The source image.</param>
/// <param name="stream">The stream to save the image to.</param>
/// <param name="format">The format to save the image in.</param>
/// <exception cref="ArgumentNullException">Thrown if the stream is null.</exception>
/// <exception cref="ArgumentNullException">The stream is null.</exception>
/// <exception cref="ArgumentNullException">The format is null.</exception>
/// <exception cref="NotSupportedException">The stream is not writable.</exception>
/// <exception cref="NotSupportedException">No encoder available for provided format.</exception>
public static void Save(this Image source, Stream stream, IImageFormat format)
{
Guard.NotNull(stream, nameof(stream));
Guard.NotNull(format, nameof(format));
if (!stream.CanWrite)
{
throw new NotSupportedException("Cannot write to the stream.");
}
IImageEncoder encoder = source.GetConfiguration().ImageFormatsManager.FindEncoder(format);
if (encoder is null)
@ -92,7 +103,7 @@ namespace SixLabors.ImageSharp
foreach (KeyValuePair<IImageFormat, IImageEncoder> val in source.GetConfiguration().ImageFormatsManager.ImageEncoders)
{
sb.AppendLine($" - {val.Key.Name} : {val.Value.GetType().Name}");
sb.AppendFormat(" - {0} : {1}{2}", val.Key.Name, val.Value.GetType().Name, Environment.NewLine);
}
throw new NotSupportedException(sb.ToString());
@ -113,9 +124,12 @@ namespace SixLabors.ImageSharp
/// </summary>
/// <param name="source">The source image</param>
/// <param name="format">The format.</param>
/// <exception cref="ArgumentNullException">The format is null.</exception>
/// <returns>The <see cref="string"/></returns>
public static string ToBase64String(this Image source, IImageFormat format)
{
Guard.NotNull(format, nameof(format));
using var stream = new MemoryStream();
source.Save(stream, format);

4
src/ImageSharp/Memory/Buffer2D{T}.cs

@ -156,7 +156,7 @@ namespace SixLabors.ImageSharp.Memory
{
DebugGuard.MustBeGreaterThanOrEqualTo(y, 0, nameof(y));
DebugGuard.MustBeLessThan(y, this.Height, nameof(y));
return this.FastMemoryGroup.View.GetBoundedSlice(y * this.Width, this.Width);
return this.FastMemoryGroup.View.GetBoundedSlice(y * (long)this.Width, this.Width);
}
/// <summary>
@ -200,7 +200,7 @@ namespace SixLabors.ImageSharp.Memory
}
[MethodImpl(InliningOptions.ColdPath)]
private Memory<T> GetRowMemorySlow(int y) => this.FastMemoryGroup.GetBoundedSlice(y * this.Width, this.Width);
private Memory<T> GetRowMemorySlow(int y) => this.FastMemoryGroup.GetBoundedSlice(y * (long)this.Width, this.Width);
[MethodImpl(InliningOptions.ColdPath)]
private Memory<T> GetSingleMemorySlow() => this.FastMemoryGroup.Single();

8
src/ImageSharp/Memory/DiscontiguousBuffers/MemoryGroupExtensions.cs

@ -1,4 +1,4 @@
// Copyright (c) Six Labors and contributors.
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
@ -38,6 +38,12 @@ namespace SixLabors.ImageSharp.Memory
Guard.MustBeLessThan(start, group.TotalLength, nameof(start));
int bufferIdx = (int)(start / group.BufferLength);
if (bufferIdx < 0)
{
throw new ArgumentOutOfRangeException(nameof(start));
}
if (bufferIdx >= group.Count)
{
throw new ArgumentOutOfRangeException(nameof(start));

67
src/ImageSharp/Processing/Extensions/ProcessingExtensions.cs

@ -19,6 +19,10 @@ namespace SixLabors.ImageSharp.Processing
/// </summary>
/// <param name="source">The image to mutate.</param>
/// <param name="operation">The operation to perform on the source.</param>
/// <exception cref="ArgumentNullException">The source is null.</exception>
/// <exception cref="ArgumentNullException">The operation is null.</exception>
/// <exception cref="ObjectDisposedException">The source has been disposed.</exception>
/// <exception cref="ImageProcessingException">The processing operation failed.</exception>
public static void Mutate(this Image source, Action<IImageProcessingContext> operation)
=> Mutate(source, source.GetConfiguration(), operation);
@ -28,6 +32,11 @@ namespace SixLabors.ImageSharp.Processing
/// <param name="source">The image to mutate.</param>
/// <param name="configuration">The configuration which allows altering default behaviour or extending the library.</param>
/// <param name="operation">The operation to perform on the source.</param>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The source is null.</exception>
/// <exception cref="ArgumentNullException">The operation is null.</exception>
/// <exception cref="ObjectDisposedException">The source has been disposed.</exception>
/// <exception cref="ImageProcessingException">The processing operation failed.</exception>
public static void Mutate(this Image source, Configuration configuration, Action<IImageProcessingContext> operation)
{
Guard.NotNull(configuration, nameof(configuration));
@ -44,6 +53,10 @@ namespace SixLabors.ImageSharp.Processing
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image to mutate.</param>
/// <param name="operation">The operation to perform on the source.</param>
/// <exception cref="ArgumentNullException">The source is null.</exception>
/// <exception cref="ArgumentNullException">The operation is null.</exception>
/// <exception cref="ObjectDisposedException">The source has been disposed.</exception>
/// <exception cref="ImageProcessingException">The processing operation failed.</exception>
public static void Mutate<TPixel>(this Image<TPixel> source, Action<IImageProcessingContext> operation)
where TPixel : unmanaged, IPixel<TPixel>
=> Mutate(source, source.GetConfiguration(), operation);
@ -55,6 +68,11 @@ namespace SixLabors.ImageSharp.Processing
/// <param name="source">The image to mutate.</param>
/// <param name="configuration">The configuration which allows altering default behaviour or extending the library.</param>
/// <param name="operation">The operation to perform on the source.</param>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The source is null.</exception>
/// <exception cref="ArgumentNullException">The operation is null.</exception>
/// <exception cref="ObjectDisposedException">The source has been disposed.</exception>
/// <exception cref="ImageProcessingException">The processing operation failed.</exception>
public static void Mutate<TPixel>(this Image<TPixel> source, Configuration configuration, Action<IImageProcessingContext> operation)
where TPixel : unmanaged, IPixel<TPixel>
{
@ -75,6 +93,10 @@ namespace SixLabors.ImageSharp.Processing
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image to mutate.</param>
/// <param name="operations">The operations to perform on the source.</param>
/// <exception cref="ArgumentNullException">The source is null.</exception>
/// <exception cref="ArgumentNullException">The operations are null.</exception>
/// <exception cref="ObjectDisposedException">The source has been disposed.</exception>
/// <exception cref="ImageProcessingException">The processing operation failed.</exception>
public static void Mutate<TPixel>(this Image<TPixel> source, params IImageProcessor[] operations)
where TPixel : unmanaged, IPixel<TPixel>
=> Mutate(source, source.GetConfiguration(), operations);
@ -86,6 +108,11 @@ namespace SixLabors.ImageSharp.Processing
/// <param name="source">The image to mutate.</param>
/// <param name="configuration">The configuration which allows altering default behaviour or extending the library.</param>
/// <param name="operations">The operations to perform on the source.</param>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The source is null.</exception>
/// <exception cref="ArgumentNullException">The operations are null.</exception>
/// <exception cref="ObjectDisposedException">The source has been disposed.</exception>
/// <exception cref="ImageProcessingException">The processing operation failed.</exception>
public static void Mutate<TPixel>(this Image<TPixel> source, Configuration configuration, params IImageProcessor[] operations)
where TPixel : unmanaged, IPixel<TPixel>
{
@ -104,7 +131,11 @@ namespace SixLabors.ImageSharp.Processing
/// </summary>
/// <param name="source">The image to clone.</param>
/// <param name="operation">The operation to perform on the clone.</param>
/// <returns>The new <see cref="SixLabors.ImageSharp.Image"/>.</returns>
/// <returns>The new <see cref="Image"/>.</returns>
/// <exception cref="ArgumentNullException">The source is null.</exception>
/// <exception cref="ArgumentNullException">The operation is null.</exception>
/// <exception cref="ObjectDisposedException">The source has been disposed.</exception>
/// <exception cref="ImageProcessingException">The processing operation failed.</exception>
public static Image Clone(this Image source, Action<IImageProcessingContext> operation)
=> Clone(source, source.GetConfiguration(), operation);
@ -114,7 +145,12 @@ namespace SixLabors.ImageSharp.Processing
/// <param name="source">The image to clone.</param>
/// <param name="configuration">The configuration which allows altering default behaviour or extending the library.</param>
/// <param name="operation">The operation to perform on the clone.</param>
/// <returns>The new <see cref="SixLabors.ImageSharp.Image"/>.</returns>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The source is null.</exception>
/// <exception cref="ArgumentNullException">The operation is null.</exception>
/// <exception cref="ObjectDisposedException">The source has been disposed.</exception>
/// <exception cref="ImageProcessingException">The processing operation failed.</exception>
/// <returns>The new <see cref="Image"/>.</returns>
public static Image Clone(this Image source, Configuration configuration, Action<IImageProcessingContext> operation)
{
Guard.NotNull(configuration, nameof(configuration));
@ -133,7 +169,11 @@ namespace SixLabors.ImageSharp.Processing
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image to clone.</param>
/// <param name="operation">The operation to perform on the clone.</param>
/// <returns>The new <see cref="SixLabors.ImageSharp.Image{TPixel}"/></returns>
/// <exception cref="ArgumentNullException">The source is null.</exception>
/// <exception cref="ArgumentNullException">The operation is null.</exception>
/// <exception cref="ObjectDisposedException">The source has been disposed.</exception>
/// <exception cref="ImageProcessingException">The processing operation failed.</exception>
/// <returns>The new <see cref="Image{TPixel}"/>.</returns>
public static Image<TPixel> Clone<TPixel>(this Image<TPixel> source, Action<IImageProcessingContext> operation)
where TPixel : unmanaged, IPixel<TPixel>
=> Clone(source, source.GetConfiguration(), operation);
@ -145,7 +185,12 @@ namespace SixLabors.ImageSharp.Processing
/// <param name="source">The image to clone.</param>
/// <param name="configuration">The configuration which allows altering default behaviour or extending the library.</param>
/// <param name="operation">The operation to perform on the clone.</param>
/// <returns>The new <see cref="SixLabors.ImageSharp.Image{TPixel}"/></returns>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The source is null.</exception>
/// <exception cref="ArgumentNullException">The operation is null.</exception>
/// <exception cref="ObjectDisposedException">The source has been disposed.</exception>
/// <exception cref="ImageProcessingException">The processing operation failed.</exception>
/// <returns>The new <see cref="Image{TPixel}"/></returns>
public static Image<TPixel> Clone<TPixel>(this Image<TPixel> source, Configuration configuration, Action<IImageProcessingContext> operation)
where TPixel : unmanaged, IPixel<TPixel>
{
@ -167,7 +212,11 @@ namespace SixLabors.ImageSharp.Processing
/// <typeparam name="TPixel">The pixel format.</typeparam>
/// <param name="source">The image to clone.</param>
/// <param name="operations">The operations to perform on the clone.</param>
/// <returns>The new <see cref="SixLabors.ImageSharp.Image{TPixel}"/></returns>
/// <exception cref="ArgumentNullException">The source is null.</exception>
/// <exception cref="ArgumentNullException">The operations are null.</exception>
/// <exception cref="ObjectDisposedException">The source has been disposed.</exception>
/// <exception cref="ImageProcessingException">The processing operation failed.</exception>
/// <returns>The new <see cref="Image{TPixel}"/></returns>
public static Image<TPixel> Clone<TPixel>(this Image<TPixel> source, params IImageProcessor[] operations)
where TPixel : unmanaged, IPixel<TPixel>
=> Clone(source, source.GetConfiguration(), operations);
@ -179,7 +228,12 @@ namespace SixLabors.ImageSharp.Processing
/// <param name="source">The image to clone.</param>
/// <param name="configuration">The configuration which allows altering default behaviour or extending the library.</param>
/// <param name="operations">The operations to perform on the clone.</param>
/// <returns>The new <see cref="SixLabors.ImageSharp.Image{TPixel}"/></returns>
/// <exception cref="ArgumentNullException">The configuration is null.</exception>
/// <exception cref="ArgumentNullException">The source is null.</exception>
/// <exception cref="ArgumentNullException">The operations are null.</exception>
/// <exception cref="ObjectDisposedException">The source has been disposed.</exception>
/// <exception cref="ImageProcessingException">The processing operation failed.</exception>
/// <returns>The new <see cref="Image{TPixel}"/></returns>
public static Image<TPixel> Clone<TPixel>(this Image<TPixel> source, Configuration configuration, params IImageProcessor[] operations)
where TPixel : unmanaged, IPixel<TPixel>
{
@ -200,6 +254,7 @@ namespace SixLabors.ImageSharp.Processing
/// </summary>
/// <param name="source">The image processing context.</param>
/// <param name="operations">The operations to perform on the source.</param>
/// <exception cref="ImageProcessingException">The processing operation failed.</exception>
/// <returns>The <see cref="IImageProcessor{TPixel}"/> to allow chaining of operations.</returns>
public static IImageProcessingContext ApplyProcessors(
this IImageProcessingContext source,

4
tests/ImageSharp.Tests/Formats/Bmp/BmpDecoderTests.cs

@ -394,10 +394,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Bmp
[Theory]
[WithFile(InvalidPaletteSize, PixelTypes.Rgba32)]
public void BmpDecoder_ThrowsImageFormatException_OnInvalidPaletteSize<TPixel>(TestImageProvider<TPixel> provider)
public void BmpDecoder_ThrowsInvalidImageContentException_OnInvalidPaletteSize<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
Assert.Throws<ImageFormatException>(() =>
Assert.Throws<InvalidImageContentException>(() =>
{
using (provider.GetImage(BmpDecoder))
{

4
tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Baseline.cs

@ -52,7 +52,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[Theory]
[WithFileCollection(nameof(UnrecoverableTestJpegs), PixelTypes.Rgba32)]
public void UnrecoverableImage_Throws_ImageFormatException<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> => Assert.Throws<ImageFormatException>(provider.GetImage);
public void UnrecoverableImage_Throws_InvalidImageContentException<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel> => Assert.Throws<InvalidImageContentException>(provider.GetImage);
}
}

2
tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.Chunks.cs

@ -72,7 +72,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
var decoder = new PngDecoder();
ImageFormatException exception =
Assert.Throws<ImageFormatException>(() => decoder.Decode<Rgb24>(null, memStream));
Assert.Throws<InvalidImageContentException>(() => decoder.Decode<Rgb24>(null, memStream));
Assert.Equal($"CRC Error. PNG {chunkName} chunk is corrupt!", exception.Message);
}

23
tests/ImageSharp.Tests/Formats/Png/PngDecoderTests.cs

@ -89,6 +89,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
TestImages.Png.Issue1014_5, TestImages.Png.Issue1014_6
};
public static readonly string[] TestImagesIssue1177 =
{
TestImages.Png.Issue1177_1,
TestImages.Png.Issue1177_2
};
[Theory]
[WithFileCollection(nameof(CommonTestImages), PixelTypes.Rgba32)]
public void Decode<TPixel>(TestImageProvider<TPixel> provider)
@ -243,6 +249,23 @@ namespace SixLabors.ImageSharp.Tests.Formats.Png
Assert.Null(ex);
}
[Theory]
[WithFileCollection(nameof(TestImagesIssue1177), PixelTypes.Rgba32)]
public void Issue1177<TPixel>(TestImageProvider<TPixel> provider)
where TPixel : unmanaged, IPixel<TPixel>
{
System.Exception ex = Record.Exception(
() =>
{
using (Image<TPixel> image = provider.GetImage(PngDecoder))
{
image.DebugSave(provider);
image.CompareToOriginal(provider, ImageComparer.Exact);
}
});
Assert.Null(ex);
}
[Theory]
[WithFile(TestImages.Png.Issue1127, PixelTypes.Rgba32)]
public void Issue1127<TPixel>(TestImageProvider<TPixel> provider)

1
tests/ImageSharp.Tests/Memory/DiscontiguousBuffers/MemoryGroupTests.cs

@ -152,6 +152,7 @@ namespace SixLabors.ImageSharp.Tests.Memory.DiscontiguousBuffers
public static TheoryData<long, int, long, int> GetBoundedSlice_ErrorData = new TheoryData<long, int, long, int>()
{
{ 300, 100, -1, 91 },
{ 300, 100, 110, 91 },
{ 42, 7, 0, 8 },
{ 42, 7, 1, 7 },

4
tests/ImageSharp.Tests/TestImages.cs

@ -95,6 +95,10 @@ namespace SixLabors.ImageSharp.Tests
public const string Issue1014_6 = "Png/issues/Issue_1014_6.png";
public const string Issue1127 = "Png/issues/Issue_1127.png";
// Issue 1177: https://github.com/SixLabors/ImageSharp/issues/1177
public const string Issue1177_1 = "Png/issues/Issue_1177_1.png";
public const string Issue1177_2 = "Png/issues/Issue_1177_2.png";
public static class Bad
{
// Odd chunk lengths

3
tests/Images/Input/Png/issues/Issue_1177_1.png

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:cef2be6012f4604f9f30b51273661058df0201be4de508235f372eb2304b2132
size 7023

3
tests/Images/Input/Png/issues/Issue_1177_2.png

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7067af724977e1ecd8fc761f50226eaaa9e9d4142be963b4edbbf0918b8eba1d
size 57125
Loading…
Cancel
Save