Browse Source

Encoder now uses appropriate quality or provied quantization tables

pull/1706/head
Dmitry Pentin 5 years ago
parent
commit
3fdefa7aef
  1. 4
      src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs
  2. 66
      src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
  3. 8
      src/ImageSharp/Formats/Jpeg/JpegMetadata.cs

4
src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs

@ -835,7 +835,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
// so we save it in the metadata
if (!Quantization.EstimateLuminanceQuality(ref table, out int quality))
{
jpegMetadata.LumaQuantizationTable = table.RoundAsInt16Block();
jpegMetadata.LuminanceQuantizationTable = table;
}
jpegMetadata.LuminanceQuality = quality;
@ -850,7 +850,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
// so we save it in the metadata
if (!Quantization.EstimateChrominanceQuality(ref table, out int quality))
{
jpegMetadata.ChromaQuantizationTable = table.RoundAsInt16Block();
jpegMetadata.ChromaQuantizationTable = table;
}
jpegMetadata.ChrominanceQuality = quality;

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

@ -646,34 +646,66 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
/// <summary>
/// Initializes quntization tables.
/// </summary>
/// <remarks>
/// We take quality values in a hierarchical order:
/// 1. Check if encoder has set quality
/// 2. Check if metadata has special table for encoding
/// 3. Check if metadata has set quality
/// 4. Take default quality value - 75
/// </remarks>
/// <param name="componentCount">Color components count.</param>
/// <param name="metadata">Jpeg metadata instance.</param>
/// <param name="luminanceQuantTable">Output luminance quantization table.</param>
/// <param name="chrominanceQuantTable">Output chrominance quantization table.</param>
private void InitQuantizationTables(int componentCount, JpegMetadata metadata, out Block8x8F luminanceQuantTable, out Block8x8F chrominanceQuantTable)
{
// We take quality values in a hierarchical order:
// 1. Check if encoder has set quality
// 2. Check if metadata has special table for encoding
// 3. Check if metadata has set quality
// 4. Take default quality value - 75
int lumaQuality = Numerics.Clamp(
this.luminanceQuality ?? metadata.LuminanceQuality ?? DefaultQualityValue,
min: 1,
max: 100);
luminanceQuantTable = Quantization.ScaleLuminanceTable(lumaQuality);
// encoder quality
if (this.luminanceQuality.HasValue)
{
int lumaQuality = Numerics.Clamp(this.luminanceQuality.Value, 1, 100);
luminanceQuantTable = Quantization.ScaleLuminanceTable(lumaQuality);
}
// non-standard table
else if (metadata.LuminanceQuantizationTable.HasValue)
{
luminanceQuantTable = metadata.LuminanceQuantizationTable.Value;
}
// metadata or default quality
else
{
int lumaQuality = Numerics.Clamp(metadata.LuminanceQuality ?? DefaultQualityValue, 1, 100);
luminanceQuantTable = Quantization.ScaleLuminanceTable(lumaQuality);
}
chrominanceQuantTable = default;
if (componentCount > 1)
{
int chromaQuality = Numerics.Clamp(
this.chrominanceQuality ?? metadata.ChrominanceQuality ?? DefaultQualityValue,
min: 1,
max: 100);
int chromaQuality;
this.subsample ??= chromaQuality >= 91 ? JpegSubsample.Ratio444 : JpegSubsample.Ratio420;
// encoder quality
if (this.chrominanceQuality.HasValue)
{
chromaQuality = Numerics.Clamp(this.chrominanceQuality.Value, 1, 100);
chrominanceQuantTable = Quantization.ScaleLuminanceTable(chromaQuality);
}
// non-standard table
else if (metadata.ChromaQuantizationTable.HasValue)
{
chromaQuality = metadata.ChrominanceQuality.Value;
chrominanceQuantTable = metadata.ChromaQuantizationTable.Value;
}
// metadata or default quality
else
{
chromaQuality = Numerics.Clamp(metadata.ChrominanceQuality ?? DefaultQualityValue, 1, 100);
chrominanceQuantTable = Quantization.ScaleChrominanceTable(chromaQuality);
}
chrominanceQuantTable = Quantization.ScaleChrominanceTable(chromaQuality);
this.subsample = chromaQuality >= 91 ? JpegSubsample.Ratio444 : JpegSubsample.Ratio420;
}
}
}

8
src/ImageSharp/Formats/Jpeg/JpegMetadata.cs

@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
{
this.ColorType = other.ColorType;
this.LumaQuantizationTable = other.LumaQuantizationTable;
this.LuminanceQuantizationTable = other.LuminanceQuantizationTable;
this.ChromaQuantizationTable = other.ChromaQuantizationTable;
this.LuminanceQuality = other.LuminanceQuality;
this.ChrominanceQuality = other.ChrominanceQuality;
@ -38,7 +38,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
/// <remarks>
/// Would be null if jpeg was encoded using table from ITU spec
/// </remarks>
internal Block8x8? LumaQuantizationTable { get; set; }
internal Block8x8F? LuminanceQuantizationTable { get; set; }
/// <summary>
/// Gets or sets chrominance qunatization table derived from jpeg image.
@ -46,7 +46,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
/// <remarks>
/// Would be null if jpeg was encoded using table from ITU spec
/// </remarks>
internal Block8x8? ChromaQuantizationTable { get; set; }
internal Block8x8F? ChromaQuantizationTable { get; set; }
/// <summary>
/// Gets or sets the jpeg luminance quality.
@ -69,7 +69,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
/// <summary>
/// Gets a value indicating whether jpeg luminance data was encoded using ITU complient quantization table.
/// </summary>
public bool UsesStandardLuminanceTable => !this.LumaQuantizationTable.HasValue;
public bool UsesStandardLuminanceTable => !this.LuminanceQuantizationTable.HasValue;
/// <summary>
/// Gets a value indicating whether jpeg luminance data was encoded using ITU complient quantization table.

Loading…
Cancel
Save