The intent of Optimal is to be a balanced trade-off between compression ratio and speed, but whereas DeflateStream, GZipStream, and ZLibStream all treat Optimal as such (using zlib's default setting for such a balanced tradeoff), Brotli treats Optimal the same as maximum compression, which is very slow. Especially now that maximum compression is expressible as CompressionLevel.SmallestSize, it's even more valuable for Optimal to represent that balanced tradeoff. Based on a variety of sources around the net and some local testing, I've changed the Optimal value from 11 to 4. This is also more important now that we've fixed the argument validation bug that allowed arbitrary numerical values to be passed through unvalidated (DeflateStream, GZipStream, and ZLibStream all properly validate).
{
case CompressionMode.Compress:
if (!stream.CanWrite)
+ {
throw new ArgumentException(SR.Stream_FalseCanWrite, nameof(stream));
+ }
+
+ _encoder.SetQuality(BrotliUtils.Quality_Default);
+ _encoder.SetWindow(BrotliUtils.WindowBits_Default);
break;
+
case CompressionMode.Decompress:
if (!stream.CanRead)
+ {
throw new ArgumentException(SR.Stream_FalseCanRead, nameof(stream));
+ }
break;
+
default:
throw new ArgumentException(SR.ArgumentOutOfRange_Enum, nameof(mode));
}
public const int WindowBits_Default = 22;
public const int WindowBits_Max = 24;
public const int Quality_Min = 0;
- public const int Quality_Default = 11;
+ public const int Quality_Default = 4;
public const int Quality_Max = 11;
public const int MaxInputSize = int.MaxValue - 515; // 515 is the max compressed extra bytes
internal static int GetQualityFromCompressionLevel(CompressionLevel compressionLevel) =>
compressionLevel switch
{
- CompressionLevel.Optimal => Quality_Default,
CompressionLevel.NoCompression => Quality_Min,
CompressionLevel.Fastest => 1,
+ CompressionLevel.Optimal => Quality_Default,
CompressionLevel.SmallestSize => Quality_Max,
_ => throw new ArgumentException(SR.ArgumentOutOfRange_Enum, nameof(compressionLevel))
};
/// <param name="stream">The stream to compress.</param>
/// <param name="compressionLevel">One of the enumeration values that indicates whether to emphasize speed or compression efficiency when compressing the stream.</param>
public BrotliStream(Stream stream, CompressionLevel compressionLevel) : this(stream, compressionLevel, leaveOpen: false) { }
+
/// <summary>Initializes a new instance of the <see cref="System.IO.Compression.BrotliStream" /> class by using the specified stream and compression level, and optionally leaves the stream open.</summary>
/// <param name="stream">The stream to compress.</param>
/// <param name="compressionLevel">One of the enumeration values that indicates whether to emphasize speed or compression efficiency when compressing the stream.</param>