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();
+ }
+}