private static void TestPngEncoderCore <TPixel>( TestImageProvider <TPixel> provider, PngColorType pngColorType, PngFilterMethod pngFilterMethod, PngBitDepth bitDepth, PngInterlaceMode interlaceMode, PngCompressionLevel compressionLevel = PngCompressionLevel.DefaultCompression, int paletteSize = 255, bool appendPngColorType = false, bool appendPngFilterMethod = false, bool appendPixelType = false, bool appendCompressionLevel = false, bool appendPaletteSize = false, bool appendPngBitDepth = false, PngChunkFilter optimizeMethod = PngChunkFilter.None) where TPixel : unmanaged, IPixel <TPixel> { using (Image <TPixel> image = provider.GetImage()) { var encoder = new PngEncoder { ColorType = pngColorType, FilterMethod = pngFilterMethod, CompressionLevel = compressionLevel, BitDepth = bitDepth, Quantizer = new WuQuantizer(new QuantizerOptions { MaxColors = paletteSize }), InterlaceMethod = interlaceMode, ChunkFilter = optimizeMethod, }; string pngColorTypeInfo = appendPngColorType ? pngColorType.ToString() : string.Empty; string pngFilterMethodInfo = appendPngFilterMethod ? pngFilterMethod.ToString() : string.Empty; string compressionLevelInfo = appendCompressionLevel ? $"_C{compressionLevel}" : string.Empty; string paletteSizeInfo = appendPaletteSize ? $"_PaletteSize-{paletteSize}" : string.Empty; string pngBitDepthInfo = appendPngBitDepth ? bitDepth.ToString() : string.Empty; string pngInterlaceModeInfo = interlaceMode != PngInterlaceMode.None ? $"_{interlaceMode}" : string.Empty; string debugInfo = $"{pngColorTypeInfo}{pngFilterMethodInfo}{compressionLevelInfo}{paletteSizeInfo}{pngBitDepthInfo}{pngInterlaceModeInfo}"; string actualOutputFile = provider.Utility.SaveTestOutputFile(image, "png", encoder, debugInfo, appendPixelType); // Compare to the Magick reference decoder. IImageDecoder referenceDecoder = TestEnvironment.GetReferenceDecoder(actualOutputFile); // We compare using both our decoder and the reference decoder as pixel transformation // occurs within the encoder itself leaving the input image unaffected. // This means we are benefiting from testing our decoder also. using (var imageSharpImage = Image.Load <TPixel>(actualOutputFile, new PngDecoder())) using (var referenceImage = Image.Load <TPixel>(actualOutputFile, referenceDecoder)) { ImageComparer.Exact.VerifySimilarity(referenceImage, imageSharpImage); } } }
/// <summary> /// Initializes a new instance of the <see cref="ZlibDeflateStream"/> class. /// </summary> /// <param name="memoryAllocator">The memory allocator to use for buffer allocations.</param> /// <param name="stream">The stream to compress.</param> /// <param name="level">The compression level.</param> public ZlibDeflateStream(MemoryAllocator memoryAllocator, Stream stream, PngCompressionLevel level) { int compressionLevel = (int)level; this.rawStream = stream; // Write the zlib header : http://tools.ietf.org/html/rfc1950 // CMF(Compression Method and flags) // This byte is divided into a 4 - bit compression method and a // 4-bit information field depending on the compression method. // bits 0 to 3 CM Compression method // bits 4 to 7 CINFO Compression info // // 0 1 // +---+---+ // |CMF|FLG| // +---+---+ const int Cmf = 0x78; int flg = 218; // http://stackoverflow.com/a/2331025/277304 if (compressionLevel >= 5 && compressionLevel <= 6) { flg = 156; } else if (compressionLevel >= 3 && compressionLevel <= 4) { flg = 94; } else if (compressionLevel <= 2) { flg = 1; } // Just in case flg -= ((Cmf * 256) + flg) % 31; if (flg < 0) { flg += 31; } this.rawStream.WriteByte(Cmf); this.rawStream.WriteByte((byte)flg); this.deflateStream = new DeflaterOutputStream(memoryAllocator, this.rawStream, compressionLevel); }
public void WorksWithAllCompressionLevels <TPixel>(TestImageProvider <TPixel> provider, PngCompressionLevel compressionLevel) where TPixel : unmanaged, IPixel <TPixel> { foreach (PngInterlaceMode interlaceMode in InterlaceMode) { TestPngEncoderCore( provider, PngColorType.RgbWithAlpha, PngFilterMethod.Adaptive, PngBitDepth.Bit8, interlaceMode, compressionLevel, appendCompressionLevel: true); } }