diff --git a/src/ImageSharp/Formats/Png/IPngDecoderOptions.cs b/src/ImageSharp/Formats/Png/IPngDecoderOptions.cs deleted file mode 100644 index 4b09c5b1c..000000000 --- a/src/ImageSharp/Formats/Png/IPngDecoderOptions.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -namespace SixLabors.ImageSharp.Formats.Png -{ - /// - /// The options for decoding png images - /// - internal interface IPngDecoderOptions - { - /// - /// Gets a value indicating whether the metadata should be ignored when the image is being decoded. - /// - bool IgnoreMetadata { get; } - } -} diff --git a/src/ImageSharp/Formats/Png/PngDecoder.cs b/src/ImageSharp/Formats/Png/PngDecoder.cs index 0b233848a..a48b281c5 100644 --- a/src/ImageSharp/Formats/Png/PngDecoder.cs +++ b/src/ImageSharp/Formats/Png/PngDecoder.cs @@ -10,24 +10,24 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// Decoder for generating an image out of a png encoded stream. /// - public sealed class PngDecoder : IImageDecoder, IPngDecoderOptions, IImageInfoDetector + public sealed class PngDecoder : ImageDecoder { /// - public bool IgnoreMetadata { get; set; } - - /// - public Image Decode(Configuration configuration, Stream stream, CancellationToken cancellationToken) - where TPixel : unmanaged, IPixel + public override Image DecodeSpecialized(PngDecoderOptions options, Stream stream, CancellationToken cancellationToken) { - PngDecoderCore decoder = new(configuration, this); - return decoder.Decode(configuration, stream, cancellationToken); + PngDecoderCore decoder = new(options); + Image image = decoder.Decode(options.GeneralOptions.Configuration, stream, cancellationToken); + + Resize(options.GeneralOptions, image); + + return image; } - /// - public Image Decode(Configuration configuration, Stream stream, CancellationToken cancellationToken) + /// + public override Image DecodeSpecialized(PngDecoderOptions options, Stream stream, CancellationToken cancellationToken) { - PngDecoderCore decoder = new(configuration, true); - IImageInfo info = decoder.Identify(configuration, stream, cancellationToken); + PngDecoderCore decoder = new(options, true); + IImageInfo info = decoder.Identify(options.GeneralOptions.Configuration, stream, cancellationToken); stream.Position = 0; PngMetadata meta = info.Metadata.GetPngMetadata(); @@ -39,49 +39,50 @@ namespace SixLabors.ImageSharp.Formats.Png if (bits == PngBitDepth.Bit16) { return !meta.HasTransparency - ? this.Decode(configuration, stream, cancellationToken) - : this.Decode(configuration, stream, cancellationToken); + ? this.DecodeSpecialized(options, stream, cancellationToken) + : this.DecodeSpecialized(options, stream, cancellationToken); } return !meta.HasTransparency - ? this.Decode(configuration, stream, cancellationToken) - : this.Decode(configuration, stream, cancellationToken); + ? this.DecodeSpecialized(options, stream, cancellationToken) + : this.DecodeSpecialized(options, stream, cancellationToken); case PngColorType.Rgb: if (bits == PngBitDepth.Bit16) { return !meta.HasTransparency - ? this.Decode(configuration, stream, cancellationToken) - : this.Decode(configuration, stream, cancellationToken); + ? this.DecodeSpecialized(options, stream, cancellationToken) + : this.DecodeSpecialized(options, stream, cancellationToken); } return !meta.HasTransparency - ? this.Decode(configuration, stream, cancellationToken) - : this.Decode(configuration, stream, cancellationToken); + ? this.DecodeSpecialized(options, stream, cancellationToken) + : this.DecodeSpecialized(options, stream, cancellationToken); case PngColorType.Palette: - return this.Decode(configuration, stream, cancellationToken); + return this.DecodeSpecialized(options, stream, cancellationToken); case PngColorType.GrayscaleWithAlpha: return (bits == PngBitDepth.Bit16) - ? this.Decode(configuration, stream, cancellationToken) - : this.Decode(configuration, stream, cancellationToken); + ? this.DecodeSpecialized(options, stream, cancellationToken) + : this.DecodeSpecialized(options, stream, cancellationToken); case PngColorType.RgbWithAlpha: return (bits == PngBitDepth.Bit16) - ? this.Decode(configuration, stream, cancellationToken) - : this.Decode(configuration, stream, cancellationToken); + ? this.DecodeSpecialized(options, stream, cancellationToken) + : this.DecodeSpecialized(options, stream, cancellationToken); default: - return this.Decode(configuration, stream, cancellationToken); + return this.DecodeSpecialized(options, stream, cancellationToken); } } /// - public IImageInfo Identify(Configuration configuration, Stream stream, CancellationToken cancellationToken) + public override IImageInfo IdentifySpecialized(PngDecoderOptions options, Stream stream, CancellationToken cancellationToken) { - PngDecoderCore decoder = new(configuration, this); - return decoder.Identify(configuration, stream, cancellationToken); + Guard.NotNull(stream, nameof(stream)); + + return new PngDecoderCore(options).Identify(options.GeneralOptions.Configuration, stream, cancellationToken); } } } diff --git a/src/ImageSharp/Formats/Png/PngDecoderCore.cs b/src/ImageSharp/Formats/Png/PngDecoderCore.cs index f46b5058a..ae01a2f56 100644 --- a/src/ImageSharp/Formats/Png/PngDecoderCore.cs +++ b/src/ImageSharp/Formats/Png/PngDecoderCore.cs @@ -4,7 +4,6 @@ using System; using System.Buffers; using System.Buffers.Binary; -using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Runtime.CompilerServices; @@ -28,17 +27,22 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// Performs the png decoding operation. /// - internal sealed class PngDecoderCore : IImageDecoderInternals + internal sealed class PngDecoderCore : IImageDecoderInternals { /// /// Reusable buffer. /// private readonly byte[] buffer = new byte[4]; + /// + /// The general decoder options. + /// + private readonly Configuration configuration; + /// /// Gets or sets a value indicating whether the metadata should be ignored when the image is being decoded. /// - private readonly bool ignoreMetadata; + private readonly bool skipMetadata; /// /// Gets or sets a value indicating whether to read the IHDR and tRNS chunks only. @@ -118,29 +122,26 @@ namespace SixLabors.ImageSharp.Formats.Png /// /// Initializes a new instance of the class. /// - /// The configuration. /// The decoder options. - public PngDecoderCore(Configuration configuration, IPngDecoderOptions options) + public PngDecoderCore(PngDecoderOptions options) { - this.Configuration = configuration ?? Configuration.Default; - this.memoryAllocator = this.Configuration.MemoryAllocator; - this.ignoreMetadata = options.IgnoreMetadata; + this.configuration = options.GeneralOptions.Configuration; + this.memoryAllocator = this.configuration.MemoryAllocator; + this.skipMetadata = options.GeneralOptions.SkipMetadata; } - internal PngDecoderCore(Configuration configuration, bool colorMetadataOnly) + internal PngDecoderCore(PngDecoderOptions options, bool colorMetadataOnly) { - this.Configuration = configuration ?? Configuration.Default; - this.memoryAllocator = this.Configuration.MemoryAllocator; + this.configuration = options.GeneralOptions.Configuration; + this.memoryAllocator = this.configuration.MemoryAllocator; this.colorMetadataOnly = colorMetadataOnly; - this.ignoreMetadata = true; + this.skipMetadata = true; } /// - public Configuration Configuration { get; } + public PngDecoderOptions Options { get; } - /// - /// Gets the dimensions of the image. - /// + /// public Size Dimensions => new(this.header.Width, this.header.Height); /// @@ -199,7 +200,7 @@ namespace SixLabors.ImageSharp.Formats.Png this.ReadInternationalTextChunk(metadata, chunk.Data.GetSpan()); break; case PngChunkType.Exif: - if (!this.ignoreMetadata) + if (!this.skipMetadata) { byte[] exifData = new byte[chunk.Length]; chunk.Data.GetSpan().CopyTo(exifData); @@ -336,7 +337,7 @@ namespace SixLabors.ImageSharp.Formats.Png break; } - if (!this.ignoreMetadata) + if (!this.skipMetadata) { byte[] exifData = new byte[chunk.Length]; chunk.Data.GetSpan().CopyTo(exifData); @@ -469,7 +470,7 @@ namespace SixLabors.ImageSharp.Formats.Png where TPixel : unmanaged, IPixel { image = Image.CreateUninitialized( - this.Configuration, + this.configuration, this.header.Width, this.header.Height, metadata); @@ -485,7 +486,7 @@ namespace SixLabors.ImageSharp.Formats.Png this.previousScanline?.Dispose(); this.scanline?.Dispose(); this.previousScanline = this.memoryAllocator.Allocate(this.bytesPerScanline, AllocationOptions.Clean); - this.scanline = this.Configuration.MemoryAllocator.Allocate(this.bytesPerScanline, AllocationOptions.Clean); + this.scanline = this.configuration.MemoryAllocator.Allocate(this.bytesPerScanline, AllocationOptions.Clean); } /// @@ -798,7 +799,7 @@ namespace SixLabors.ImageSharp.Formats.Png case PngColorType.Rgb: PngScanlineProcessor.ProcessRgbScanline( - this.Configuration, + this.configuration, this.header, scanlineSpan, rowSpan, @@ -812,7 +813,7 @@ namespace SixLabors.ImageSharp.Formats.Png case PngColorType.RgbWithAlpha: PngScanlineProcessor.ProcessRgbaScanline( - this.Configuration, + this.configuration, this.header, scanlineSpan, rowSpan, @@ -1001,7 +1002,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// The containing the data. private void ReadTextChunk(ImageMetadata baseMetadata, PngMetadata metadata, ReadOnlySpan data) { - if (this.ignoreMetadata) + if (this.skipMetadata) { return; } @@ -1036,7 +1037,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// The containing the data. private void ReadCompressedTextChunk(ImageMetadata baseMetadata, PngMetadata metadata, ReadOnlySpan data) { - if (this.ignoreMetadata) + if (this.skipMetadata) { return; } @@ -1222,10 +1223,10 @@ namespace SixLabors.ImageSharp.Formats.Png { fixed (byte* compressedDataBase = compressedData) { - using (IMemoryOwner destBuffer = this.memoryAllocator.Allocate(this.Configuration.StreamProcessingBufferSize)) + using (IMemoryOwner destBuffer = this.memoryAllocator.Allocate(this.configuration.StreamProcessingBufferSize)) using (var memoryStreamOutput = new MemoryStream(compressedData.Length)) using (var memoryStreamInput = new UnmanagedMemoryStream(compressedDataBase, compressedData.Length)) - using (var bufferedStream = new BufferedReadStream(this.Configuration, memoryStreamInput)) + using (var bufferedStream = new BufferedReadStream(this.configuration, memoryStreamInput)) using (var inflateStream = new ZlibInflateStream(bufferedStream)) { Span destUncompressedData = destBuffer.GetSpan(); @@ -1324,7 +1325,7 @@ namespace SixLabors.ImageSharp.Formats.Png /// The containing the data. private void ReadInternationalTextChunk(ImageMetadata metadata, ReadOnlySpan data) { - if (this.ignoreMetadata) + if (this.skipMetadata) { return; } @@ -1563,7 +1564,7 @@ namespace SixLabors.ImageSharp.Formats.Png private IMemoryOwner ReadChunkData(int length) { // We rent the buffer here to return it afterwards in Decode() - IMemoryOwner buffer = this.Configuration.MemoryAllocator.Allocate(length, AllocationOptions.Clean); + IMemoryOwner buffer = this.configuration.MemoryAllocator.Allocate(length, AllocationOptions.Clean); this.currentStream.Read(buffer.GetSpan(), 0, length); diff --git a/src/ImageSharp/Formats/Png/PngDecoderOptions.cs b/src/ImageSharp/Formats/Png/PngDecoderOptions.cs new file mode 100644 index 000000000..f8b3364bb --- /dev/null +++ b/src/ImageSharp/Formats/Png/PngDecoderOptions.cs @@ -0,0 +1,14 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +namespace SixLabors.ImageSharp.Formats.Png +{ + /// + /// Configuration options for decoding Png images. + /// + public class PngDecoderOptions : ISpecializedDecoderOptions + { + /// + public DecoderOptions GeneralOptions { get; set; } = new(); + } +} diff --git a/src/ImageSharp/Formats/Tga/ITgaDecoderOptions.cs b/src/ImageSharp/Formats/Tga/ITgaDecoderOptions.cs deleted file mode 100644 index 240b8b9b3..000000000 --- a/src/ImageSharp/Formats/Tga/ITgaDecoderOptions.cs +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (c) Six Labors. -// Licensed under the Apache License, Version 2.0. - -namespace SixLabors.ImageSharp.Formats.Tga -{ - /// - /// The options for decoding tga images. Currently empty, but this may change in the future. - /// - internal interface ITgaDecoderOptions - { - } -} diff --git a/src/ImageSharp/Formats/Tga/TgaDecoder.cs b/src/ImageSharp/Formats/Tga/TgaDecoder.cs index bb0a0d548..60616f9cd 100644 --- a/src/ImageSharp/Formats/Tga/TgaDecoder.cs +++ b/src/ImageSharp/Formats/Tga/TgaDecoder.cs @@ -10,28 +10,29 @@ namespace SixLabors.ImageSharp.Formats.Tga /// /// Image decoder for Truevision TGA images. /// - public sealed class TgaDecoder : IImageDecoder, ITgaDecoderOptions, IImageInfoDetector + public sealed class TgaDecoder : ImageDecoder { /// - public Image Decode(Configuration configuration, Stream stream, CancellationToken cancellationToken) - where TPixel : unmanaged, IPixel + public override Image DecodeSpecialized(TgaDecoderOptions options, Stream stream, CancellationToken cancellationToken) { - Guard.NotNull(stream, nameof(stream)); + TgaDecoderCore decoder = new(options); + Image image = decoder.Decode(options.GeneralOptions.Configuration, stream, cancellationToken); + + Resize(options.GeneralOptions, image); - var decoder = new TgaDecoderCore(configuration, this); - return decoder.Decode(configuration, stream, cancellationToken); + return image; } - /// - public Image Decode(Configuration configuration, Stream stream, CancellationToken cancellationToken) - => this.Decode(configuration, stream, cancellationToken); + /// + public override Image DecodeSpecialized(TgaDecoderOptions options, Stream stream, CancellationToken cancellationToken) + => this.DecodeSpecialized(options, stream, cancellationToken); /// - public IImageInfo Identify(Configuration configuration, Stream stream, CancellationToken cancellationToken) + public override IImageInfo IdentifySpecialized(TgaDecoderOptions options, Stream stream, CancellationToken cancellationToken) { Guard.NotNull(stream, nameof(stream)); - return new TgaDecoderCore(configuration, this).Identify(configuration, stream, cancellationToken); + return new TgaDecoderCore(options).Identify(options.GeneralOptions.Configuration, stream, cancellationToken); } } } diff --git a/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs b/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs index d101ccd94..421c0224a 100644 --- a/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs +++ b/src/ImageSharp/Formats/Tga/TgaDecoderCore.cs @@ -15,13 +15,18 @@ namespace SixLabors.ImageSharp.Formats.Tga /// /// Performs the tga decoding operation. /// - internal sealed class TgaDecoderCore : IImageDecoderInternals + internal sealed class TgaDecoderCore : IImageDecoderInternals { /// /// A scratch buffer to reduce allocations. /// private readonly byte[] scratchBuffer = new byte[4]; + /// + /// General configuration options. + /// + private readonly Configuration configuration; + /// /// The metadata. /// @@ -47,11 +52,6 @@ namespace SixLabors.ImageSharp.Formats.Tga /// private BufferedReadStream currentStream; - /// - /// The bitmap decoder options. - /// - private readonly ITgaDecoderOptions options; - /// /// Indicates whether there is a alpha channel present. /// @@ -60,22 +60,19 @@ namespace SixLabors.ImageSharp.Formats.Tga /// /// Initializes a new instance of the class. /// - /// The configuration. /// The options. - public TgaDecoderCore(Configuration configuration, ITgaDecoderOptions options) + public TgaDecoderCore(TgaDecoderOptions options) { - this.Configuration = configuration; - this.memoryAllocator = configuration.MemoryAllocator; - this.options = options; + this.Options = options; + this.configuration = options.GeneralOptions.Configuration; + this.memoryAllocator = this.configuration.MemoryAllocator; } /// - public Configuration Configuration { get; } + public TgaDecoderOptions Options { get; } - /// - /// Gets the dimensions of the image. - /// - public Size Dimensions => new Size(this.fileHeader.Width, this.fileHeader.Height); + /// + public Size Dimensions => new(this.fileHeader.Width, this.fileHeader.Height); /// public Image Decode(BufferedReadStream stream, CancellationToken cancellationToken) @@ -87,7 +84,7 @@ namespace SixLabors.ImageSharp.Formats.Tga this.currentStream.Skip(this.fileHeader.IdLength); // Parse the color map, if present. - if (this.fileHeader.ColorMapType != 0 && this.fileHeader.ColorMapType != 1) + if (this.fileHeader.ColorMapType is not 0 and not 1) { TgaThrowHelper.ThrowNotSupportedException($"Unknown tga colormap type {this.fileHeader.ColorMapType} found"); } @@ -97,7 +94,7 @@ namespace SixLabors.ImageSharp.Formats.Tga throw new UnknownImageFormatException("Width or height cannot be 0"); } - var image = Image.CreateUninitialized(this.Configuration, this.fileHeader.Width, this.fileHeader.Height, this.metadata); + var image = Image.CreateUninitialized(this.configuration, this.fileHeader.Width, this.fileHeader.Height, this.metadata); Buffer2D pixels = image.GetRootFramePixelBuffer(); if (this.fileHeader.ColorMapType == 1) @@ -451,11 +448,11 @@ namespace SixLabors.ImageSharp.Formats.Tga if (this.fileHeader.ImageType == TgaImageType.BlackAndWhite) { - PixelOperations.Instance.FromLa16Bytes(this.Configuration, rowSpan, pixelSpan, width); + PixelOperations.Instance.FromLa16Bytes(this.configuration, rowSpan, pixelSpan, width); } else { - PixelOperations.Instance.FromBgra5551Bytes(this.Configuration, rowSpan, pixelSpan, width); + PixelOperations.Instance.FromBgra5551Bytes(this.configuration, rowSpan, pixelSpan, width); } } } @@ -655,7 +652,7 @@ namespace SixLabors.ImageSharp.Formats.Tga { this.currentStream.Read(row); Span pixelSpan = pixels.DangerousGetRowSpan(y); - PixelOperations.Instance.FromL8Bytes(this.Configuration, row, pixelSpan, width); + PixelOperations.Instance.FromL8Bytes(this.configuration, row, pixelSpan, width); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -682,7 +679,7 @@ namespace SixLabors.ImageSharp.Formats.Tga { this.currentStream.Read(row); Span pixelSpan = pixels.DangerousGetRowSpan(y); - PixelOperations.Instance.FromBgr24Bytes(this.Configuration, row, pixelSpan, width); + PixelOperations.Instance.FromBgr24Bytes(this.configuration, row, pixelSpan, width); } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -701,7 +698,7 @@ namespace SixLabors.ImageSharp.Formats.Tga { this.currentStream.Read(row); Span pixelSpan = pixels.DangerousGetRowSpan(y); - PixelOperations.Instance.FromBgra32Bytes(this.Configuration, row, pixelSpan, width); + PixelOperations.Instance.FromBgra32Bytes(this.configuration, row, pixelSpan, width); } [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/ImageSharp/Formats/Tga/TgaDecoderOptions.cs b/src/ImageSharp/Formats/Tga/TgaDecoderOptions.cs new file mode 100644 index 000000000..abce31c66 --- /dev/null +++ b/src/ImageSharp/Formats/Tga/TgaDecoderOptions.cs @@ -0,0 +1,14 @@ +// Copyright (c) Six Labors. +// Licensed under the Apache License, Version 2.0. + +namespace SixLabors.ImageSharp.Formats.Tga +{ + /// + /// Configuration options for decoding Png images. + /// + public class TgaDecoderOptions : ISpecializedDecoderOptions + { + /// + public DecoderOptions GeneralOptions { get; set; } = new(); + } +}