diff --git a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs index b58e99a10..cf21dd226 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegDecoderCore.cs +++ b/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; diff --git a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs index 593937b92..fea24111c 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs +++ b/src/ImageSharp/Formats/Jpeg/JpegEncoderCore.cs @@ -646,34 +646,66 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// /// Initializes quntization tables. /// + /// + /// 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 + /// /// Color components count. /// Jpeg metadata instance. /// Output luminance quantization table. /// Output chrominance quantization table. 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; } } } diff --git a/src/ImageSharp/Formats/Jpeg/JpegMetadata.cs b/src/ImageSharp/Formats/Jpeg/JpegMetadata.cs index 8b3332ef8..4a58c6946 100644 --- a/src/ImageSharp/Formats/Jpeg/JpegMetadata.cs +++ b/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 /// /// Would be null if jpeg was encoded using table from ITU spec /// - internal Block8x8? LumaQuantizationTable { get; set; } + internal Block8x8F? LuminanceQuantizationTable { get; set; } /// /// Gets or sets chrominance qunatization table derived from jpeg image. @@ -46,7 +46,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// /// Would be null if jpeg was encoded using table from ITU spec /// - internal Block8x8? ChromaQuantizationTable { get; set; } + internal Block8x8F? ChromaQuantizationTable { get; set; } /// /// Gets or sets the jpeg luminance quality. @@ -69,7 +69,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg /// /// Gets a value indicating whether jpeg luminance data was encoded using ITU complient quantization table. /// - public bool UsesStandardLuminanceTable => !this.LumaQuantizationTable.HasValue; + public bool UsesStandardLuminanceTable => !this.LuminanceQuantizationTable.HasValue; /// /// Gets a value indicating whether jpeg luminance data was encoded using ITU complient quantization table.