Browse Source

Fixed encoder metadata usage

pull/1706/head
Dmitry Pentin 5 years ago
parent
commit
376d190d2a
  1. 32
      src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs
  2. 80
      src/ImageSharp/Formats/Jpeg/JpegMetadata.cs

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

@ -23,11 +23,6 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
/// </summary> /// </summary>
internal sealed unsafe class JpegEncoderCore : IImageEncoderInternals internal sealed unsafe class JpegEncoderCore : IImageEncoderInternals
{ {
/// <summary>
/// Default JPEG encoding quality for both luminance and chominance tables.
/// </summary>
private const int DefaultQualityValue = 75;
/// <summary> /// <summary>
/// The number of quantization tables. /// The number of quantization tables.
/// </summary> /// </summary>
@ -659,50 +654,29 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
/// <param name="chrominanceQuantTable">Output chrominance quantization table.</param> /// <param name="chrominanceQuantTable">Output chrominance quantization table.</param>
private void InitQuantizationTables(int componentCount, JpegMetadata metadata, out Block8x8F luminanceQuantTable, out Block8x8F chrominanceQuantTable) private void InitQuantizationTables(int componentCount, JpegMetadata metadata, out Block8x8F luminanceQuantTable, out Block8x8F chrominanceQuantTable)
{ {
// encoder quality
if (this.luminanceQuality.HasValue) if (this.luminanceQuality.HasValue)
{ {
int lumaQuality = Numerics.Clamp(this.luminanceQuality.Value, 1, 100); int lumaQuality = Numerics.Clamp(this.luminanceQuality.Value, 1, 100);
luminanceQuantTable = Quantization.ScaleLuminanceTable(lumaQuality); luminanceQuantTable = Quantization.ScaleLuminanceTable(lumaQuality);
} }
// non-standard table
else if (metadata.LuminanceQuantizationTable.HasValue)
{
luminanceQuantTable = metadata.LuminanceQuantizationTable.Value;
}
// metadata or default quality
else else
{ {
int lumaQuality = Numerics.Clamp(metadata.LuminanceQuality ?? DefaultQualityValue, 1, 100); luminanceQuantTable = metadata.LuminanceQuantizationTable;
luminanceQuantTable = Quantization.ScaleLuminanceTable(lumaQuality);
} }
chrominanceQuantTable = default; chrominanceQuantTable = default;
if (componentCount > 1) if (componentCount > 1)
{ {
int chromaQuality; int chromaQuality;
// encoder quality
if (this.chrominanceQuality.HasValue) if (this.chrominanceQuality.HasValue)
{ {
chromaQuality = Numerics.Clamp(this.chrominanceQuality.Value, 1, 100); chromaQuality = Numerics.Clamp(this.chrominanceQuality.Value, 1, 100);
chrominanceQuantTable = Quantization.ScaleLuminanceTable(chromaQuality); 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 else
{ {
chromaQuality = Numerics.Clamp(metadata.ChrominanceQuality ?? DefaultQualityValue, 1, 100); chromaQuality = metadata.ChrominanceQuality;
chrominanceQuantTable = Quantization.ScaleChrominanceTable(chromaQuality); chrominanceQuantTable = metadata.ChromaQuantizationTable;
} }
this.subsample = chromaQuality >= 91 ? JpegSubsample.Ratio444 : JpegSubsample.Ratio420; this.subsample = chromaQuality >= 91 ? JpegSubsample.Ratio444 : JpegSubsample.Ratio420;

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

@ -11,6 +11,17 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
/// </summary> /// </summary>
public class JpegMetadata : IDeepCloneable public class JpegMetadata : IDeepCloneable
{ {
/// <summary>
/// Default JPEG quality for both luminance and chominance tables.
/// </summary>
private const int DefaultQualityValue = 75;
private Block8x8F? lumaQuantTable;
private Block8x8F? chromaQuantTable;
private int? lumaQuality;
private int? chromaQuality;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="JpegMetadata"/> class. /// Initializes a new instance of the <see cref="JpegMetadata"/> class.
/// </summary> /// </summary>
@ -33,20 +44,40 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
} }
/// <summary> /// <summary>
/// Gets or sets luminance qunatization table derived from jpeg image. /// Gets or sets luminance qunatization table for jpeg image.
/// </summary> /// </summary>
/// <remarks> internal Block8x8F LuminanceQuantizationTable
/// Would be null if jpeg was encoded using table from ITU spec {
/// </remarks> get
internal Block8x8F? LuminanceQuantizationTable { get; set; } {
if (this.lumaQuantTable.HasValue)
{
return this.lumaQuantTable.Value;
}
return Quantization.ScaleLuminanceTable(this.LuminanceQuality);
}
set => this.lumaQuantTable = value;
}
/// <summary> /// <summary>
/// Gets or sets chrominance qunatization table derived from jpeg image. /// Gets or sets chrominance qunatization table for jpeg image.
/// </summary> /// </summary>
/// <remarks> internal Block8x8F ChromaQuantizationTable
/// Would be null if jpeg was encoded using table from ITU spec {
/// </remarks> get
internal Block8x8F? ChromaQuantizationTable { get; set; } {
if (this.chromaQuantTable.HasValue)
{
return this.chromaQuantTable.Value;
}
return Quantization.ScaleChrominanceTable(this.ChrominanceQuality);
}
set => this.chromaQuantTable = value;
}
/// <summary> /// <summary>
/// Gets or sets the jpeg luminance quality. /// Gets or sets the jpeg luminance quality.
@ -55,7 +86,11 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
/// This value might not be accurate if it was calculated during jpeg decoding /// This value might not be accurate if it was calculated during jpeg decoding
/// with non-complient ITU quantization tables. /// with non-complient ITU quantization tables.
/// </remarks> /// </remarks>
public int? LuminanceQuality { get; set; } public int LuminanceQuality
{
get => this.lumaQuality ?? DefaultQualityValue;
set => this.lumaQuality = value;
}
/// <summary> /// <summary>
/// Gets or sets the jpeg chrominance quality. /// Gets or sets the jpeg chrominance quality.
@ -64,30 +99,21 @@ namespace SixLabors.ImageSharp.Formats.Jpeg
/// This value might not be accurate if it was calculated during jpeg decoding /// This value might not be accurate if it was calculated during jpeg decoding
/// with non-complient ITU quantization tables. /// with non-complient ITU quantization tables.
/// </remarks> /// </remarks>
public int? ChrominanceQuality { get; set; } public int ChrominanceQuality
{
/// <summary> get => this.chromaQuality ?? DefaultQualityValue;
/// Gets a value indicating whether jpeg luminance data was encoded using ITU complient quantization table. set => this.chromaQuality = value;
/// </summary> }
public bool UsesStandardLuminanceTable => !this.LuminanceQuantizationTable.HasValue;
/// <summary>
/// Gets a value indicating whether jpeg luminance data was encoded using ITU complient quantization table.
/// </summary>
public bool UsesStandardChrominanceTable => !this.ChromaQuantizationTable.HasValue;
/// <summary> /// <summary>
/// Gets or sets the encoded quality. /// Gets or sets the encoded quality.
/// </summary> /// </summary>
public int Quality public int Quality
{ {
[Obsolete("This accessor will soon be deprecated. Use LuminanceQuality and ChrominanceQuality getters instead.", error: false)]
get get
{ {
const int defaultQuality = 75; int lumaQuality = this.lumaQuality ?? DefaultQualityValue;
int chromaQuality = this.chromaQuality ?? lumaQuality;
int lumaQuality = this.LuminanceQuality ?? defaultQuality;
int chromaQuality = this.LuminanceQuality ?? lumaQuality;
return (int)Math.Round((lumaQuality + chromaQuality) / 2f); return (int)Math.Round((lumaQuality + chromaQuality) / 2f);
} }

Loading…
Cancel
Save