mirror of https://github.com/SixLabors/ImageSharp
7 changed files with 279 additions and 0 deletions
@ -0,0 +1,30 @@ |
|||||
|
// Copyright (c) Six Labors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using System; |
||||
|
using System.IO; |
||||
|
using System.Threading; |
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Formats.Bmp |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Image decoder for generating an image out of a Windows bitmap stream.
|
||||
|
/// </summary>
|
||||
|
public class BmpDecoder2 : ImageDecoder<BmpDecoderOptions> |
||||
|
{ |
||||
|
/// <inheritdoc/>
|
||||
|
public override Image<TPixel> DecodeSpecialized<TPixel>(BmpDecoderOptions options, Stream stream, CancellationToken cancellationToken) |
||||
|
{ |
||||
|
throw new NotImplementedException(); |
||||
|
} |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
public override Image DecodeSpecialized(BmpDecoderOptions options, Stream stream, CancellationToken cancellationToken) |
||||
|
=> this.DecodeSpecialized<Rgba32>(options, stream, cancellationToken); |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
public override IImageInfo IdentifySpecialized(BmpDecoderOptions options, Stream stream, CancellationToken cancellationToken) |
||||
|
=> throw new NotImplementedException(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
// Copyright (c) Six Labors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Formats.Bmp |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Image decoder options for decoding Windows bitmap streams.
|
||||
|
/// </summary>
|
||||
|
public sealed class BmpDecoderOptions : ISpecializedDecoderOptions |
||||
|
{ |
||||
|
/// <inheritdoc/>
|
||||
|
public DecoderOptions GeneralOptions { get; set; } = new(); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the value indicating how to deal with skipped pixels,
|
||||
|
/// which can occur during decoding run length encoded bitmaps.
|
||||
|
/// </summary>
|
||||
|
public RleSkippedPixelHandling RleSkippedPixelHandling { get; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,33 @@ |
|||||
|
// Copyright (c) Six Labors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Formats |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Provides general configuration options for decoding image formats.
|
||||
|
/// </summary>
|
||||
|
public sealed class DecoderOptions |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Gets or sets a custom Configuration instance to be used by the image processing pipeline.
|
||||
|
/// </summary>
|
||||
|
public Configuration Configuration { get; set; } = Configuration.Default; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets or sets the target size to decode the image into.
|
||||
|
/// </summary>
|
||||
|
public Size? TargetSize { get; set; } = null; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets or sets a value indicating whether to ignore encoded metadata when decoding.
|
||||
|
/// </summary>
|
||||
|
public bool SkipMetadata { get; set; } = false; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets or sets the number of image frames to decode.
|
||||
|
/// Leave <see langword="null"/> to decode all frames.
|
||||
|
/// </summary>
|
||||
|
// supported decoders may handle this internally but we will fallback to removeing additional frames after decode.
|
||||
|
public int? MaxFrames { get; set; } = null; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,37 @@ |
|||||
|
// Copyright (c) Six Labors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using System.IO; |
||||
|
using System.Threading; |
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Formats |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Encapsulates properties and methods required for decoding an image from a stream.
|
||||
|
/// </summary>
|
||||
|
public interface IImageDecoder2 |
||||
|
{ |
||||
|
/// <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="options">The general decoder options.</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="ImageFormatException">Thrown if the encoded image contains errors.</exception>
|
||||
|
Image<TPixel> Decode<TPixel>(DecoderOptions options, Stream stream, CancellationToken cancellationToken) |
||||
|
where TPixel : unmanaged, IPixel<TPixel>; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Decodes the image from the specified stream to an <see cref="Image"/>.
|
||||
|
/// </summary>
|
||||
|
/// <param name="options">The general decoder options.</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"/>.</returns>
|
||||
|
/// <exception cref="ImageFormatException">Thrown if the encoded image contains errors.</exception>
|
||||
|
Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
// Copyright (c) Six Labors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using System.IO; |
||||
|
using System.Threading; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Formats |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Encapsulates methods used for detecting the raw image information without fully decoding it.
|
||||
|
/// </summary>
|
||||
|
public interface IImageInfoDetector2 |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Reads the raw image information from the specified stream.
|
||||
|
/// </summary>
|
||||
|
/// <param name="options">The general decoder options.</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="IImageInfo"/> object.</returns>
|
||||
|
/// <exception cref="ImageFormatException">Thrown if the encoded image contains errors.</exception>
|
||||
|
IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
// Copyright (c) Six Labors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Formats |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Provides specialized configuration options for decoding image formats.
|
||||
|
/// </summary>
|
||||
|
public interface ISpecializedDecoderOptions |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Gets or sets the general decoder options.
|
||||
|
/// </summary>
|
||||
|
DecoderOptions GeneralOptions { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,119 @@ |
|||||
|
// Copyright (c) Six Labors.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
|
||||
|
using System.IO; |
||||
|
using System.Threading; |
||||
|
using SixLabors.ImageSharp.PixelFormats; |
||||
|
using SixLabors.ImageSharp.Processing; |
||||
|
|
||||
|
namespace SixLabors.ImageSharp.Formats |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// The base class for all image decoders.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="T">The type of specialized decoder options.</typeparam>
|
||||
|
public abstract class ImageDecoder<T> : IImageInfoDetector2, IImageDecoder2 |
||||
|
where T : ISpecializedDecoderOptions, new() |
||||
|
{ |
||||
|
/// <inheritdoc/>
|
||||
|
public IImageInfo Identify(DecoderOptions options, Stream stream, CancellationToken cancellationToken) |
||||
|
{ |
||||
|
T specializedOptions = new() { GeneralOptions = options }; |
||||
|
return this.IdentifySpecialized(specializedOptions, stream, cancellationToken); |
||||
|
} |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
public Image<TPixel> Decode<TPixel>(DecoderOptions options, Stream stream, CancellationToken cancellationToken) |
||||
|
where TPixel : unmanaged, IPixel<TPixel> |
||||
|
{ |
||||
|
T specializedOptions = new() { GeneralOptions = options }; |
||||
|
Image<TPixel> image = this.DecodeSpecialized<TPixel>(specializedOptions, stream, cancellationToken); |
||||
|
|
||||
|
Resize(options, image); |
||||
|
|
||||
|
return image; |
||||
|
} |
||||
|
|
||||
|
/// <inheritdoc/>
|
||||
|
public Image Decode(DecoderOptions options, Stream stream, CancellationToken cancellationToken) |
||||
|
{ |
||||
|
T specializedOptions = new() { GeneralOptions = options }; |
||||
|
Image image = this.DecodeSpecialized(specializedOptions, stream, cancellationToken); |
||||
|
|
||||
|
Resize(options, image); |
||||
|
|
||||
|
return image; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Reads the raw image information from the specified stream.
|
||||
|
/// </summary>
|
||||
|
/// <param name="options">The specialized decoder options.</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="IImageInfo"/> object.</returns>
|
||||
|
/// <exception cref="ImageFormatException">Thrown if the encoded image contains errors.</exception>
|
||||
|
public abstract IImageInfo IdentifySpecialized(T options, Stream stream, CancellationToken cancellationToken); |
||||
|
|
||||
|
/// <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="options">The specialized decoder options.</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="ImageFormatException">Thrown if the encoded image contains errors.</exception>
|
||||
|
public abstract Image<TPixel> DecodeSpecialized<TPixel>(T options, Stream stream, CancellationToken cancellationToken) |
||||
|
where TPixel : unmanaged, IPixel<TPixel>; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Decodes the image from the specified stream to an <see cref="Image"/> of a specific pixel type.
|
||||
|
/// </summary>
|
||||
|
/// <param name="options">The specialized decoder options.</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="ImageFormatException">Thrown if the encoded image contains errors.</exception>
|
||||
|
public abstract Image DecodeSpecialized(T options, Stream stream, CancellationToken cancellationToken); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Performs a resize operation against the decoded image. If the target size is not set, or the image size
|
||||
|
/// already matches the target size, the image is untouched.
|
||||
|
/// </summary>
|
||||
|
/// <param name="options">The decoder options.</param>
|
||||
|
/// <param name="image">The decoded image.</param>
|
||||
|
protected static void Resize(DecoderOptions options, Image image) |
||||
|
{ |
||||
|
if (ShouldResize(options, image)) |
||||
|
{ |
||||
|
ResizeOptions resizeOptions = new() |
||||
|
{ |
||||
|
Size = options.TargetSize.Value, |
||||
|
Sampler = KnownResamplers.Box, |
||||
|
Mode = ResizeMode.Max |
||||
|
}; |
||||
|
|
||||
|
image.Mutate(x => x.Resize(resizeOptions)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Determines whether the decoded image should be resized.
|
||||
|
/// </summary>
|
||||
|
/// <param name="options">The decoder options.</param>
|
||||
|
/// <param name="image">The decoded image.</param>
|
||||
|
/// <returns><see langword="true"/> if the image should be resized, otherwise; <see langword="false"/>.</returns>
|
||||
|
private static bool ShouldResize(DecoderOptions options, Image image) |
||||
|
{ |
||||
|
if (options.TargetSize is null) |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
Size targetSize = options.TargetSize.Value; |
||||
|
Size currentSize = image.Size(); |
||||
|
return currentSize.Width != targetSize.Width && currentSize.Height != targetSize.Height; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue