diff --git a/src/ImageSharp/Formats/Jpeg/IJpegEncoderOptions.cs b/src/ImageSharp/Formats/Jpeg/IJpegEncoderOptions.cs
deleted file mode 100644
index b7e6d5d614..0000000000
--- a/src/ImageSharp/Formats/Jpeg/IJpegEncoderOptions.cs
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) Six Labors.
-// Licensed under the Six Labors Split License.
-
-namespace SixLabors.ImageSharp.Formats.Jpeg;
-
-///
-/// Encoder for writing the data image to a stream in jpeg format.
-///
-internal interface IJpegEncoderOptions
-{
- ///
- /// Gets or sets the quality, that will be used to encode the image. Quality
- /// index must be between 0 and 100 (compression from max to min).
- /// Defaults to 75.
- ///
- public int? Quality { get; set; }
-
- ///
- /// Gets or sets the component encoding mode.
- ///
- ///
- /// Interleaved encoding mode encodes all color components in a single scan.
- /// Non-interleaved encoding mode encodes each color component in a separate scan.
- ///
- public bool? Interleaved { get; set; }
-
- ///
- /// Gets or sets jpeg color for encoding.
- ///
- public JpegEncodingColor? ColorType { get; set; }
-}
diff --git a/src/ImageSharp/Formats/Jpeg/JpegEncoder.cs b/src/ImageSharp/Formats/Jpeg/JpegEncoder.cs
index 28d095eedc..fb48d2b443 100644
--- a/src/ImageSharp/Formats/Jpeg/JpegEncoder.cs
+++ b/src/ImageSharp/Formats/Jpeg/JpegEncoder.cs
@@ -1,21 +1,24 @@
// Copyright (c) Six Labors.
// Licensed under the Six Labors Split License.
-using SixLabors.ImageSharp.PixelFormats;
-
namespace SixLabors.ImageSharp.Formats.Jpeg;
///
/// Encoder for writing the data image to a stream in jpeg format.
///
-public sealed class JpegEncoder : IImageEncoder, IJpegEncoderOptions
+public sealed class JpegEncoder : ImageEncoder
{
///
/// Backing field for .
///
private int? quality;
- ///
+ ///
+ /// Gets or sets the quality, that will be used to encode the image. Quality
+ /// index must be between 0 and 100 (compression from max to min).
+ /// Defaults to 75.
+ ///
+ /// Quality factor must be in [1..100] range.
public int? Quality
{
get => this.quality;
@@ -30,10 +33,18 @@ public sealed class JpegEncoder : IImageEncoder, IJpegEncoderOptions
}
}
- ///
+ ///
+ /// Gets or sets the component encoding mode.
+ ///
+ ///
+ /// Interleaved encoding mode encodes all color components in a single scan.
+ /// Non-interleaved encoding mode encodes each color component in a separate scan.
+ ///
public bool? Interleaved { get; set; }
- ///
+ ///
+ /// Gets or sets jpeg color for encoding.
+ ///
public JpegEncodingColor? ColorType { get; set; }
///
@@ -42,10 +53,9 @@ public sealed class JpegEncoder : IImageEncoder, IJpegEncoderOptions
/// The pixel format.
/// The to encode from.
/// The to encode the image data to.
- public void Encode(Image image, Stream stream)
- where TPixel : unmanaged, IPixel
+ public override void Encode(Image image, Stream stream)
{
- var encoder = new JpegEncoderCore(this);
+ JpegEncoderCore encoder = new(this);
encoder.Encode(image, stream);
}
@@ -57,10 +67,9 @@ public sealed class JpegEncoder : IImageEncoder, IJpegEncoderOptions
/// The to encode the image data to.
/// The token to monitor for cancellation requests.
/// A representing the asynchronous operation.
- public Task EncodeAsync(Image image, Stream stream, CancellationToken cancellationToken)
- where TPixel : unmanaged, IPixel
+ public override Task EncodeAsync(Image image, Stream stream, CancellationToken cancellationToken)
{
- var encoder = new JpegEncoderCore(this);
+ JpegEncoderCore encoder = new(this);
return encoder.EncodeAsync(image, stream, cancellationToken);
}
}
diff --git a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
index 83c2e27e91..e915b74bc3 100644
--- a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
+++ b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
@@ -29,7 +29,7 @@ internal sealed unsafe partial class JpegEncoderCore : IImageEncoderInternals
///
private readonly byte[] buffer = new byte[20];
- private readonly IJpegEncoderOptions options;
+ private readonly JpegEncoder encoder;
///
/// The output stream. All attempted writes after the first error become no-ops.
@@ -39,9 +39,9 @@ internal sealed unsafe partial class JpegEncoderCore : IImageEncoderInternals
///
/// Initializes a new instance of the class.
///
- /// The options.
- public JpegEncoderCore(IJpegEncoderOptions options)
- => this.options = options;
+ /// The parent encoder.
+ public JpegEncoderCore(JpegEncoder encoder)
+ => this.encoder = encoder;
public Block8x8F[] QuantizationTables { get; } = new Block8x8F[4];
@@ -71,8 +71,8 @@ internal sealed unsafe partial class JpegEncoderCore : IImageEncoderInternals
JpegMetadata jpegMetadata = metadata.GetJpegMetadata();
JpegFrameConfig frameConfig = this.GetFrameConfig(jpegMetadata);
- bool interleaved = this.options.Interleaved ?? jpegMetadata.Interleaved ?? true;
- using var frame = new JpegFrame(image, frameConfig, interleaved);
+ bool interleaved = this.encoder.Interleaved ?? jpegMetadata.Interleaved ?? true;
+ using JpegFrame frame = new(image, frameConfig, interleaved);
// Write the Start Of Image marker.
this.WriteStartOfImage();
@@ -96,14 +96,14 @@ internal sealed unsafe partial class JpegEncoderCore : IImageEncoderInternals
this.WriteStartOfFrame(image.Width, image.Height, frameConfig);
// Write the Huffman tables.
- var scanEncoder = new HuffmanScanEncoder(frame.BlocksPerMcu, stream);
+ HuffmanScanEncoder scanEncoder = new(frame.BlocksPerMcu, stream);
this.WriteDefineHuffmanTables(frameConfig.HuffmanTables, scanEncoder);
// Write the quantization tables.
- this.WriteDefineQuantizationTables(frameConfig.QuantizationTables, this.options.Quality, jpegMetadata);
+ this.WriteDefineQuantizationTables(frameConfig.QuantizationTables, this.encoder.Quality, jpegMetadata);
// Write scans with actual pixel data
- using var spectralConverter = new SpectralConverter(frame, image, this.QuantizationTables);
+ using SpectralConverter spectralConverter = new(frame, image, this.QuantizationTables);
this.WriteHuffmanScans(frame, frameConfig, spectralConverter, scanEncoder, cancellationToken);
// Write the End Of Image marker.
@@ -172,6 +172,9 @@ internal sealed unsafe partial class JpegEncoderCore : IImageEncoderInternals
///
/// Writes the Define Huffman Table marker and tables.
///
+ /// The table configuration.
+ /// The scan encoder.
+ /// is .
private void WriteDefineHuffmanTables(JpegHuffmanTableConfig[] tableConfigs, HuffmanScanEncoder scanEncoder)
{
if (tableConfigs is null)
@@ -203,6 +206,7 @@ internal sealed unsafe partial class JpegEncoderCore : IImageEncoderInternals
///
/// Writes the APP14 marker to indicate the image is in RGB color space.
///
+ /// The color transform byte.
private void WriteApp14Marker(byte colorTransform)
{
this.WriteMarkerHeader(JpegConstants.Markers.APP14, 2 + Components.Decoder.AdobeMarker.Length);
@@ -498,6 +502,9 @@ internal sealed unsafe partial class JpegEncoderCore : IImageEncoderInternals
///
/// Writes the Start Of Frame (Baseline) marker.
///
+ /// The frame width.
+ /// The frame height.
+ /// The frame configuration.
private void WriteStartOfFrame(int width, int height, JpegFrameConfig frame)
{
JpegComponentConfig[] components = frame.Components;
@@ -536,6 +543,7 @@ internal sealed unsafe partial class JpegEncoderCore : IImageEncoderInternals
///
/// Writes the StartOfScan marker.
///
+ /// The collecction of component configuration items.
private void WriteStartOfScan(Span components)
{
// Write the SOS (Start Of Scan) marker "\xff\xda" followed by 12 bytes:
@@ -588,7 +596,18 @@ internal sealed unsafe partial class JpegEncoderCore : IImageEncoderInternals
///
/// Writes scans for given config.
///
- private void WriteHuffmanScans(JpegFrame frame, JpegFrameConfig frameConfig, SpectralConverter spectralConverter, HuffmanScanEncoder encoder, CancellationToken cancellationToken)
+ /// The type of pixel format.
+ /// The current frame.
+ /// The frame configuration.
+ /// The spectral converter.
+ /// The scan encoder.
+ /// The cancellation token.
+ private void WriteHuffmanScans(
+ JpegFrame frame,
+ JpegFrameConfig frameConfig,
+ SpectralConverter spectralConverter,
+ HuffmanScanEncoder encoder,
+ CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel
{
if (frame.Components.Length == 1)
@@ -696,7 +715,7 @@ internal sealed unsafe partial class JpegEncoderCore : IImageEncoderInternals
private JpegFrameConfig GetFrameConfig(JpegMetadata metadata)
{
- JpegEncodingColor color = this.options.ColorType ?? metadata.ColorType ?? JpegEncodingColor.YCbCrRatio420;
+ JpegEncodingColor color = this.encoder.ColorType ?? metadata.ColorType ?? JpegEncodingColor.YCbCrRatio420;
JpegFrameConfig frameConfig = Array.Find(
FrameConfigs,
cfg => cfg.EncodingColor == color);