Browse Source

(WIP) quality

pull/1706/head
Dmitry Pentin 5 years ago
parent
commit
eaeab7a03a
  1. 47
      src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
  2. 16
      src/ImageSharp/Formats/Jpeg/JpegMetadata.cs

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

@ -102,18 +102,9 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
// Compute number of components based on color type in options.
int componentCount = (this.colorType == JpegColorType.Luminance) ? 1 : 3;
// Initialize the quantization tables.
// TODO: Right now encoder writes both quantization tables for grayscale images - we shouldn't do that
int lumaQuality = Numerics.Clamp(this.luminanceQuality ?? jpegMetadata.LuminanceQuality, 1, 100);
Block8x8F luminanceQuantTable = Quantization.ScaleLuminanceTable(lumaQuality);
Block8x8F chrominanceQuantTable = default;
if (componentCount > 1)
{
int chromaQuality = Numerics.Clamp(this.chrominanceQuality ?? jpegMetadata.ChrominanceQuality, 1, 100);
this.subsample ??= chromaQuality >= 91 ? JpegSubsample.Ratio444 : JpegSubsample.Ratio420;
chrominanceQuantTable = Quantization.ScaleChrominanceTable(chromaQuality);
}
// Initialize the quantization tables.
this.InitQuantizationTables(componentCount, jpegMetadata, out Block8x8F luminanceQuantTable, out Block8x8F chrominanceQuantTable);
// Write the Start Of Image marker.
this.WriteApplicationHeader(metadata);
@ -651,5 +642,39 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
this.buffer[3] = (byte)(length & 0xff);
this.outputStream.Write(this.buffer, 0, 4);
}
/// <summary>
/// Initializes quntization tables.
/// </summary>
/// <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);
chrominanceQuantTable = default;
if (componentCount > 1)
{
int chromaQuality = Numerics.Clamp(
this.chrominanceQuality ?? metadata.ChrominanceQuality ?? DefaultQualityValue,
min: 1,
max: 100);
this.subsample ??= chromaQuality >= 91 ? JpegSubsample.Ratio444 : JpegSubsample.Ratio420;
chrominanceQuantTable = Quantization.ScaleChrominanceTable(chromaQuality);
}
}
}
}

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

@ -24,7 +24,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
/// <param name="other">The metadata to create an instance from.</param>
private JpegMetadata(JpegMetadata other)
{
this.Quality = other.Quality;
this.ColorType = other.ColorType;
this.LumaQuantizationTable = other.LumaQuantizationTable;
@ -56,7 +55,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
/// This value might not be accurate if it was calculated during jpeg decoding
/// with non-complient ITU quantization tables.
/// </remarks>
public int LuminanceQuality { get; set; }
public int? LuminanceQuality { get; set; }
/// <summary>
/// Gets or sets the jpeg chrominance quality.
@ -65,7 +64,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
/// This value might not be accurate if it was calculated during jpeg decoding
/// with non-complient ITU quantization tables.
/// </remarks>
public int ChrominanceQuality { get; set; }
public int? ChrominanceQuality { get; set; }
/// <summary>
/// Gets a value indicating whether jpeg luminance data was encoded using ITU complient quantization table.
@ -82,7 +81,16 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
/// </summary>
public int Quality
{
get => (int)Math.Round((this.LuminanceQuality + this.ChrominanceQuality) / 2f);
[Obsolete("This accessor will soon be deprecated. Use LuminanceQuality and ChrominanceQuality getters instead.", error: false)]
get
{
const int defaultQuality = 75;
int lumaQuality = this.LuminanceQuality ?? defaultQuality;
int chromaQuality = this.LuminanceQuality ?? lumaQuality;
return (int)Math.Round((lumaQuality + chromaQuality) / 2f);
}
set
{
this.LuminanceQuality = value;

Loading…
Cancel
Save