mirror of https://github.com/SixLabors/ImageSharp
18 changed files with 222 additions and 269 deletions
@ -1,50 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using SixLabors.ImageSharp.IO; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats; |
|||
|
|||
/// <summary>
|
|||
/// Abstraction for shared internals for XXXDecoderCore implementations to be used with <see cref="ImageDecoderUtilities"/>.
|
|||
/// </summary>
|
|||
internal interface IImageDecoderInternals |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the general decoder options.
|
|||
/// </summary>
|
|||
DecoderOptions Options { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets the dimensions of the image being decoded.
|
|||
/// </summary>
|
|||
Size Dimensions { get; } |
|||
|
|||
/// <summary>
|
|||
/// Decodes the image from the specified stream.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
/// <param name="stream">The stream, where the image should be decoded from. Cannot be null.</param>
|
|||
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
|
|||
/// <exception cref="ArgumentNullException"><paramref name="stream"/> is null.</exception>
|
|||
/// <returns>The decoded image.</returns>
|
|||
/// <remarks>
|
|||
/// Cancellable synchronous method. In case of cancellation,
|
|||
/// an <see cref="OperationCanceledException"/> shall be thrown which will be handled on the call site.
|
|||
/// </remarks>
|
|||
Image<TPixel> Decode<TPixel>(BufferedReadStream stream, CancellationToken cancellationToken) |
|||
where TPixel : unmanaged, IPixel<TPixel>; |
|||
|
|||
/// <summary>
|
|||
/// Reads the raw image information from the specified stream.
|
|||
/// </summary>
|
|||
/// <param name="stream">The <see cref="BufferedReadStream"/> containing image data.</param>
|
|||
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
|
|||
/// <returns>The <see cref="ImageInfo"/>.</returns>
|
|||
/// <remarks>
|
|||
/// Cancellable synchronous method. In case of cancellation,
|
|||
/// an <see cref="OperationCanceledException"/> shall be thrown which will be handled on the call site.
|
|||
/// </remarks>
|
|||
ImageInfo Identify(BufferedReadStream stream, CancellationToken cancellationToken); |
|||
} |
|||
@ -0,0 +1,127 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using SixLabors.ImageSharp.IO; |
|||
using SixLabors.ImageSharp.Memory; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats; |
|||
|
|||
/// <summary>
|
|||
/// The base class for all stateful image decoders.
|
|||
/// </summary>
|
|||
internal abstract class ImageDecoderCore |
|||
{ |
|||
/// <summary>
|
|||
/// Initializes a new instance of the <see cref="ImageDecoderCore"/> class.
|
|||
/// </summary>
|
|||
/// <param name="options">The general decoder options.</param>
|
|||
protected ImageDecoderCore(DecoderOptions options) |
|||
=> this.Options = options; |
|||
|
|||
/// <summary>
|
|||
/// Gets the general decoder options.
|
|||
/// </summary>
|
|||
public DecoderOptions Options { get; } |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets the dimensions of the image being decoded.
|
|||
/// </summary>
|
|||
public Size Dimensions { get; protected internal set; } |
|||
|
|||
/// <summary>
|
|||
/// Reads the raw image information from the specified stream.
|
|||
/// </summary>
|
|||
/// <param name="configuration">The shared configuration.</param>
|
|||
/// <param name="stream">The <see cref="Stream" /> containing image data.</param>
|
|||
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
|
|||
/// <returns>The <see cref="ImageInfo" />.</returns>
|
|||
/// <exception cref="InvalidImageContentException">Thrown if the encoded image contains errors.</exception>
|
|||
public ImageInfo Identify( |
|||
Configuration configuration, |
|||
Stream stream, |
|||
CancellationToken cancellationToken) |
|||
{ |
|||
using BufferedReadStream bufferedReadStream = new(configuration, stream, cancellationToken); |
|||
|
|||
try |
|||
{ |
|||
return this.Identify(bufferedReadStream, cancellationToken); |
|||
} |
|||
catch (InvalidMemoryOperationException ex) |
|||
{ |
|||
throw new InvalidImageContentException(this.Dimensions, ex); |
|||
} |
|||
catch (Exception) |
|||
{ |
|||
throw; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Decodes the image from the specified stream to an <see cref="Image{TPixel}" /> of a specific pixel type.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
/// <param name="configuration">The shared configuration.</param>
|
|||
/// <param name="stream">The <see cref="Stream" /> containing image data.</param>
|
|||
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
|
|||
/// <returns>The <see cref="Image{TPixel}" />.</returns>
|
|||
/// <exception cref="InvalidImageContentException">Thrown if the encoded image contains errors.</exception>
|
|||
public Image<TPixel> Decode<TPixel>( |
|||
Configuration configuration, |
|||
Stream stream, |
|||
CancellationToken cancellationToken) |
|||
where TPixel : unmanaged, IPixel<TPixel> |
|||
{ |
|||
// Test may pass a BufferedReadStream in order to monitor EOF hits, if so, use the existing instance.
|
|||
BufferedReadStream bufferedReadStream = |
|||
stream as BufferedReadStream ?? new BufferedReadStream(configuration, stream, cancellationToken); |
|||
|
|||
try |
|||
{ |
|||
return this.Decode<TPixel>(bufferedReadStream, cancellationToken); |
|||
} |
|||
catch (InvalidMemoryOperationException ex) |
|||
{ |
|||
throw new InvalidImageContentException(this.Dimensions, ex); |
|||
} |
|||
catch (Exception) |
|||
{ |
|||
throw; |
|||
} |
|||
finally |
|||
{ |
|||
if (bufferedReadStream != stream) |
|||
{ |
|||
bufferedReadStream.Dispose(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Reads the raw image information from the specified stream.
|
|||
/// </summary>
|
|||
/// <param name="stream">The <see cref="BufferedReadStream"/> containing image data.</param>
|
|||
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
|
|||
/// <returns>The <see cref="ImageInfo"/>.</returns>
|
|||
/// <remarks>
|
|||
/// Cancellable synchronous method. In case of cancellation,
|
|||
/// an <see cref="OperationCanceledException"/> shall be thrown which will be handled on the call site.
|
|||
/// </remarks>
|
|||
protected abstract ImageInfo Identify(BufferedReadStream stream, CancellationToken cancellationToken); |
|||
|
|||
/// <summary>
|
|||
/// Decodes the image from the specified stream.
|
|||
/// </summary>
|
|||
/// <typeparam name="TPixel">The pixel format.</typeparam>
|
|||
/// <param name="stream">The stream, where the image should be decoded from. Cannot be null.</param>
|
|||
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
|
|||
/// <exception cref="ArgumentNullException"><paramref name="stream"/> is null.</exception>
|
|||
/// <returns>The decoded image.</returns>
|
|||
/// <remarks>
|
|||
/// Cancellable synchronous method. In case of cancellation, an <see cref="OperationCanceledException"/> shall
|
|||
/// be thrown which will be handled on the call site.
|
|||
/// </remarks>
|
|||
protected abstract Image<TPixel> Decode<TPixel>(BufferedReadStream stream, CancellationToken cancellationToken) |
|||
where TPixel : unmanaged, IPixel<TPixel>; |
|||
} |
|||
@ -1,81 +0,0 @@ |
|||
// Copyright (c) Six Labors.
|
|||
// Licensed under the Six Labors Split License.
|
|||
|
|||
using SixLabors.ImageSharp.IO; |
|||
using SixLabors.ImageSharp.Memory; |
|||
using SixLabors.ImageSharp.PixelFormats; |
|||
|
|||
namespace SixLabors.ImageSharp.Formats; |
|||
|
|||
/// <summary>
|
|||
/// Utility methods for <see cref="IImageDecoderInternals"/>.
|
|||
/// </summary>
|
|||
internal static class ImageDecoderUtilities |
|||
{ |
|||
internal static ImageInfo Identify( |
|||
this IImageDecoderInternals decoder, |
|||
Configuration configuration, |
|||
Stream stream, |
|||
CancellationToken cancellationToken) |
|||
{ |
|||
using BufferedReadStream bufferedReadStream = new(configuration, stream, cancellationToken); |
|||
|
|||
try |
|||
{ |
|||
return decoder.Identify(bufferedReadStream, cancellationToken); |
|||
} |
|||
catch (InvalidMemoryOperationException ex) |
|||
{ |
|||
throw new InvalidImageContentException(decoder.Dimensions, ex); |
|||
} |
|||
catch (Exception) |
|||
{ |
|||
throw; |
|||
} |
|||
} |
|||
|
|||
internal static Image<TPixel> Decode<TPixel>( |
|||
this IImageDecoderInternals decoder, |
|||
Configuration configuration, |
|||
Stream stream, |
|||
CancellationToken cancellationToken) |
|||
where TPixel : unmanaged, IPixel<TPixel> |
|||
=> decoder.Decode<TPixel>(configuration, stream, DefaultLargeImageExceptionFactory, cancellationToken); |
|||
|
|||
internal static Image<TPixel> Decode<TPixel>( |
|||
this IImageDecoderInternals decoder, |
|||
Configuration configuration, |
|||
Stream stream, |
|||
Func<InvalidMemoryOperationException, Size, InvalidImageContentException> largeImageExceptionFactory, |
|||
CancellationToken cancellationToken) |
|||
where TPixel : unmanaged, IPixel<TPixel> |
|||
{ |
|||
// Test may pass a BufferedReadStream in order to monitor EOF hits, if so, use the existing instance.
|
|||
BufferedReadStream bufferedReadStream = stream as BufferedReadStream ?? new BufferedReadStream(configuration, stream, cancellationToken); |
|||
|
|||
try |
|||
{ |
|||
return decoder.Decode<TPixel>(bufferedReadStream, cancellationToken); |
|||
} |
|||
catch (InvalidMemoryOperationException ex) |
|||
{ |
|||
throw largeImageExceptionFactory(ex, decoder.Dimensions); |
|||
} |
|||
catch (Exception) |
|||
{ |
|||
throw; |
|||
} |
|||
finally |
|||
{ |
|||
if (bufferedReadStream != stream) |
|||
{ |
|||
bufferedReadStream.Dispose(); |
|||
} |
|||
} |
|||
} |
|||
|
|||
private static InvalidImageContentException DefaultLargeImageExceptionFactory( |
|||
InvalidMemoryOperationException memoryOperationException, |
|||
Size dimensions) => |
|||
new(dimensions, memoryOperationException); |
|||
} |
|||
Loading…
Reference in new issue