Browse Source

Moved encode method choice to the JpegEncoderCore

pull/1632/head
Dmitry Pentin 5 years ago
parent
commit
7e0a317461
  1. 41
      src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs
  2. 35
      src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs

41
src/ImageSharp/Formats/Jpeg/Components/Encoder/HuffmanScanEncoder.cs

@ -85,7 +85,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder
/// <param name="luminanceQuantTable">Luminance quantization table provided by the callee</param>
/// <param name="chrominanceQuantTable">Chrominance quantization table provided by the callee</param>
/// <param name="cancellationToken">The token to monitor for cancellation.</param>
private void Encode444<TPixel>(Image<TPixel> pixels, ref Block8x8F luminanceQuantTable, ref Block8x8F chrominanceQuantTable, CancellationToken cancellationToken)
public void Encode444<TPixel>(Image<TPixel> pixels, ref Block8x8F luminanceQuantTable, ref Block8x8F chrominanceQuantTable, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>
{
var unzig = ZigZag.CreateUnzigTable();
@ -129,6 +129,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder
ref unzig);
}
}
// Pad the last byte with 1's.
this.Emit(0x7f, 7);
this.target.Write(this.emitBuffer, 0, this.emitLen);
}
/// <summary>
@ -140,7 +144,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder
/// <param name="luminanceQuantTable">Luminance quantization table provided by the callee</param>
/// <param name="chrominanceQuantTable">Chrominance quantization table provided by the callee</param>
/// <param name="cancellationToken">The token to monitor for cancellation.</param>
private void Encode420<TPixel>(Image<TPixel> pixels, ref Block8x8F luminanceQuantTable, ref Block8x8F chrominanceQuantTable, CancellationToken cancellationToken)
public void Encode420<TPixel>(Image<TPixel> pixels, ref Block8x8F luminanceQuantTable, ref Block8x8F chrominanceQuantTable, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>
{
// TODO: Need a JpegScanEncoder<TPixel> class or struct that encapsulates the scan-encoding implementation. (Similar to JpegScanDecoder.)
@ -199,6 +203,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder
ref unzig);
}
}
// Pad the last byte with 1's.
this.Emit(0x7f, 7);
this.target.Write(this.emitBuffer, 0, this.emitLen);
}
@ -209,7 +217,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder
/// <param name="pixels">The pixel accessor providing access to the image pixels.</param>
/// <param name="luminanceQuantTable">Luminance quantization table provided by the callee</param>
/// <param name="cancellationToken">The token to monitor for cancellation.</param>
private void EncodeGrayscale<TPixel>(Image<TPixel> pixels, ref Block8x8F luminanceQuantTable, CancellationToken cancellationToken)
public void EncodeGrayscale<TPixel>(Image<TPixel> pixels, ref Block8x8F luminanceQuantTable, CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>
{
var unzig = ZigZag.CreateUnzigTable();
@ -239,33 +247,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Encoder
ref unzig);
}
}
}
public void WriteStartOfScan<TPixel>(
Image<TPixel> image,
JpegColorType? colorType,
JpegSubsample? subsample,
ref Block8x8F luminanceQuantTable,
ref Block8x8F chrominanceTable,
CancellationToken cancellationToken)
where TPixel : unmanaged, IPixel<TPixel>
{
if (colorType == JpegColorType.Luminance)
{
this.EncodeGrayscale(image, ref luminanceQuantTable, cancellationToken);
}
else
{
switch (subsample)
{
case JpegSubsample.Ratio444:
this.Encode444(image, ref luminanceQuantTable, ref chrominanceTable, cancellationToken);
break;
case JpegSubsample.Ratio420:
this.Encode420(image, ref luminanceQuantTable, ref chrominanceTable, cancellationToken);
break;
}
}
// Pad the last byte with 1's.
this.Emit(0x7f, 7);

35
src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs

@ -86,9 +86,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
private readonly int? quality;
/// <summary>
/// Gets or sets the subsampling method to use.
/// Component count.
/// </summary>
private readonly JpegColorType? colorType;
private readonly int componentCount;
/// <summary>
/// The output stream. All attempted writes after the first error become no-ops.
@ -103,7 +103,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
{
this.quality = options.Quality;
this.subsample = options.Subsample;
this.colorType = options.ColorType;
this.componentCount = (options.ColorType == JpegColorType.Luminance) ? 1 : 3;
}
/// <summary>
@ -129,9 +129,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
this.outputStream = stream;
ImageMetadata metadata = image.Metadata;
// Compute number of components based on color type in options.
int componentCount = (this.colorType == JpegColorType.Luminance) ? 1 : 3;
// System.Drawing produces identical output for jpegs with a quality parameter of 0 and 1.
int qlty = Numerics.Clamp(this.quality ?? metadata.GetJpegMetadata().Quality, 1, 100);
this.subsample ??= qlty >= 91 ? JpegSubsample.Ratio444 : JpegSubsample.Ratio420;
@ -153,7 +150,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
Block8x8F luminanceQuantTable = default;
Block8x8F chrominanceQuantTable = default;
InitQuantizationTable(0, scale, ref luminanceQuantTable);
if (componentCount > 1)
if (this.componentCount > 1)
{
InitQuantizationTable(1, scale, ref chrominanceQuantTable);
}
@ -177,13 +174,23 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
this.WriteStartOfScan(image, componentCount, cancellationToken);
// Write the scan compressed data.
new HuffmanScanEncoder(stream).WriteStartOfScan(
image,
this.colorType,
this.subsample,
ref luminanceQuantTable,
ref chrominanceQuantTable,
cancellationToken);
var scanEncoder = new HuffmanScanEncoder(stream);
if (this.componentCount == 1)
{
scanEncoder.EncodeGrayscale(image, ref luminanceQuantTable, cancellationToken);
}
else
{
switch (subsample)
{
case JpegSubsample.Ratio444:
scanEncoder.Encode444(image, ref luminanceQuantTable, ref chrominanceQuantTable, cancellationToken);
break;
case JpegSubsample.Ratio420:
scanEncoder.Encode420(image, ref luminanceQuantTable, ref chrominanceQuantTable, cancellationToken);
break;
}
}
// Write the End Of Image marker.
this.buffer[0] = JpegConstants.Markers.XFF;

Loading…
Cancel
Save